Ingestion API

Trigger Batch

Fan out up to 20 event-type payloads in a single request

Trigger multiple event types in one request — 1 to 20 items per call. Each item fans out to every endpoint subscribed to its event type, independently of the other items.

POST /api/ingest/event/batch

Request

curl -X POST https://us.api.nahook.com/api/ingest/event/batch \
  -H "Authorization: Bearer nhk_us_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "eventType": "order.paid", "payload": { "orderId": "ord_1" } },
      { "eventType": "user.created", "payload": { "userId": "usr_2" }, "metadata": { "source": "signup" } }
    ]
  }'
const result = await nahook.triggerBatch([
  { eventType: "order.paid", payload: { orderId: "ord_1" } },
  { eventType: "user.created", payload: { userId: "usr_2" }, metadata: { source: "signup" } },
]);
result = client.trigger_batch([
    {"eventType": "order.paid", "payload": {"orderId": "ord_1"}},
    {"eventType": "user.created", "payload": {"userId": "usr_2"}, "metadata": {"source": "signup"}},
])
result, err := c.TriggerBatch(ctx, []nahook.TriggerBatchItem{
    {EventType: "order.paid", Payload: map[string]any{"orderId": "ord_1"}},
    {EventType: "user.created", Payload: map[string]any{"userId": "usr_2"}, Metadata: map[string]string{"source": "signup"}},
})
import com.nahook.types.TriggerBatchItem;
import java.util.List;
import java.util.Map;

BatchResult result = client.triggerBatch(List.of(
    new TriggerBatchItem("order.paid", Map.of("orderId", "ord_1")),
    new TriggerBatchItem("user.created", Map.of("userId", "usr_2"), Map.of("source", "signup"))
));
var result = await client.TriggerBatchAsync(new[] {
    new TriggerBatchItem {
        EventType = "order.paid",
        Payload = new Dictionary<string, object> { ["orderId"] = "ord_1" }
    },
    new TriggerBatchItem {
        EventType = "user.created",
        Payload = new Dictionary<string, object> { ["userId"] = "usr_2" },
        Metadata = new Dictionary<string, string> { ["source"] = "signup" }
    }
});
$result = $client->triggerBatch([
    ["eventType" => "order.paid", "payload" => ["orderId" => "ord_1"]],
    ["eventType" => "user.created", "payload" => ["userId" => "usr_2"], "metadata" => ["source" => "signup"]],
]);
result = client.trigger_batch([
  { event_type: "order.paid", payload: { order_id: "ord_1" } },
  { event_type: "user.created", payload: { user_id: "usr_2" }, metadata: { "source" => "signup" } }
])
use nahook::types::TriggerBatchItem;
use std::collections::HashMap;

let result = client.trigger_batch(vec![
    TriggerBatchItem {
        event_type: "order.paid".into(),
        payload: serde_json::json!({"orderId": "ord_1"}),
        metadata: None,
    },
    TriggerBatchItem {
        event_type: "user.created".into(),
        payload: serde_json::json!({"userId": "usr_2"}),
        metadata: Some(HashMap::from([("source".into(), "signup".into())])),
    },
]).await?;

Body

FieldTypeRequiredNotes
itemsarrayyes1 to 20 items. Each item fans out independently.
items[].eventTypestringyesEvent type name (e.g. order.paid).
items[].payloadobjectyesArbitrary JSON, delivered to every subscribed endpoint.
items[].metadataobject<string, string>noUp to 5 keys, string values. Attached to every fanned-out delivery for this item.
items[].idempotencyKeystringnoAccepted for input-shape parity with Send Batch, but the value is ignored today — no-op.

The API key must be workspace-scoped — same rule as the single Trigger. Each item's payload is capped by your plan's per-payload limit; a batch can hold up to 20 items.

Response

202 Accepted (all items queued) or 207 Multi-Status (at least one item failed).

{
  "items": [
    {
      "index": 0,
      "eventTypeId": "evt_order_paid",
      "deliveryIds": ["del_a1", "del_b2"],
      "status": "accepted",
      "failures": []
    },
    {
      "index": 1,
      "status": "accepted",
      "error": { "code": "not_found", "message": "Event type not found" }
    }
  ]
}
FieldTypeNotes
items[].indexintegerPosition in the request items array — use it to correlate.
items[].eventTypeIdstringPresent on successful items only.
items[].deliveryIdsstring[]One entry per endpoint that was queued. May be empty if no endpoints are subscribed.
items[].statusstring"accepted" for processed items.
items[].failuresarrayPer-endpoint enqueue failures within a single fan-out item — same shape as the single Trigger endpoint's failures field.
items[].errorobjectPresent when the entire item failed (e.g. unknown event type). Mutually exclusive with the other success fields.

Like Send Batch:

  • 202 — every item was processed.
  • 207 — at least one item failed. Successful items are still queued.

Errors

Batch-level errors (the whole request fails before any item is processed):

StatusCodeWhen
400invalid_requestMissing items, empty list, or more than 20 items.
400invalid_api_keyUsed a key that isn't workspace-scoped.
401unauthorizedMissing, malformed, or revoked API key.
429rate_limitedWorkspace or per-API-key rate limit hit.
504ingest_timeoutServer-side ingest exceeded 5 s. Safe to retry.

Per-item errors live in items[].error. Common ones: not_found (unknown event type), payload_too_large, internal_error.