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

# Pull the next leased batch of events

> Leases the next batch of events after the durable consumer's server-tracked position. Only durable consumer destinations can be pulled; other destination types return 400. A pull immediately resumes the calling worker's own outstanding lease (pulling before acknowledging means the previous handout was abandoned). The `workerId` identifies the individual worker and must be unique per worker instance; omitting it makes all anonymous pulls share one identity. Expired leases are redelivered before new work is handed out. Returns 204 when the durable consumer is caught up, 409 while it is paused and 429 when the in-flight window is full.



## OpenAPI

````yaml /api-reference/openapi/events.json post /v1/event-destinations/{id}/pull
openapi: 3.1.1
info:
  title: Occtoo Events API
  description: >-
    Occtoo Events API exposes customer-safe CloudEvents derived from changes
    across an Occtoo tenant. Use pull for scheduled or batch processing and SSE
    for low-latency delivery. Both transports read the same ordered, 90-day
    retained event projection.


    ## Quick start


    1. Select **Authorize** and sign in with the existing Occtoo identity, or
    provide a bearer token or organization API key.

    2. Inspect the [event catalog](https://api.occtoo.com/v1/event-types) to
    select event types and entity-level filters.

    3. Pull the first page, process it, and persist its `after` cursor.


    ```bash

    curl --get 'https://api.occtoo.com/v1/events' \
      --header 'Authorization: Bearer <access-token>' \
      --data-urlencode 'limit=100' \
      --data-urlencode 'filter=type eq "source.updated" and sourceId eq "products"'
    ```


    To check whether that consumer has reached the latest event matching the
    same filter, read stream metadata and compare `latest.sequence` with the
    last processed CloudEvent sequence. Sequence gaps identify position, not an
    exact number of pending matching events.


    ```bash

    curl --get 'https://api.occtoo.com/v1/events/metadata' \
      --header 'Authorization: Bearer <access-token>' \
      --data-urlencode 'filter=type eq "source.updated" and sourceId eq "products"'
    ```


    ## Authentication and tenancy


    Event reads require a tenant-scoped credential. All delivery endpoints
    require `read:events`. Interactive user calls use Authorization Code with
    PKCE and can reuse the existing Occtoo sign-in session. Machine consumers
    can send a tenant-scoped Kinde application token as `Authorization: Bearer
    <token>` or an Occtoo organization API key as `x-api-key:
    <organization-api-key>`. The gateway validates the credential, projects
    application scopes directly as permissions, and supplies its tenant and
    actor identity to the Events API; the tenant cannot be selected with a query
    parameter.


    Native browser `EventSource` cannot attach either authorization header.
    Browser applications should consume SSE with streaming `fetch` or relay it
    through an authenticated backend; server-side SSE clients can set either
    header directly.


    ## Delivery and checkpoints


    Events are ordered by the fixed-width `sequence` extension rather than their
    timestamp. A new SSE connection without a cursor starts live at the current
    tenant-stream tail; it does not replay retained history. Pull normally
    transports a position as an opaque `after` cursor, but accepts the raw
    sequence as a recovery checkpoint when the cursor was not retained. SSE
    transports the raw sequence as `Last-Event-ID`. Resuming is exclusive: the
    event at the supplied position is not delivered again. Public event ids are
    deterministic UUIDv5 values, so replaying the same internal event recreates
    the same id. Consumers should nevertheless make business processing
    idempotent and checkpoint only after successful processing.


    ### Recover from a recorded sequence


    If the returned pull cursor was lost but the last successfully processed
    CloudEvent `sequence` was retained, pass that sequence directly as `after`.
    Continue using the same filter as the original subscription.


    ```bash

    curl --get 'https://api.occtoo.com/v1/events' \
      --header 'Authorization: Bearer <access-token>' \
      --data-urlencode 'after=003.00000000000000184467' \
      --data-urlencode 'filter=type eq "source.updated" and sourceId eq "products"'
    ```


    To resume SSE from the same processed position, send `Last-Event-ID:
    003.00000000000000184467`. The first event returned has a greater sequence.


    ## Filtering


    `filter` implements a bounded RFC 7644-derived subset: `eq`, `and`, `or`,
    parentheses and JSON double-quoted strings. `and` binds more tightly than
    `or`. Use parentheses when combining event families. `type`, the envelope
    `subject`, and the data properties advertised by the catalog are accepted.
    Match a single entry with `type eq "source_entry.updated" and sourceId eq
    "products" and subject eq "sku-123"`. Subjects are opaque, case-sensitive
    strings; their meaning depends on the event type. Subject filters match only
    events normalized after subject projection was enabled; older retained
    events are not backfilled.


    ## Schema compatibility


    The CloudEvent `type` is stable and unversioned. Read the exact payload
    version from `dataschema`. A new minor version is additive: ignore unknown
    fields and fetch the new immutable schema asynchronously. Do not deserialize
    a new major version as an earlier major; retain or quarantine the raw event
    until the consumer is upgraded.


    Machine-readable contracts:
    [OpenAPI](https://api.occtoo.com/openapi/events.json) ·
    [AsyncAPI](https://api.occtoo.com/asyncapi/events.json) · [event
    catalog](https://api.occtoo.com/v1/event-types)
  version: 1.0.0
  summary: Pull, inspect and stream tenant-scoped Occtoo events.
servers:
  - url: https://api.occtoo.com
    description: Occtoo public API
security: []
tags:
  - name: Event delivery
    description: >-
      Consume the ordered tenant event feed by finite pull pages or a resumable
      SSE connection, and inspect retained filtered stream metadata. For a
      server-tracked position, pull leased batches from a durable consumer and
      acknowledge them, letting competing stateless workers share one durable
      consumer; durable consumer delivery is at-least-once, so processing must
      be idempotent. All operations use the same filter semantics.
  - name: Event discovery
    description: >-
      Discover stable event type names, available schema versions and the entity
      properties that can be filtered.
  - name: Event schemas
    description: >-
      Retrieve immutable JSON Schemas referenced by each CloudEvent `dataschema`
      attribute.
externalDocs:
  description: AsyncAPI contract for the SSE channel and all event messages
  url: https://api.occtoo.com/asyncapi/events.json
paths:
  /v1/event-destinations/{id}/pull:
    post:
      tags:
        - Event delivery
      summary: Pull the next leased batch of events
      description: >-
        Leases the next batch of events after the durable consumer's
        server-tracked position. Only durable consumer destinations can be
        pulled; other destination types return 400. A pull immediately resumes
        the calling worker's own outstanding lease (pulling before acknowledging
        means the previous handout was abandoned). The `workerId` identifies the
        individual worker and must be unique per worker instance; omitting it
        makes all anonymous pulls share one identity. Expired leases are
        redelivered before new work is handed out. Returns 204 when the durable
        consumer is caught up, 409 while it is paused and 429 when the in-flight
        window is full.
      operationId: PullDurableConsumerBatch
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: limit
          in: query
          schema:
            pattern: ^-?(?:0|[1-9]\d*)$
            type:
              - integer
              - string
            format: int32
            default: 20
        - name: visibility
          in: query
          schema:
            pattern: ^-?(?:0|[1-9]\d*)$
            type:
              - integer
              - string
            format: int32
            default: 60
        - name: workerId
          in: query
          schema:
            type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DurableConsumerBatch'
        '204':
          description: No Content
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '401':
          description: Unauthorized
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '409':
          description: Conflict
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '429':
          description: Too Many Requests
      security:
        - kindeOAuth: []
        - bearerAuth: []
        - apiKey: []
components:
  schemas:
    DurableConsumerBatch:
      required:
        - leaseId
        - generation
        - attempt
        - events
      type: object
      properties:
        leaseId:
          type: string
          format: uuid
        generation:
          pattern: ^-?(?:0|[1-9]\d*)$
          type:
            - integer
            - string
          format: int32
        attempt:
          pattern: ^-?(?:0|[1-9]\d*)$
          type:
            - integer
            - string
          format: int32
        events:
          type: array
    ApiError:
      required:
        - message
      type: object
      properties:
        message:
          type: string
  securitySchemes:
    kindeOAuth:
      type: oauth2
      description: >-
        Sign in with the existing Occtoo Studio identity and selected
        organization.
      flows:
        authorizationCode:
          authorizationUrl: >-
            https://auth.occtoo.com/oauth2/auth?audience=https%3A%2F%2Fapi-weu.occtoo.com
          tokenUrl: https://auth.occtoo.com/oauth2/token
          scopes:
            openid: Authenticate the user with OpenID Connect.
            profile: Read the user's basic profile.
            email: Read the user's email address.
            offline: Refresh the access token without another interactive sign-in.
          x-usePkce: SHA-256
          x-scalar-redirect-uri: https://api.occtoo.com/docs/
    bearerAuth:
      type: http
      description: >-
        Tenant-scoped Occtoo access token, including Kinde machine-to-machine
        application tokens.
      scheme: bearer
      bearerFormat: JWT
    apiKey:
      type: apiKey
      description: Occtoo organization API key.
      name: x-api-key
      in: header

````

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