> ## Documentation Index
> Fetch the complete documentation index at: https://docs.retriever.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Run a slow service (a list of 1 to 100 inputs)

> The only way to run a slow service (`getEmail`, `getPhoneNumber`,
`webResearch`, `getLinkedInUserComments`, `getLinkedInUserReactions`):
1 to 100 inputs in one call, one job per input, in the order sent. Put
every person of a task in the same list.
Every input is validated first; one bad input refuses the whole list
with its index, and no job is created.

An input the schema accepts but that names too little to search (a
contact with no LinkedIn profile, and no first and last name with a
company) is not refused here: its line ends `provider_rejected`.

Each line follows the job rules. For `getEmail` and `getPhoneNumber`
only, an answer your organization already has for that person from the
last 7 days is reused and the line comes back with
`reused: true` (nothing is charged for it). Other slow services never
reuse a finished answer: they only share a search still running, like
every service does. A failed line is never reused: the same input sent
again gets a new job. The batch and its jobs are
created together or not at all. `Retriever-Fresh: true` forces a
fresh, billed execution of every line. Collect the results with
`GET /v1/services/jobs/batch/{id}`. Requests and results are emptied
after 30 days.

Each line reserves its worst-case price before its search. When the
balance cannot reserve even the cheapest line that needs a new search,
the whole list is refused with `402 insufficient_credits` and no job
is created. Otherwise the list is accepted, and a line that finds no
balance left ends `failed` with `usage_limit`: top up, then send the
failed inputs again. No line carries its own charge: compare
`GET /credits` before and after the batch for its total.

`getPhoneNumber` returns every number its sources found in `phones`
(number, country, line type, line status, source), best first;
`phone_number` is the first entry.




## OpenAPI

````yaml /openapi.yaml post /v1/services/jobs/batch
openapi: 3.1.0
info:
  title: Retriever Public API
  version: 1.0.0
  description: >
    Retriever public API: start the prospecting agent (runs), read and export

    tables, import data, sync exclusion lists, run structured research (Go),

    and call atomic services.


    **Model Context Protocol (MCP)**: the same account and credits are available

    through the hosted MCP server (`POST /mcp`, Streamable HTTP). See the MCP

    guide in this documentation (Model Context Protocol navigation). Primary

    tools: `service_discover`, `service_execute`, `service_batch_execute` and

    `service_batch_get` (the slow services), `retriever_build_list_start`,

    `table_*`, `sequence_*`, `inbox_*`.


    **Authentication**: `Authorization: Bearer ret_live_…`. Create the key in
    the

    app: Settings → **API keys** → **Create API key**. The key grants access to

    resources in the key owner's organization.


    **Errors**: every HTTP error has the shape

    `{ "error": { "code": "…", "message": "…", "details": … } }`.

    Branch your code on `error.code` (stable), never on `message`.


    **Rate limits**: key-authenticated responses include

    `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset` (seconds).

    A `429` response also includes `Retry-After` (seconds).


    API error messages are in English.
  contact:
    name: Retriever
servers:
  - url: https://api.retriever.run
    description: Production
  - url: http://localhost:4320
    description: Local app-server
security:
  - bearerAuth: []
tags:
  - name: Runs
    description: Prospecting agent « prompt in, table out ». Asynchronous.
  - name: Tables
    description: Read live tables in a workspace.
  - name: Workspaces
    description: Create workspaces and import tables.
  - name: Exclusions
    description: Company and people lists to never source.
  - name: Go
    description: Autonomous web research and structured extraction.
  - name: Services
    description: Atomic services (search, scraping, email…).
  - name: Credits
    description: Credit balance.
paths:
  /v1/services/jobs/batch:
    post:
      tags:
        - Services
      summary: Run a slow service (a list of 1 to 100 inputs)
      description: |
        The only way to run a slow service (`getEmail`, `getPhoneNumber`,
        `webResearch`, `getLinkedInUserComments`, `getLinkedInUserReactions`):
        1 to 100 inputs in one call, one job per input, in the order sent. Put
        every person of a task in the same list.
        Every input is validated first; one bad input refuses the whole list
        with its index, and no job is created.

        An input the schema accepts but that names too little to search (a
        contact with no LinkedIn profile, and no first and last name with a
        company) is not refused here: its line ends `provider_rejected`.

        Each line follows the job rules. For `getEmail` and `getPhoneNumber`
        only, an answer your organization already has for that person from the
        last 7 days is reused and the line comes back with
        `reused: true` (nothing is charged for it). Other slow services never
        reuse a finished answer: they only share a search still running, like
        every service does. A failed line is never reused: the same input sent
        again gets a new job. The batch and its jobs are
        created together or not at all. `Retriever-Fresh: true` forces a
        fresh, billed execution of every line. Collect the results with
        `GET /v1/services/jobs/batch/{id}`. Requests and results are emptied
        after 30 days.

        Each line reserves its worst-case price before its search. When the
        balance cannot reserve even the cheapest line that needs a new search,
        the whole list is refused with `402 insufficient_credits` and no job
        is created. Otherwise the list is accepted, and a line that finds no
        balance left ends `failed` with `usage_limit`: top up, then send the
        failed inputs again. No line carries its own charge: compare
        `GET /credits` before and after the batch for its total.

        `getPhoneNumber` returns every number its sources found in `phones`
        (number, country, line type, line status, source), best first;
        `phone_number` is the first entry.
      operationId: createServiceJobBatch
      parameters:
        - name: Retriever-Fresh
          in: header
          required: false
          schema:
            type: string
            enum:
              - 'true'
          description: >-
            `true`: a new, billed search for every line, even when your
            organization has a recent answer.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - service
                - inputs
              properties:
                service:
                  type: string
                  example: getPhoneNumber
                inputs:
                  type: array
                  minItems: 1
                  maxItems: 100
                  items:
                    type: object
                    description: >-
                      One direct input object, as `POST /services/{serviceName}`
                      takes it.
      responses:
        '200':
          description: 'Every input already had an answer: the batch is complete.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceJobBatch'
        '202':
          description: Batch accepted; at least one job is still running.
          headers:
            Location:
              schema:
                type: string
            Retry-After:
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ServiceJobBatch'
        '400':
          description: >-
            `invalid_request`: the body or an input is invalid (the message
            names the field, and an input's index), or `service_not_async`: a
            fast service, call it directly on `POST /services/{serviceName}`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          description: >-
            `insufficient_credits`: the balance cannot reserve the cheapest line
            that needs a new search. No job is created. Top up (`GET /credits`
            for the balance), then send the list again.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '404':
          description: >-
            `not_found`: no public service has this name (`GET /services` lists
            them).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          $ref: '#/components/responses/TooManyRequests'
components:
  schemas:
    ServiceJobBatch:
      type: object
      properties:
        ok:
          type: boolean
        batch_id:
          type: string
          example: svcbatch_9f2c4b1e8a7d6c5f
        service:
          type: string
        size:
          type: integer
        status:
          type: string
          enum:
            - queued
            - running
            - completed
          description: '`completed` once every job has ended, whatever each one''s outcome.'
        counts:
          type: object
          properties:
            queued:
              type: integer
            running:
              type: integer
            completed:
              type: integer
            failed:
              type: integer
            cancelled:
              type: integer
        jobs:
          type: array
          description: One entry per input, in the order sent.
          items:
            allOf:
              - $ref: '#/components/schemas/ServiceJobLine'
              - type: object
                properties:
                  input_index:
                    type: integer
        poll_url:
          type: string
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Stable code; use in your application.
            message:
              type: string
              description: Human-readable explanation. May change.
            details:
              description: Optional details (e.g. list of invalid fields).
    ServiceJobLine:
      type: object
      properties:
        job_id:
          type: string
        service:
          type: string
        status:
          type: string
          enum:
            - queued
            - running
            - completed
            - failed
            - cancelled
        attempt:
          type: integer
          description: >-
            Number of times the provider call started (the current claim
            included). Becomes 2 if a restart resumed a started job. A restart
            before the call started does not count.
        reused:
          type: boolean
          description: >-
            `true` when the answer came from one your organization already paid
            for (a recent answer, or a job another list started): nothing was
            charged for it. On a batch line, also `true` for a line that points
            to a job another line or list created.
        result:
          type: object
          description: Present only if `completed`.
        error:
          type: object
          description: >-
            Present only if `failed`. Never a negative answer, and nothing was
            charged (except the Deep agent's miss price when a contact lookup's
            Deep agent finished its search).
          properties:
            code:
              type: string
              description: >-
                Retryable: `timeout`, `capacity`, `interrupted`,
                `provider_error`, `provider_unavailable`, `capability_error`,
                `service_error`, `service_execution_failed`, `worker_lost`,
                `usage_limit` (after a top-up). Not retryable:
                `provider_rejected`, `validation_error`, `invalid_output` (the
                service answered outside its own contract) and any other code.
            message:
              type: string
            retryable:
              type: boolean
              description: >-
                `true`: the same input can get an answer later (after a top-up
                for `usage_limit`), send it again in a new batch. `false`: it
                gets the same refusal.
        created_at:
          type: string
          format: date-time
        started_at:
          type: string
          format: date-time
          nullable: true
          description: When the provider call first started. Null while the job waits.
        completed_at:
          type: string
          format: date-time
          nullable: true
  responses:
    Unauthorized:
      description: >-
        `not_authenticated`: missing header, malformed (expected `Bearer
        <key>`), revoked or unknown key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: not_authenticated
              message: A valid API key is required.
    TooManyRequests:
      description: '`rate_limited`: wait `Retry-After` seconds, then retry.'
      headers:
        Retry-After:
          schema:
            type: integer
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimit-Limit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimit-Remaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimit-Reset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: rate_limited
              message: Rate limit exceeded. Retry later.
  headers:
    RateLimit-Limit:
      schema:
        type: integer
      description: Window budget.
    RateLimit-Remaining:
      schema:
        type: integer
      description: Remaining requests.
    RateLimit-Reset:
      schema:
        type: integer
      description: Seconds until reset.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key `ret_live_…` created in Settings → API keys.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.