Trigger
Fan out a payload to every endpoint subscribed to an event type
Trigger an event type — Nahook fans out a single payload to every active endpoint subscribed to that event type in the API key's workspace (and environment, if the key is environment-scoped). Subscriptions are managed via the Management API or the dashboard.
POST /api/ingest/event/{eventType}
Request
curl -X POST https://us.api.nahook.com/api/ingest/event/order.paid \
-H "Authorization: Bearer nhk_us_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"payload": { "orderId": "ord_123", "status": "paid" },
"metadata": { "source": "checkout-service" }
}'const result = await nahook.trigger("order.paid", {
payload: { orderId: "ord_123", status: "paid" },
metadata: { source: "checkout-service" }, // optional
});result = client.trigger("order.paid", {
"orderId": "ord_123",
"status": "paid",
}, metadata={"source": "checkout-service"}) # optionalresult, err := c.Trigger(ctx, "order.paid", nahook.TriggerOptions{
Payload: map[string]any{"orderId": "ord_123", "status": "paid"},
Metadata: map[string]string{"source": "checkout-service"}, // optional
})import com.nahook.types.TriggerOptions;
import java.util.Map;
var payload = Map.of("orderId", "ord_123", "status", "paid");
var metadata = Map.of("source", "checkout-service");
TriggerResult result = client.trigger("order.paid",
new TriggerOptions(payload, metadata)); // metadata optionalvar result = await client.TriggerAsync("order.paid", new TriggerOptions {
Payload = new Dictionary<string, object> {
["orderId"] = "ord_123",
["status"] = "paid"
},
Metadata = new Dictionary<string, string> { ["source"] = "checkout-service" } // optional
});$result = $client->trigger("order.paid", [
"payload" => ["orderId" => "ord_123", "status" => "paid"],
"metadata" => ["source" => "checkout-service"], // optional
]);result = client.trigger("order.paid",
payload: { order_id: "ord_123", status: "paid" },
metadata: { "source" => "checkout-service" }) # optionaluse std::collections::HashMap;
let result = client.trigger("order.paid", TriggerOptions {
payload: serde_json::json!({
"orderId": "ord_123",
"status": "paid"
}),
metadata: Some(HashMap::from([
("source".into(), "checkout-service".into()),
])), // optional
}).await?;Body
| Field | Type | Required | Notes |
|---|---|---|---|
payload | object | yes | Arbitrary JSON. Each subscribed endpoint receives the same payload. |
metadata | object<string, string> | no | Up to 5 keys. Values must be strings. Attached to every fanned-out delivery for filtering / debugging. |
The API key must be workspace-scoped (not endpoint-scoped) — fan-out needs to enumerate subscriptions across the workspace. A 400 is returned otherwise.
Response
202 Accepted
{
"eventTypeId": "evt_order_paid",
"deliveryIds": ["del_a1", "del_b2", "del_c3"],
"status": "accepted",
"failures": []
}| Field | Type | Notes |
|---|---|---|
eventTypeId | string | Internal ID of the matched event type. |
deliveryIds | string[] | One entry per endpoint that was successfully queued. |
status | string | Always "accepted" on a 202 — even partial fan-outs. See failures. |
failures | array | Empty when every subscribed endpoint was enqueued. Populated on partial fan-out (see below). |
Partial fan-out
If at least one subscribed endpoint was queued, Nahook returns 202 even when others couldn't be enqueued (e.g., FK violation, statement timeout). The failures array describes each one. Successfully-queued siblings have still been published.
{
"eventTypeId": "evt_order_paid",
"deliveryIds": ["del_a1"],
"status": "accepted",
"failures": [
{ "endpointId": "ep_xyz", "code": "internal_error", "message": "Failed to publish to Kafka" }
]
}If no endpoint was queued (no subscriptions, every endpoint failed, etc.), deliveryIds is empty and the status code is still 202. Check whether deliveryIds is empty to detect "nothing was delivered."
Errors
| Status | Code | When |
|---|---|---|
400 | invalid_api_key | Used a key that isn't workspace-scoped. Fan-out requires workspace access. |
401 | unauthorized | Missing, malformed, or revoked API key. |
413 | payload_too_large | Payload exceeded your plan's per-payload cap. |
429 | rate_limited | Workspace or per-API-key rate limit hit. |
504 | ingest_timeout | Server-side ingest exceeded 5 s. Safe to retry. |
trigger does not accept an idempotencyKey — duplicate calls produce duplicate deliveries. If you need dedup semantics across fan-outs, do it on your side before calling, or use Send against a specific endpoint instead.