---
title: "Poll a bulk-enrichment batch"
method: GET
path: "/api/v1/enrichment/contacts/bulk/{batch_id}"
tags: ["Enrichment"]
---

# Poll a bulk-enrichment batch

`GET /api/v1/enrichment/contacts/bulk/{batch_id}`

## Request

- Base URL: `https://api.rodz.io` (the document declares no server; this is the origin it was published from)
- URL: `https://api.rodz.io/api/v1/enrichment/contacts/bulk/{batch_id}`
- Auth: HTTP bearer

Fetch the status and (paginated) results of a bulk-enrichment batch submitted to `POST /api/v1/enrichment/contacts/bulk`.

This is the delivery path for `deliveryMode: poll`, and a fallback for `deliveryMode: webhook` (e.g. a missed webhook). Cost is unchanged — the 0.5-credit-per-match charge happens once on completion, whether you poll or use a webhook.

**Lifecycle:** `status` is `pending` → `processing` → `done` | `failed` (and, in webhook mode only, `delivery_failed` if the batch enriched fine but your webhook kept rejecting the push). Poll every few seconds while `pending`/`processing`.

**Input:** `batchId` in the path. Pagination: `cursor` (opaque, start omitted) and `limit` (default 1,000, max 10,000).

**Output:** `status`, `total`, `found`, and `results` — each `{externalId, url, person}` where `person` is the full profile (same shape as the webhook payload) or `null` when not matched. When more results remain, `nextCursor` is set — pass it back as `?cursor=` for the next page.

Results are retained for **7 days** after completion; older or unknown batch IDs return 404.

## Path parameters

- `batch_id` string, required

## Query parameters

- `cursor` integer: Opaque pagination cursor (start from the beginning if omitted)
- `limit` integer: Max results per page (default 1,000)

## Response `200`

Successful Response

- object: Status + (paginated) results of a bulk-enrichment batch.
  - `success` boolean
  - `data` object, required
    - `batchId` string, required: The batch identifier
    - `status` string, required: `pending` | `processing` | `done` | `failed` | `delivery_failed` (`delivery_failed` only in webhook mode — the enrichment finished but your webhook kept rejecting delivery)
    - `deliveryMode` string, required: `webhook` or `poll`
    - `total` integer, nullable: Total profiles in the batch (null until done)
    - `found` integer, nullable: Profiles successfully enriched (null until done)
    - `results` object[]: This page of results — each `{externalId, url, person}` (same `person` shape as the webhook payload; `person` is null when not matched). Empty until the batch is `done`.
      - `externalId` string, nullable: Your own reference, echoed back from the request
      - `url` string, nullable: The LinkedIn profile URL that was enriched
      - `person` object, nullable: A bulk-enriched profile. Typed from live responses on 2026-08-07 rather than from the sibling ``GET /enrichment/contact`` model: for the SAME profile the two endpoints return materially different objects (bulk adds seniority/jobFunction/geo ids, contact adds isPremium/city/websites and 15 more). Generating one type for both would misdescribe whichever you called.
        - `name` string, nullable
        - `firstName` string, nullable
        - `lastName` string, nullable
        - `headline` string, nullable
        - `linkedinSummary` string, nullable: The profile "About" section
        - `photoUrl` string, nullable
        - `linkedInUrl` string, nullable
        - `linkedInId` string, nullable: LinkedIn's numeric member id
        - `linkedinSalesLink` string, nullable: Sales Navigator member token for this profile
        - `location` string, nullable
        - `country` string, nullable: ISO-3166 alpha-2, e.g. `US`
        - `countryName` string, nullable
        - `region` string, nullable: Short region code, e.g. "na"
        - `regionName` string, nullable: e.g. "North America"
        - `geoId` integer, nullable: LinkedIn's numeric location id
        - `industry` string, nullable
        - `industryId` integer, nullable
        - `seniority` string, nullable: Seniority band, e.g. "cxo"
        - `subRole` string, nullable: Normalised role, e.g. "chairman and ceo"
        - `jobFunction` string, nullable: Normalised function, e.g. "general_management"
        - `activeCompany` string, nullable: Current employer name
        - `currentCompanyId` integer, nullable
        - `currentCompanyDetail` object[], nullable
          - `companyName` string, nullable
          - `jobTitle` string, nullable
          - `location` string, nullable: Where the role was based
          - `startTime` string, nullable: Start date (YYYY-MM-DD)
          - `endTime` string, nullable: End date (YYYY-MM-DD), or "Present" for a current role
          - `yearsInCompany` string, nullable: Human-readable, e.g. "8 yrs 7 mos"
          - `yearsInRole` string, nullable: Human-readable, e.g. "8 yrs 7 mos"
          - `employmentStatus` string, nullable
          - `companyId` integer, nullable: LinkedIn's numeric company id
          - `companyUrl` string, nullable: Company LinkedIn page URL
          - `companyWebsite` string, nullable
          - `companyIndustry` string, nullable
          - `companyType` string, nullable: e.g. "Public Company", "Educational Institution"
          - `companyTagline` string, nullable
          - `companyDescription` string, nullable
          - `companySpecialties` string[], nullable
          - `companyStaffCount` integer, nullable: Employees on LinkedIn
          - `companyStaffRange` string, nullable: Size band, e.g. "10001+"
          - `companyFollowerCount` integer, nullable
          - `companyFoundedYear` integer, nullable
          - `companyRevenueRange` string, nullable
          - `companyHqCity` string, nullable
          - `companyHqRegion` string, nullable
          - `companyCountryCode` string, nullable: ISO-3166 alpha-2, e.g. `US`
        - `pastCompaniesDetails` object[], nullable
          - `companyName` string, nullable
          - `jobTitle` string, nullable
          - `location` string, nullable: Where the role was based
          - `startTime` string, nullable: Start date (YYYY-MM-DD)
          - `endTime` string, nullable: End date (YYYY-MM-DD), or "Present" for a current role
          - `yearsInCompany` string, nullable: Human-readable, e.g. "8 yrs 7 mos"
          - `yearsInRole` string, nullable: Human-readable, e.g. "8 yrs 7 mos"
          - `employmentStatus` string, nullable
          - `companyId` integer, nullable: LinkedIn's numeric company id
          - `companyUrl` string, nullable: Company LinkedIn page URL
          - `companyWebsite` string, nullable
          - `companyIndustry` string, nullable
          - `companyType` string, nullable: e.g. "Public Company", "Educational Institution"
          - `companyTagline` string, nullable
          - `companyDescription` string, nullable
          - `companySpecialties` string[], nullable
          - `companyStaffCount` integer, nullable: Employees on LinkedIn
          - `companyStaffRange` string, nullable: Size band, e.g. "10001+"
          - `companyFollowerCount` integer, nullable
          - `companyFoundedYear` integer, nullable
          - `companyRevenueRange` string, nullable
          - `companyHqCity` string, nullable
          - `companyHqRegion` string, nullable
          - `companyCountryCode` string, nullable: ISO-3166 alpha-2, e.g. `US`
        - `formerCompaniesList` string, nullable: Previous employers, comma-separated
        - `education` object, nullable
          - `educationDetails` object[], nullable
            - `universityName` string, nullable
            - `degree` string, nullable
            - `fieldsOfStudy` string[], nullable
            - `schoolId` integer, nullable: LinkedIn's numeric id for the school
            - `startedOn` object, nullable
              - …
            - `endedOn` object, nullable
              - …
          - `universitiesNamesList` string, nullable: All school names, comma-separated — convenient for a single CRM field
        - `connectionsCount` integer, nullable
        - `followerCount` integer, nullable
        - `followers` string, nullable: Same value as `followerCount`, as a string
        - `languages` string, nullable: Languages, comma-separated
        - `languagesDetail` object[], nullable: Per-language entries. Left free-form on purpose: it was `null` on every profile we probed against live production (2026-08-07), so we have no observed shape to publish. Read defensively.
        - `skillsList` string, nullable: Skills, comma-separated
        - `skillsDetail` object[], nullable: Per-skill entries. Free-form for the same reason as `languagesDetail` — never observed populated.
    - `nextCursor` string, nullable: Pass as `?cursor=` to fetch the next page; null when no more

## Other responses

- `404`: No batch found for this ID under your account — wrong ID, results aged out (7-day TTL), or the ID belongs to a different account.
- `422`: Validation Error
- `429`: Rate limit exceeded. Retry after the number of seconds in the `Retry-After` response header.

---

[API](https://skmtc.dev/rodz/apis/rodz-api.md) · [All operations](https://skmtc.dev/rodz/apis/rodz-api/llms.txt) · [OpenAPI document](https://skmtc.dev/rodz/apis/rodz-api/revisions/3003505ff896?raw)
