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

# Read events

> Read the progress events of a search after a cursor. Send the last `seq` you have
as `after`, or as the `Last-Event-ID` header. With no cursor, you get every event
from the first one.

The `Accept` request header picks the response:

- `application/json` (the default; `*/*` or no `Accept` header gives the same)
  returns one JSON object: the `search_id` and an `events` list of the events
  stored so far.
- `text/event-stream` returns a stream that follows a running search to
  `search.finished`, or replays a search that has ended. Use the stream to
  resume a streaming start that broke.

`search.finished` is the last event. Its `data.search` is the search object, as
`GET /agent/searches/{search_id}` returns it at that moment, with the charge in
`credits_used`.

<Note>
    Default `rate-limit` is 300 requests per minute, shared by the read, events, and cancel routes.
</Note>




## OpenAPI

````yaml /openapi-specs/2025-11-01/agent_search.yaml get /agent/searches/{search_id}/events
openapi: 3.0.3
info:
  title: Agent Search API
  version: '2025-11-01'
  description: >
    The Agent Search API (beta) takes a question in plain words and returns the
    matching

    people, companies or jobs, each with the reasons it matches. You send the
    question to `POST /agent/searches`. An agent searches the

    Crustdata datasets in the background, picks the columns of the answer, and
    checks each

    row against the requirements it read in your question.


    A search runs for tens of seconds to a few minutes. Read it with

    `GET /agent/searches/{search_id}` until `state` is `succeeded`, `failed` or
    `cancelled`,

    or stream its events with `Accept: text/event-stream`.


    All requests require a valid API key passed via the `Authorization` header
    as a Bearer

    token and an `x-api-version` header set to `2025-11-01`.
servers:
  - url: https://api.crustdata.com
    description: Production API server
security:
  - bearerAuth: []
tags:
  - name: Agent Search APIs
    description: Start, read, stream and cancel agent searches.
paths:
  /agent/searches/{search_id}/events:
    get:
      tags:
        - Agent Search APIs
      summary: Read the events of an agent search
      description: >
        Read the progress events of a search after a cursor. Send the last `seq`
        you have

        as `after`, or as the `Last-Event-ID` header. With no cursor, you get
        every event

        from the first one.


        The `Accept` request header picks the response:


        - `application/json` (the default; `*/*` or no `Accept` header gives the
        same)
          returns one JSON object: the `search_id` and an `events` list of the events
          stored so far.
        - `text/event-stream` returns a stream that follows a running search to
          `search.finished`, or replays a search that has ended. Use the stream to
          resume a streaming start that broke.

        `search.finished` is the last event. Its `data.search` is the search
        object, as

        `GET /agent/searches/{search_id}` returns it at that moment, with the
        charge in

        `credits_used`.


        <Note>
            Default `rate-limit` is 300 requests per minute, shared by the read, events, and cancel routes.
        </Note>
      operationId: readAgentSearchEvents
      parameters:
        - $ref: '#/components/parameters/ApiVersion'
        - $ref: '#/components/parameters/SearchId'
        - name: after
          in: query
          required: false
          description: >-
            Return the events after this `seq`, a whole number from 0 to
            2147483647. Default 0.
          schema:
            type: integer
            minimum: 0
            maximum: 2147483647
            default: 0
        - name: Last-Event-ID
          in: header
          required: false
          description: >-
            The same cursor as `after`, as an event-stream client sends it on a
            reconnect. It wins over `after`.
          schema:
            type: string
      responses:
        '200':
          headers:
            X-Credits-Used:
              $ref: '#/components/headers/XCreditsUsed'
          description: The events after the cursor, as one list or as a stream.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AgentSearchEvents'
              examples:
                events:
                  summary: >-
                    The events after seq 50 of a search that ended (data.search
                    trimmed to 1 row)
                  value:
                    search_id: 1318-07fcae93f67c961a96c8758766b2fea1
                    events:
                      - seq: 51
                        data:
                          run: 1
                          state: succeeded
                          next_run: false
                          completion: answered
                        type: run.finished
                        message: 'Run 1 finished: answered.'
                        version: 1
                        search_id: 1318-07fcae93f67c961a96c8758766b2fea1
                        created_at: '2026-11-13T11:32:44.442Z'
                      - seq: 52
                        data:
                          state: succeeded
                          completion: answered
                          search:
                            search_id: 1318-07fcae93f67c961a96c8758766b2fea1
                            query: The founders of Crustdata
                            state: succeeded
                            created_at: '2026-11-13T11:32:26.860998+00:00'
                            output:
                              note: null
                              reason: null
                              person:
                                constraints:
                                  - id: c1
                                    text: Founded Crustdata.
                                    importance: hard
                                columns:
                                  - key: name
                                    label: Name
                                    field: basic_profile.name
                                  - key: profile_url
                                    label: Profile URL
                                    field: >-
                                      social_handles.professional_network_identifier.profile_url
                                  - key: basic_profile_headline
                                    label: Headline
                                    field: basic_profile.headline
                                rows:
                                  - id: 1068035
                                    values:
                                      name: Abhilash Chowdhary
                                      profile_url: >-
                                        https://www.linkedin.com/in/abhilashchowdhary
                                      basic_profile_headline: >-
                                        Co-founder at Crustdata (YC F24) | Infra
                                        for building AI employees
                                    constraints:
                                      - constraint_id: c1
                                        assessment: satisfied
                                        evidence: >-
                                          Headline identifies him as Crustdata
                                          co-founder, and current employer title
                                          is Co-Founder & CEO.
                                        fields:
                                          - basic_profile.headline
                            credits_used:
                              agent_cost: 0.66
                              search_cost: 0.1385
                              enrich_cost: 0
                              contact_cost: 0
                              total_cost: 0.7985
                            error: null
                        type: search.finished
                        message: 'Search finished: 3 people found.'
                        version: 1
                        search_id: 1318-07fcae93f67c961a96c8758766b2fea1
                        created_at: '2026-11-13T11:32:44.444Z'
            text/event-stream:
              schema:
                type: string
                description: >-
                  Server-sent events, in the same frame shape as the streaming
                  start of `POST /agent/searches`.
        '400':
          headers:
            X-Credits-Used:
              $ref: '#/components/headers/XCreditsUsed'
          description: The cursor is not a whole number from 0 to 2147483647.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                bad_cursor:
                  summary: after is not a whole number in range
                  value:
                    error:
                      type: invalid_request
                      message: >-
                        `after` and `Last-Event-ID` must be a whole number from
                        0 to 2147483647.
                      metadata: []
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/UnknownSearch'
        '429':
          description: >-
            More than 300 requests in one minute, or, on a stream, too many open
            event streams. The stream `429` carries `Retry-After: 5`.
          headers:
            Retry-After:
              $ref: '#/components/headers/RetryAfter'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                too_many_streams:
                  summary: Too many event streams are open
                  value:
                    error:
                      type: rate_limit_error
                      message: >-
                        Too many event streams are open. Read the events list
                        instead, or try again in 5 seconds.
                      metadata:
                        - retryable: true
                          retry_after_seconds: 5
        '503':
          $ref: '#/components/responses/ReadUnavailable'
components:
  parameters:
    ApiVersion:
      name: x-api-version
      in: header
      required: true
      schema:
        type: string
        enum:
          - '2025-11-01'
        default: '2025-11-01'
        example: '2025-11-01'
      description: API version to use. This endpoint currently requires `2025-11-01`.
    SearchId:
      name: search_id
      in: path
      required: true
      description: The `search_id` that the start returned.
      schema:
        type: string
        example: 1318-07fcae93f67c961a96c8758766b2fea1
  headers:
    XCreditsUsed:
      description: >-
        Exact credits this request deducted, as a decimal string (for example
        `0.9125`). On these routes, only the first read after a search ends
        carries a value above `0`. Responses generated before a request reaches
        the API, such as rate-limit `429`s, do not carry it.
      schema:
        type: string
        example: '0.9125'
    RetryAfter:
      description: Seconds to wait before you try again.
      schema:
        type: string
        example: '5'
  schemas:
    AgentSearchEvents:
      type: object
      description: The events after the cursor, oldest first.
      required:
        - search_id
        - events
      properties:
        search_id:
          type: string
          example: 1318-07fcae93f67c961a96c8758766b2fea1
        events:
          type: array
          items:
            $ref: '#/components/schemas/AgentSearchEvent'
          example:
            - seq: 2
              data:
                run: 1
                max_runs: 2
              type: run.started
              message: Run 1 of 2 started.
              version: 1
              search_id: 1318-c379345672f34397a53fafff6dcfaa83
              created_at: '2026-11-13T11:32:55.583Z'
    ErrorResponse:
      type: object
      description: >-
        The body of almost every error response. A `405` and a `404` on an
        unknown path have another body.
      required:
        - error
      properties:
        error:
          type: object
          required:
            - type
            - message
            - metadata
          properties:
            type:
              type: string
              example: invalid_request
            message:
              type: string
            metadata:
              type: array
              description: >-
                Empty, or `[{"retryable": true, "retry_after_seconds": N}]` on a
                error that can clear if you try again later.
              items:
                type: object
                properties:
                  retryable:
                    type: boolean
                  retry_after_seconds:
                    type: integer
    AgentSearchEvent:
      type: object
      description: >-
        One progress event. Ignore an event `type` you do not know, because new
        types can come.
      required:
        - seq
        - type
        - version
        - search_id
        - created_at
        - message
      properties:
        seq:
          type: integer
          description: >-
            Grows by 1 for each event of the search. It is the cursor for
            `after` and `Last-Event-ID`.
          example: 2
        type:
          type: string
          description: >-
            This enum is open. Values today: `search.created`, `run.started`,
            `step.started`, `step.running`, `step.finished`,
            `tool_call.started`, `tool_call.finished`, `answer.chosen`,
            `run.finished`, `search.finished`. `search.finished` is the last
            event.
          example: run.started
        version:
          type: integer
          example: 1
        search_id:
          type: string
          example: 1318-c379345672f34397a53fafff6dcfaa83
        created_at:
          type: string
          format: date-time
          example: '2026-11-13T11:32:55.577Z'
        message:
          type: string
          description: One plain sentence for a person to read.
          example: Run 1 of 2 started.
        data:
          type: object
          description: >-
            Details of the event. Its shape is part of the contract only for
            `search.finished`, where `data.search` is the search object. Some
            events, such as `search.created`, have no `data`.
          additionalProperties: true
  responses:
    Unauthorized:
      description: The API key is missing or not valid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            invalid_api_key:
              summary: No API key, or an API key that is not valid
              value:
                error:
                  type: unauthorized
                  message: Invalid API key in request.
                  metadata: []
    UnknownSearch:
      description: No search of your account has this `search_id`.
      headers:
        X-Credits-Used:
          $ref: '#/components/headers/XCreditsUsed'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            unknown_search:
              summary: The search_id is not one of yours
              value:
                error:
                  type: not_found
                  message: Unknown search_id.
                  metadata: []
    ReadUnavailable:
      description: >-
        Agent Search did not answer, or the rows of an ended search are not
        ready yet. Try again after `Retry-After` seconds. These messages come
        from the api code and were not reproduced live.
      headers:
        X-Credits-Used:
          $ref: '#/components/headers/XCreditsUsed'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          examples:
            not_answered:
              summary: Agent Search did not answer
              value:
                error:
                  type: service_unavailable
                  message: Agent Search did not answer. Try again in a few seconds.
                  metadata:
                    - retryable: true
                      retry_after_seconds: 5
            rows_not_ready:
              summary: The rows of an ended search are not ready
              value:
                error:
                  type: service_unavailable
                  message: >-
                    The rows of this search are not ready. Try again in a few
                    seconds.
                  metadata:
                    - retryable: true
                      retry_after_seconds: 5
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: API key passed as a Bearer token in the `Authorization` header.

````

## Related topics

- [Read a search](https://docs.crustdata.com/api-reference/agent-search-apis/read-an-agent-search.md)
- [Agent Search API](https://docs.crustdata.com/agent-search-docs/overview.md)
- [Cancel a search](https://docs.crustdata.com/api-reference/agent-search-apis/cancel-an-agent-search.md)
- [Rate limits](https://docs.crustdata.com/general/rate-limits.md)
- [Usage events](https://docs.crustdata.com/api-reference/account-apis/list-usage-events.md)
