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

# Send a batch

> Messages, system events, actions, identification and verification in one batch, with per-item errors.



## OpenAPI

````yaml openapi/en/cell.json POST /v1/batch
openapi: 3.1.0
info:
  title: Niadra data API
  version: '1'
  description: >-
    Writing, context, history, objects, identity, privacy and governance of one
    space. Every space has a stable address, with the space and the region in
    its name.
servers:
  - url: https://{space}.{region}.api.niadra.com
    variables:
      space:
        default: acme-prod
        description: The space, which comes in the source key.
      region:
        default: us-east-1
        description: The region of the space, which also comes in the key.
security: []
paths:
  /v1/batch:
    post:
      tags:
        - ingest
      summary: Send a batch
      description: >-
        Up to 500 items of mixed types: messages, system events, actions,
        `identify`, `verify`, `handoff` and the end of a conversation or task.
        The raw event is stored before the answer and deduplicated by
        `idempotency_key`, so a retry is always safe. Items are validated one by
        one: when every item is accepted the answer is 200, and when any is
        rejected it is 207 with one entry per rejected item in `errors`, never a
        422 for the whole batch. Scopes are checked per item: `track` for
        events, `act` for actions, `identify` for identification.


        **Authentication.** Source key: `Authorization: Bearer nia_sk_...`.
        Scopes are checked item by item: `track` for events, `act` for actions,
        `identify` for identification.
      operationId: batch_v1_batch_post
      requestBody:
        content:
          application/json:
            schema:
              $id: urn:niadra:v1:batch-request
              additionalProperties: false
              properties:
                items:
                  items:
                    discriminator:
                      mapping:
                        conversation.ended:
                          $ref: '#/components/schemas/ConversationEndedItem'
                        event:
                          $ref: '#/components/schemas/EventItem'
                        handoff:
                          $ref: '#/components/schemas/HandoffItem'
                        heartbeat:
                          $ref: '#/components/schemas/HeartbeatItem'
                        identify:
                          $ref: '#/components/schemas/IdentifyItem'
                        task.ended:
                          $ref: '#/components/schemas/TaskEndedItem'
                        verify:
                          $ref: '#/components/schemas/VerifyItem'
                      propertyName: type
                    oneOf:
                      - $ref: '#/components/schemas/EventItem'
                      - $ref: '#/components/schemas/IdentifyItem'
                      - $ref: '#/components/schemas/VerifyItem'
                      - $ref: '#/components/schemas/ConversationEndedItem'
                      - $ref: '#/components/schemas/TaskEndedItem'
                      - $ref: '#/components/schemas/HandoffItem'
                      - $ref: '#/components/schemas/HeartbeatItem'
                  maxItems: 500
                  minItems: 1
                  title: Items
                  type: array
              required:
                - items
              title: BatchRequest
              type: object
            example:
              items:
                - type: event
                  kind: message
                  idempotency_key: wamid.HBgLMTQxNTU1NTAxMjMVAgASGBQzQUQ
                  channel: whatsapp
                  conversation_id: wa-8812
                  handles:
                    - type: phone_e164
                      value: '+14155550123'
                  speaker:
                    role: customer
                  direction: inbound
                  content:
                    type: text
                    text: The technician never showed up. I am calling you.
                  occurred_at: '2026-09-22T17:02:11Z'
                - type: event
                  kind: action
                  idempotency_key: 0192f7a1-6c1e-7c3a-9b1e-5d2f8a4c0e11
                  channel: erp
                  task_id: billing-7741
                  handles:
                    - type: system_id
                      value: '48213'
                      scope: crm
                  object_refs:
                    - type: invoice
                      namespace: erp
                      id: '0823'
                  speaker:
                    role: ai_agent
                    id: billing-agent
                  action:
                    operation: credit
                    result: $40 credit on the August bill
                    closes:
                      object:
                        type: invoice
                        namespace: erp
                        id: '0823'
                      operation: dispute
                  occurred_at: '2026-09-22T17:06:21Z'
        required: true
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchResponse'
              example:
                accepted: 2
                duplicates: 0
                errors: []
          description: Every item was accepted or recognized as a duplicate.
        '207':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BatchResponse'
              example:
                accepted: 1
                duplicates: 0
                errors:
                  - index: 1
                    code: scope_missing
                    detail: the key lacks the act scope
          description: Some items were rejected; see `errors`.
      security:
        - sourceKey: []
      x-codeSamples:
        - lang: python
          label: Python
          source: >-
            from niadra import Niadra, phone, system_id


            niadra = Niadra()  # reads NIADRA_API_KEY


            # Queued and sent in the background, in batches

            niadra.track({
                "channel": "whatsapp",
                "conversation_id": "wa-8812",
                "idempotency_key": message["id"],  # the provider message id
                "handles": [phone("+14155550123")],
                "speaker": {"role": "customer"},
                "content": {"text": "The technician never showed up. I am calling you."},
            })


            niadra.action(
                "credit",
                subject=system_id("crm", "48213"),
                object="invoice:erp:0823",
                result="$40 credit on the August bill",
                closes={"object": {"type": "invoice", "namespace": "erp", "id": "0823"}, "operation": "dispute"},
                channel="erp",
                task_id="billing-7741",
            )


            niadra.flush()  # waits for the queue, for example before a worker
            exits
        - lang: typescript
          label: TypeScript
          source: >-
            import { Niadra, handles } from "@niadra/sdk";


            const niadra = new Niadra(); // reads NIADRA_API_KEY


            // Queued and sent in the background, in batches

            niadra.track({
              channel: "whatsapp",
              conversation_id: "wa-8812",
              idempotency_key: message.id, // the provider message id
              handles: [handles.phone("+14155550123")],
              speaker: "customer",
              text: "The technician never showed up. I am calling you.",
            });


            niadra.action({
              channel: "erp",
              task_id: "billing-7741",
              handles: [handles.systemId("48213", "crm")],
              object_refs: ["invoice:erp:0823"],
              operation: "credit",
              result: "$40 credit on the August bill",
              closes: { object: { type: "invoice", namespace: "erp", id: "0823" }, operation: "dispute" },
            });


            await niadra.flush(); // waits for the queue, for example before a
            worker exits
components:
  schemas:
    ConversationEndedItem:
      additionalProperties: false
      properties:
        conversation_id:
          maxLength: 512
          minLength: 1
          title: Conversation Id
          type: string
        idempotency_key:
          maxLength: 512
          minLength: 1
          title: Idempotency Key
          type: string
        occurred_at:
          format: date-time
          title: Occurred At
          type: string
        type:
          const: conversation.ended
          default: conversation.ended
          title: Type
          type: string
      required:
        - idempotency_key
        - conversation_id
        - occurred_at
      title: ConversationEndedItem
      type: object
      description: >-
        Closes the session now instead of waiting for inactivity. Send it at the
        end of every call.
    EventItem:
      additionalProperties: false
      description: A message, a system event or an agent action.
      properties:
        action:
          anyOf:
            - $ref: '#/components/schemas/ActionInfo'
            - type: 'null'
        canonical_type:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          description: System events only, e.g. `invoice.credited`.
          title: Canonical Type
        channel:
          maxLength: 256
          minLength: 1
          title: Channel
          type: string
          description: >-
            Where it happened: `whatsapp`, `voice`, `app`, `email`, `erp`,
            `crm`, `ticket`.
        content:
          anyOf:
            - $ref: '#/components/schemas/Content'
            - type: 'null'
        context_stamp:
          anyOf:
            - $ref: '#/components/schemas/ContextStamp'
            - type: 'null'
        conversation_aliases:
          items:
            maxLength: 512
            minLength: 1
            type: string
          maxItems: 8
          title: Conversation Aliases
          type: array
          description: >-
            Other ids of the same conversation, such as the platform id and the
            trunk id of a call.
        conversation_id:
          anyOf:
            - maxLength: 512
              minLength: 1
              type: string
            - type: 'null'
          title: Conversation Id
          description: >-
            Your id for the conversation. A WhatsApp thread may last months;
            Niadra splits it into sessions.
        corrects_event_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Corrects Event Id
        direction:
          anyOf:
            - enum:
                - inbound
                - outbound
              type: string
            - type: 'null'
          title: Direction
        fields:
          additionalProperties: true
          description: Structured fields of a system event.
          title: Fields
          type: object
        handles:
          items:
            $ref: '#/components/schemas/Handle'
          maxItems: 16
          title: Handles
          type: array
          description: Handles of the person the event is about.
        idempotency_key:
          description: Provider message id, or a UUIDv7 minted by the SDK.
          maxLength: 512
          minLength: 1
          title: Idempotency Key
          type: string
        kind:
          $ref: '#/components/schemas/EventKind'
          default: message
          description: Defaults to `message`.
        object_refs:
          items:
            $ref: '#/components/schemas/ObjectRef'
          maxItems: 16
          title: Object Refs
          type: array
          description: Orders, tickets, invoices the event is about.
        occurred_at:
          format: date-time
          title: Occurred At
          type: string
          description: >-
            When it happened at the source. Events are ordered by this, never by
            arrival.
        speaker:
          $ref: '#/components/schemas/SpeakerRef'
        subjects:
          items:
            $ref: '#/components/schemas/Subject'
          maxItems: 8
          title: Subjects
          type: array
          description: >-
            Use instead of `handles` when the event is about more than one
            subject.
        task_id:
          anyOf:
            - maxLength: 512
              minLength: 1
              type: string
            - type: 'null'
          title: Task Id
          description: Your id for the task of an internal agent.
        type:
          const: event
          default: event
          title: Type
          type: string
        verification_hint:
          anyOf:
            - $ref: '#/components/schemas/Verification'
            - type: 'null'
        visibility:
          $ref: '#/components/schemas/Visibility'
          default: public
          description: Defaults to `public`.
        voice:
          anyOf:
            - $ref: '#/components/schemas/VoiceInfo'
            - type: 'null'
      required:
        - idempotency_key
        - channel
        - speaker
        - occurred_at
      title: EventItem
      type: object
    HandoffItem:
      additionalProperties: false
      description: A transfer to a human or another agent; the measurement reads it.
      properties:
        conversation_id:
          maxLength: 512
          minLength: 1
          title: Conversation Id
          type: string
        idempotency_key:
          maxLength: 512
          minLength: 1
          title: Idempotency Key
          type: string
        mode:
          default: warm
          enum:
            - warm
            - cold
          title: Mode
          type: string
          description: '`warm` when the receiver gets a briefing. Defaults to `warm`.'
        occurred_at:
          format: date-time
          title: Occurred At
          type: string
        reason:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          title: Reason
        target:
          enum:
            - human
            - agent
          title: Target
          type: string
        target_source:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          title: Target Source
          description: The source that takes over, when it is integrated with Niadra.
        type:
          const: handoff
          default: handoff
          title: Type
          type: string
      required:
        - idempotency_key
        - conversation_id
        - target
        - occurred_at
      title: HandoffItem
      type: object
    HeartbeatItem:
      additionalProperties: false
      description: Periodic counters from the SDK, used to compute per-source coverage.
      properties:
        sent:
          minimum: 0
          title: Sent
          type: integer
          description: Events the SDK sent in the window.
        type:
          const: heartbeat
          default: heartbeat
          title: Type
          type: string
        window_start:
          format: date-time
          title: Window Start
          type: string
      required:
        - window_start
        - sent
      title: HeartbeatItem
      type: object
    IdentifyItem:
      additionalProperties: false
      description: States that several handles belong to the same subject.
      properties:
        conversation_id:
          anyOf:
            - maxLength: 512
              minLength: 1
              type: string
            - type: 'null'
          title: Conversation Id
        handles:
          items:
            $ref: '#/components/schemas/Handle'
          maxItems: 16
          minItems: 2
          title: Handles
          type: array
          description: Handles that belong to the same subject.
        idempotency_key:
          maxLength: 512
          minLength: 1
          title: Idempotency Key
          type: string
        method:
          $ref: '#/components/schemas/AssertionMethod'
          default: explicit_identify
          description: Defaults to `explicit_identify`.
        occurred_at:
          format: date-time
          title: Occurred At
          type: string
        subject_kind:
          $ref: '#/components/schemas/SubjectKind'
          default: person
          description: >-
            Defaults to `person`. Handles of different subject kinds are never
            linked by an assertion.
        type:
          const: identify
          default: identify
          title: Type
          type: string
      required:
        - idempotency_key
        - handles
        - occurred_at
      title: IdentifyItem
      type: object
    TaskEndedItem:
      additionalProperties: false
      properties:
        idempotency_key:
          maxLength: 512
          minLength: 1
          title: Idempotency Key
          type: string
        occurred_at:
          format: date-time
          title: Occurred At
          type: string
        task_id:
          maxLength: 512
          minLength: 1
          title: Task Id
          type: string
        type:
          const: task.ended
          default: task.ended
          title: Type
          type: string
      required:
        - idempotency_key
        - task_id
        - occurred_at
      title: TaskEndedItem
      type: object
      description: Closes the session of an internal-agent task.
    VerifyItem:
      additionalProperties: false
      description: >-
        Raises the verification level of one conversation or task. Never
        inferred.
      properties:
        conversation_id:
          anyOf:
            - maxLength: 512
              minLength: 1
              type: string
            - type: 'null'
          title: Conversation Id
        handle:
          $ref: '#/components/schemas/Handle'
          description: The handle whose possession was proven.
        idempotency_key:
          maxLength: 512
          minLength: 1
          title: Idempotency Key
          type: string
        level:
          $ref: '#/components/schemas/Verification'
        method:
          enum:
            - otp_whatsapp
            - otp_sms
            - login
            - kba
            - network_attestation
            - human_agent
          title: Method
          type: string
        occurred_at:
          format: date-time
          title: Occurred At
          type: string
        task_id:
          anyOf:
            - maxLength: 512
              minLength: 1
              type: string
            - type: 'null'
          title: Task Id
        type:
          const: verify
          default: verify
          title: Type
          type: string
        valid_until:
          anyOf:
            - format: date-time
              type: string
            - type: 'null'
          title: Valid Until
      required:
        - idempotency_key
        - method
        - level
        - handle
        - occurred_at
      title: VerifyItem
      type: object
    BatchResponse:
      additionalProperties: false
      properties:
        accepted:
          title: Accepted
          type: integer
        duplicates:
          title: Duplicates
          type: integer
          description: Items whose idempotency key was already stored.
        errors:
          items:
            $ref: '#/components/schemas/ItemError'
          title: Errors
          type: array
      required:
        - accepted
        - duplicates
        - errors
      title: BatchResponse
      type: object
    ActionInfo:
      additionalProperties: false
      properties:
        closes:
          anyOf:
            - $ref: '#/components/schemas/Closes'
            - type: 'null'
        corrects_action_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Corrects Action Id
          description: >-
            An action is immutable; a correction is a new action that points to
            the old one.
        operation:
          description: Canonical operation, e.g. `credit`, `reschedule`.
          maxLength: 256
          minLength: 1
          title: Operation
          type: string
        purpose:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          title: Purpose
        result:
          anyOf:
            - maxLength: 2000
              type: string
            - type: 'null'
          title: Result
      required:
        - operation
      title: ActionInfo
      type: object
      description: >-
        Required when `kind` is `action`, and only valid there. Needs the `act`
        scope.
    Content:
      additionalProperties: false
      properties:
        media_ref:
          anyOf:
            - maxLength: 512
              minLength: 1
              type: string
            - type: 'null'
          description: Reference returned by /v1/media/uploads.
          title: Media Ref
        media_sha256:
          anyOf:
            - pattern: ^[0-9a-f]{64}$
              type: string
            - type: 'null'
          title: Media Sha256
          description: SHA-256 of the media, in hex.
        stt_confidence:
          anyOf:
            - maximum: 1
              minimum: 0
              type: number
            - type: 'null'
          title: Stt Confidence
          description: Speech-to-text confidence, 0 to 1.
        text:
          anyOf:
            - maxLength: 200000
              type: string
            - type: 'null'
          title: Text
        transcript:
          anyOf:
            - maxLength: 200000
              type: string
            - type: 'null'
          title: Transcript
        type:
          default: text
          enum:
            - text
            - audio
            - image
            - file
          title: Type
          type: string
      title: Content
      type: object
      description: >-
        What was said or sent. Media never travels inline: upload it first and
        pass the reference.
    ContextStamp:
      additionalProperties: false
      description: >-
        Which context an agent's prompt carried and when it went in: the SDK
        sets it on the

        agent's turn, so measurement can tell a late context from an unused one.
      properties:
        etag:
          anyOf:
            - maxLength: 512
              minLength: 1
              type: string
            - type: 'null'
          title: Etag
        injected_at:
          format: date-time
          title: Injected At
          type: string
      required:
        - injected_at
      title: ContextStamp
      type: object
    Handle:
      additionalProperties: false
      description: >-
        An identifier of a subject in some channel or system: a phone, an
        e-mail, a CRM id.
      properties:
        scope:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          description: >-
            Namespace for scoped identifiers: the WhatsApp Business account for
            `wa_bsuid`, the system for `system_id`, the country for
            `gov_id_hmac`.
          title: Scope
        subject_kind:
          anyOf:
            - $ref: '#/components/schemas/SubjectKind'
            - type: 'null'
          description: Defaults to `person`, except for organization-only handle types.
        type:
          $ref: '#/components/schemas/HandleType'
        value:
          maxLength: 320
          minLength: 1
          title: Value
          type: string
          description: >-
            The identifier. Normalized on the server: E.164 for phones,
            lowercase for e-mail.
      required:
        - type
        - value
      title: Handle
      type: object
    EventKind:
      enum:
        - message
        - system_event
        - action
      title: EventKind
      type: string
      description: >-
        What an event records: something said, a change in a system of record,
        or what an agent did in a system.
    ObjectRef:
      additionalProperties: false
      description: >-
        A business object in a system of record, e.g. `invoice` / `erp` /
        `0823`.
      properties:
        id:
          maxLength: 512
          minLength: 1
          title: Id
          type: string
          description: The id in that system.
        namespace:
          maxLength: 256
          minLength: 1
          title: Namespace
          type: string
          description: The system it lives in, such as `erp`.
        type:
          maxLength: 256
          minLength: 1
          title: Type
          type: string
          description: Object type, such as `invoice`, `order` or `ticket`.
      required:
        - type
        - namespace
        - id
      title: ObjectRef
      type: object
    SpeakerRef:
      additionalProperties: false
      properties:
        id:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          description: Agent or attendant id inside the source.
          title: Id
        role:
          $ref: '#/components/schemas/Speaker'
      required:
        - role
      title: SpeakerRef
      type: object
    Subject:
      additionalProperties: false
      properties:
        handles:
          items:
            $ref: '#/components/schemas/Handle'
          maxItems: 16
          minItems: 1
          title: Handles
          type: array
        kind:
          $ref: '#/components/schemas/SubjectKind'
        role:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          title: Role
          description: Role of the person in the event, such as `driver` or `buyer`.
      required:
        - kind
        - handles
      title: Subject
      type: object
      description: >-
        One subject an event is about, when it is about more than one (a driver
        and the carrier).
    Verification:
      description: Session verification levels. `no_customer` sits outside the V0-V4 scale.
      enum:
        - V0
        - V1
        - V2
        - V3
        - V4
        - no_customer
      title: Verification
      type: string
    Visibility:
      enum:
        - public
        - internal
      title: Visibility
      type: string
      description: >-
        `internal` marks notes the customer never saw, such as an attendant
        note.
    VoiceInfo:
      additionalProperties: false
      properties:
        ani:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          title: Ani
          description: Calling number.
        answered_at:
          anyOf:
            - format: date-time
              type: string
            - type: 'null'
          title: Answered At
        dnis:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          title: Dnis
          description: Dialed number.
        end_reason:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          title: End Reason
        ended_at:
          anyOf:
            - format: date-time
              type: string
            - type: 'null'
          title: Ended At
        network_attestation:
          anyOf:
            - enum:
                - A
                - B
                - C
              type: string
            - type: 'null'
          title: Network Attestation
          description: >-
            Network attestation level of the call (STIR/SHAKEN and equivalents).
            A maps to V2, B and C to V1.
        recording_ref:
          anyOf:
            - maxLength: 512
              minLength: 1
              type: string
            - type: 'null'
          title: Recording Ref
        trunk:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          title: Trunk
        turn_offset_ms:
          anyOf:
            - minimum: 0
              type: integer
            - type: 'null'
          title: Turn Offset Ms
          description: Offset of this turn from the start of the call.
      title: VoiceInfo
      type: object
      description: Call metadata for voice events.
    AssertionMethod:
      enum:
        - explicit_identify
        - otp
        - login
        - system_import
        - same_event
        - co_occurrence
        - channel_rotation
        - accepted_suggestion
        - external_resolver
        - declared
      title: AssertionMethod
      type: string
      description: How the link between two handles was established.
    SubjectKind:
      enum:
        - person
        - account
        - partner
      title: SubjectKind
      type: string
      description: >-
        A person, a customer organization (`account`) or an organization that
        takes part without being a customer (`partner`).
    ItemError:
      additionalProperties: false
      properties:
        code:
          title: Code
          type: string
        detail:
          anyOf:
            - type: string
            - type: 'null'
          title: Detail
        index:
          title: Index
          type: integer
          description: Position of the item in `items`.
      required:
        - index
        - code
      title: ItemError
      type: object
    Closes:
      additionalProperties: false
      description: >-
        The open item an action fulfils: by id, or by object and canonical
        operation.
      properties:
        item_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Item Id
          description: The open item id.
        object:
          anyOf:
            - $ref: '#/components/schemas/ObjectRef'
            - type: 'null'
        operation:
          anyOf:
            - maxLength: 256
              minLength: 1
              type: string
            - type: 'null'
          title: Operation
          description: Canonical operation, together with `object`.
      title: Closes
      type: object
    HandleType:
      enum:
        - phone_e164
        - wa_id
        - wa_jid
        - wa_lid
        - wa_bsuid
        - email
        - gov_id_hmac
        - app_user_id
        - system_id
        - org_registry_hmac
        - email_domain
        - anon_id
      title: HandleType
      type: string
      description: >-
        The kind of identifier. The value is classified by its format, never by
        the field it came from.
    Speaker:
      enum:
        - customer
        - ai_agent
        - human_agent
        - system
      title: Speaker
      type: string
      description: Who produced the event.
  securitySchemes:
    sourceKey:
      type: http
      scheme: bearer
      description: nia_sk_...

````