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

# Request a re-sync of several resources in one call

> Queues up to 25 on-demand re-syncs in one round trip. Kinds may be mixed. Each item is processed independently and under the SAME guardrails as POST /sync-requests — its own scope check, its own 5-minute per-resource cooldown (30 per connector for appointments), and its own slot of the 500-per-organization-per-24h ceiling: a batch of 25 spends 25 slots, not one. **Best-effort, not atomic**: the 202 says the batch was processed, not that every item queued. Each result carries either `request` (queued, including `resourceUpdatedAt`) or `error` (the status and message the single-resource endpoint would have returned — 500 among them, scoped to the one item rather than failing the request, plus a batch-only 503 when the batch hit its time budget before that item was started: a 503 item ran nothing, holds no cooldown and spent no cap slot, so retry it in a smaller batch), never both — an item refused by its cooldown does not affect the others. Results come back in the order sent, with `resourceId` echoed verbatim. Poll each queued item's `GET /sync-requests/{id}` as usual; the sync_request.completed webhook fires once PER ITEM, not per batch. The response is held until every item has been dispatched, so it can take several seconds. More than the maximum is a 400 naming the limit, never a silent truncation.



## OpenAPI

````yaml /openapi-v3.json post /sync-requests/batch
openapi: 3.0.0
info:
  title: Max AI Public API
  description: API for third-party marketplace apps
  version: '3.0'
  contact: {}
servers:
  - url: https://api.maxcare.ai/v3
security: []
tags: []
paths:
  /sync-requests/batch:
    post:
      tags:
        - Sync Requests
      summary: Request a re-sync of several resources in one call
      description: >-
        Queues up to 25 on-demand re-syncs in one round trip. Kinds may be
        mixed. Each item is processed independently and under the SAME
        guardrails as POST /sync-requests — its own scope check, its own
        5-minute per-resource cooldown (30 per connector for appointments), and
        its own slot of the 500-per-organization-per-24h ceiling: a batch of 25
        spends 25 slots, not one. **Best-effort, not atomic**: the 202 says the
        batch was processed, not that every item queued. Each result carries
        either `request` (queued, including `resourceUpdatedAt`) or `error` (the
        status and message the single-resource endpoint would have returned —
        500 among them, scoped to the one item rather than failing the request,
        plus a batch-only 503 when the batch hit its time budget before that
        item was started: a 503 item ran nothing, holds no cooldown and spent no
        cap slot, so retry it in a smaller batch), never both — an item refused
        by its cooldown does not affect the others. Results come back in the
        order sent, with `resourceId` echoed verbatim. Poll each queued item's
        `GET /sync-requests/{id}` as usual; the sync_request.completed webhook
        fires once PER ITEM, not per batch. The response is held until every
        item has been dispatched, so it can take several seconds. More than the
        maximum is a 400 naming the limit, never a silent truncation.
      operationId: SyncRequestsPublicController_createSyncRequestBatch
      parameters:
        - name: X-Organization-Id
          in: header
          required: true
          schema:
            type: string
          description: Target clinic organization ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateSyncRequestBatchBodyV3'
      responses:
        '202':
          description: Accepted — queued for background processing
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateSyncRequestBatchSuccessResponseV3'
        '400':
          description: Missing or invalid request parameter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiBadRequestResponse'
        '401':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiUnauthorizedResponse'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiRateLimitResponse'
      security:
        - api-key: []
components:
  schemas:
    CreateSyncRequestBatchBodyV3:
      type: object
      properties:
        requests:
          description: >-
            The resources to re-sync, each identified by its prefixed id
            (clm_/bil_/pat_/nte_/apt_)
          maxItems: 25
          minItems: 1
          type: array
          items:
            $ref: '#/components/schemas/CreateSyncRequestBodyV3'
      required:
        - requests
    CreateSyncRequestBatchSuccessResponseV3:
      type: object
      properties:
        code:
          type: string
          description: Response code
          example: success
        data:
          $ref: '#/components/schemas/CreateSyncRequestBatchResponseDataV3'
      required:
        - code
        - data
    PublicApiBadRequestResponse:
      type: object
      properties:
        code:
          type: string
          description: Error code
          example: bad_request
        message:
          type: string
          description: Human-readable error message
          example: '''id'' must be a valid UUID'
        trace_id:
          type: string
          description: Trace ID for debugging
          example: 550e8400-e29b-41d4-a716-446655440000
      required:
        - code
        - message
        - trace_id
    PublicApiUnauthorizedResponse:
      type: object
      properties:
        code:
          type: string
          description: Error code
          example: unauthorized
        message:
          type: string
          description: Human-readable error message
          example: Invalid or missing API key
        trace_id:
          type: string
          description: Trace ID for debugging
          example: 550e8400-e29b-41d4-a716-446655440000
      required:
        - code
        - message
        - trace_id
    PublicApiRateLimitResponse:
      type: object
      properties:
        code:
          type: string
          description: Error code
          example: rate_limit_exceeded
        message:
          type: string
          description: Human-readable error message
          example: Rate limit exceeded. Maximum 1000 requests per 60 seconds.
        trace_id:
          type: string
          description: Trace ID for debugging
          example: 550e8400-e29b-41d4-a716-446655440000
      required:
        - code
        - message
        - trace_id
    CreateSyncRequestBodyV3:
      type: object
      properties:
        resourceType:
          type: string
          description: What kind of resource to re-sync with the EHR
          enum:
            - claim
            - bill
            - patient
            - note
            - appointment
          example: claim
        resourceId:
          type: string
          description: >-
            The resource's id in its prefixed form (clm_/bil_/pat_/nte_/apt_),
            or a raw UUID
          example: clm_a1b2c3d456784abc9def0123456789ab
      required:
        - resourceType
        - resourceId
    CreateSyncRequestBatchResponseDataV3:
      type: object
      properties:
        requests:
          description: >-
            One result per item, in the order you sent them. **Partial success
            is the normal case**: the 202 says the batch was processed, NOT that
            everything queued. Every item carries either `request` or `error`,
            never both and never neither — check each one.
          type: array
          items:
            $ref: '#/components/schemas/BatchSyncRequestItemResponseV3'
      required:
        - requests
    BatchSyncRequestItemResponseV3:
      type: object
      properties:
        resourceType:
          type: string
          description: The item's `resourceType`, echoed back
          enum:
            - claim
            - bill
            - patient
            - note
            - appointment
          example: bill
        resourceId:
          type: string
          description: >-
            The item's `resourceId`, echoed back verbatim in the prefixed form
            you sent it
          example: bil_a1b2c3d456784abc9def0123456789ab
        request:
          description: >-
            The queued sync request, identical to what POST /sync-requests
            returns — including `resourceUpdatedAt`. Null when this item was
            refused; see `error`.
          nullable: true
          allOf:
            - $ref: '#/components/schemas/ExternalSyncRequestResponseV3'
        error:
          description: Why this item was refused, or null when it was queued.
          nullable: true
          example: null
          allOf:
            - $ref: '#/components/schemas/BatchSyncRequestItemError'
      required:
        - resourceType
        - resourceId
        - request
        - error
    ExternalSyncRequestResponseV3:
      type: object
      properties:
        id:
          type: string
          description: Sync request unique identifier
          example: srq_c1d2e3f456784abc9def0123456789ab
        resourceType:
          type: string
          description: Kind of resource being re-synced
          enum:
            - claim
            - bill
            - patient
            - note
            - appointment
          example: claim
        resourceId:
          type: string
          description: The resource being re-synced
          example: clm_a1b2c3d456784abc9def0123456789ab
        status:
          type: string
          description: Request lifecycle status. Poll until 'completed' or 'failed'.
          enum:
            - queued
            - completed
            - failed
          example: queued
        errorKind:
          type: string
          description: >-
            Why a failed request failed, as a closed marker: `child_run_failed`
            (a sync run failed or was interrupted), `cancelled_before_start`
            (the sync runs were discarded while still queued — usually because
            an equivalent sync already held the lane — so nothing this request
            dispatched ran: it costs no daily-cap slot, but still holds the
            cooldown — 5 minutes, or 30 per connector for an appointment), or
            `stale` (no terminal outcome inside the 30-minute watch window).
            Null unless status is 'failed'. A request that could not be started
            at all never reaches this field: it is refused synchronously with a
            4xx or 502 and no request id, so there is nothing to poll.
          nullable: true
          example: null
        resourceUpdatedAt:
          type: string
          description: >-
            The resource's own change stamp as it stood when this request was
            accepted, so you can tell whether the re-sync changed anything:
            re-read the resource and compare. It is the SAME field that
            resource's endpoint returns — `updatedAt` for claim, bill, note and
            patient; `lastSyncedAt` for appointment, which exposes that instead.
            Note it moves only when the data actually CHANGED, so it is not a
            completion signal: use the request's own `status` (or the completion
            webhook) for that. **Returned only on the 202 that creates the
            request** — it is a property of the resource at request time, is not
            stored, and is always null on GET.
          nullable: true
          example: '2026-08-09T12:00:00.000Z'
        requestedAt:
          type: string
          description: When the re-sync was requested
          example: '2026-08-09T12:00:00.000Z'
        completedAt:
          type: string
          description: When the request reached a terminal state
          nullable: true
          example: null
      required:
        - id
        - resourceType
        - resourceId
        - status
        - errorKind
        - resourceUpdatedAt
        - requestedAt
        - completedAt
    BatchSyncRequestItemError:
      type: object
      properties:
        statusCode:
          type: number
          description: >-
            The status the same request would have received from POST
            /sync-requests on its own: 400 (un-syncable resource), 403 (missing
            scope for that kind), 404 (no such resource in this organization),
            409 (cooldown or a re-sync already running), 429 (the organization's
            daily cap), 502 (the re-sync could not be started). 500 is the same
            unhandled failure the single-resource endpoint would answer with —
            same status and the same `Internal server error` message — except
            that here it is scoped to the one item so the rest of the batch
            still runs. 503 is genuinely batch-only: the batch reached its time
            budget before this item was started, so nothing ran for it — it
            holds no cooldown and spent no daily-cap slot, and can be retried
            immediately in a smaller batch.
          example: 409
        message:
          type: string
          description: >-
            Human-readable reason, the same message the single-resource endpoint
            would have returned.
          example: >-
            This bill was already re-synced in the last 5 minutes. Retry after
            the cooldown.
      required:
        - statusCode
        - message
  securitySchemes:
    api-key:
      scheme: bearer
      bearerFormat: JWT
      type: http
      description: Marketplace API key

````