---
title: "Track Events (Batch)"
method: POST
path: "/v1/events/batch"
tags: ["Events"]
---

# Track Events (Batch)

`POST /v1/events/batch`

Record up to 500 events in one request with row-level partial success: one malformed row never fails the batch. Idempotency is per row via dedupeKey; a request-level Idempotency-Key header is rejected. Aggregate properties payloads are limited to 1MB.

## Request body

- object
  - `projectId` string, required
  - `events` IngestEventRow[], required
    - `name` string, required — Event name, e.g. purchase.completed. Names containing refund or cancelled record negative conversion amounts.
    - `origin` string
    - `eventVersion` string
    - `identifiers` EventIdentifiers, required — Contact identity for the event. At least one of email or subscriberId is required. Provider ids (externalCustomerId, externalCheckoutId, externalOrderId) support integrations and conversion attribution.
      - `email` string, email
      - `subscriberId` string
      - `externalCustomerId` string
      - `externalCheckoutId` string
      - `externalOrderId` string — The provider's order or charge id. Required for the event to record a conversion.
    - `profile` EventProfile — Contact metadata to update. Profile updates never change subscription status, tags, or consent. Events never opt a contact in.
      - `firstName` string
      - `lastName` string
      - `phone` string
      - `country` string
      - `language` string
      - `customFields` object
    - `properties` object — Event facts. Up to 16KB, 50 top-level keys, 4 levels deep. A numeric value (major units, e.g. 49.99) together with identifiers.externalOrderId records a conversion; currency is an ISO code, default USD.
    - `occurredAt` string, date-time — When the event happened. Defaults to receipt time.
    - `dedupeKey` string — Event-identity dedupe key. Replaying the same key stores nothing and returns the original eventId.

## Response `201`

Batch processed with per-row results

- ApiResponseTrackEventBatchResult
  - `success` boolean, required
  - `data` object, nullable
    - `accepted` integer
    - `duplicates` integer
    - `results` object[]
      - `index` integer
      - `stored` boolean
      - `eventId` string
      - `dedupeKey` string
    - `invalid` object[]
      - `index` integer
      - `error` string
  - `error` string, nullable

## Other responses

- `400` — Envelope invalid, aggregate payload too large, or request-level Idempotency-Key supplied
- `401` — Missing or invalid API key
- `403` — Missing audience:write permission or no access to the project

---

[API](https://skmtc.net/migma/apis/migma-ai-api-v1.md) · [All operations](https://skmtc.net/migma/apis/migma-ai-api-v1/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/migma/migma-ai-api-v1/revisions/2d06ad0e0bc3/schema)
