Skip to main content

Overview

Events let your backend tell Migma when a customer does something that matters, such as completing a purchase, starting a trial, or requesting a refund. Migma stores each event against a contact and uses purchase events to attribute revenue back to the email a recipient clicked. Common uses:
  • Report a purchase so Migma can credit the email that drove it
  • Record trial starts, upgrades, or cancellations as customer activity
  • Send negative amounts for refunds and cancellations so revenue stays honest
  • Feed order and profile context into a contact without changing their subscription
Events are inbound: your system reports them to Migma. This is the opposite direction from webhooks, which are outbound notifications Migma sends to you.
Reporting events requires an API key with the audience:write permission.

Quick start

Report a completed purchase with an order identifier and a value. Migma stores the event and, when the value and order identifier are present, records it as a conversion.
curl https://api.migma.ai/v1/events \
  -H "Authorization: Bearer $MIGMA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-10432" \
  -d '{
    "projectId": "665f1e928c2a9e4d8f123123",
    "name": "purchase.completed",
    "identifiers": {
      "email": "casey@example.com",
      "externalOrderId": "order-10432"
    },
    "properties": {
      "value": 49.99,
      "currency": "USD"
    },
    "occurredAt": "2026-07-03T12:34:56.789Z"
  }'
The response is synchronous:
{
  "stored": true,
  "eventId": "668f2f7b9a9b6d84f1b2c345",
  "dedupeKey": "order-10432"
}

Event fields

FieldRequiredMeaning
projectIdYesThe brand the event belongs to.
nameYesThe event name, such as purchase.completed or trial.started.
identifiersYesHow Migma matches the event to a contact. See below.
profileNoContact metadata to update: firstName, lastName, phone, country, language, customFields.
propertiesNoStructured event data. Up to 16KB, 50 top-level keys, and 4 levels deep.
occurredAtNoWhen the event happened, in ISO 8601 format. Defaults to receipt time.
dedupeKeyNoA key to make the event replay-safe. See Replay safety.

Identifiers

Provide at least one way to match the event to a contact:
IdentifierUse
emailMatch or create a contact by email address.
subscriberIdMatch an existing contact by its Migma ID.
externalCustomerIdYour own customer ID, stored for cross-referencing.
externalCheckoutIdYour checkout or session ID.
externalOrderIdYour order ID. Required for conversion attribution.
Events never change subscription status. An event never opts anyone in, resubscribes an unsubscribed contact, or makes a non-sendable contact sendable. When you include profile, Migma updates contact metadata only. To manage subscription status, use the Contacts API.

Replay safety

Networks retry. Migma gives you two ways to make sure a retried report is stored once.
  • Single events: send an Idempotency-Key header. A retry with the same key returns the original result instead of storing a second event.
  • Batches: set a per-event dedupeKey on each row. A request-level Idempotency-Key header on a batch returns 400, because one key cannot cover many events.
Raw events are retained for 90 days.

Batches

Report up to 500 events in one request with POST /v1/events/batch. Each row is validated on its own, so a batch can partially succeed: valid rows are stored, invalid rows are reported back, and duplicates are counted.
curl https://api.migma.ai/v1/events/batch \
  -H "Authorization: Bearer $MIGMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": "665f1e928c2a9e4d8f123123",
    "events": [
      {
        "name": "purchase.completed",
        "identifiers": { "email": "casey@example.com", "externalOrderId": "order-10432" },
        "properties": { "value": 49.99, "currency": "USD" },
        "dedupeKey": "order-10432"
      },
      {
        "name": "trial.started",
        "identifiers": { "email": "jordan@example.com" },
        "dedupeKey": "trial-jordan-1"
      }
    ]
  }'
The response reports each row:
{
  "accepted": 1,
  "duplicates": 1,
  "results": [
    { "stored": true, "eventId": "668f30a19a9b6d84f1b2c400", "dedupeKey": "order-10432" },
    { "stored": false, "duplicate": true, "dedupeKey": "trial-jordan-1" }
  ],
  "invalid": []
}
FieldMeaning
acceptedRows stored on this request.
duplicatesRows skipped because their dedupeKey was already stored.
resultsPer-row outcome, in request order.
invalidRows that failed validation, with the reason for each.

Conversion attribution

An event becomes a conversion when it carries both identifiers.externalOrderId and a numeric properties.value in major units, such as 49.99. Set properties.currency to an ISO code; it defaults to USD. Migma attributes the conversion to the last email the recipient clicked within the previous five days, and credits that email once. Refunds and cancellations keep the numbers honest. When an event name contains refund or cancelled, Migma records a negative amount, so returned revenue is subtracted rather than counted.
curl https://api.migma.ai/v1/events \
  -H "Authorization: Bearer $MIGMA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: refund-10432" \
  -d '{
    "projectId": "665f1e928c2a9e4d8f123123",
    "name": "order.refunded",
    "identifiers": {
      "email": "casey@example.com",
      "externalOrderId": "order-10432"
    },
    "properties": {
      "value": 49.99,
      "currency": "USD"
    }
  }'

Revenue in campaign stats

When conversions have been attributed to a campaign, GET /v1/campaigns/{id}/stats includes a conversion block, and the same figures appear in campaign analytics in the app when it ships:
{
  "conversions": 12,
  "revenue": 584.88,
  "currency": "USD",
  "source": "events"
}
The conversion block is omitted entirely when nothing has been reported, so a campaign with no attributed revenue shows no conversion figures rather than fake zeros.

API Reference

Review event endpoints, schemas, and permissions.

Webhooks

Receive outbound notifications when Migma activity happens.