Overview
Send webhook payloads to Nahook over HTTP — auth, base URL, and SDK setup
The Ingestion API is what you call to send a webhook payload into Nahook. Once accepted, Nahook handles signing, delivery, retries, and analytics on your behalf. There are four operations, mapped 1:1 to the methods on every official SDK:
| Operation | Path | What it does |
|---|---|---|
| Send | POST /api/ingest/{endpointId} | Deliver a payload to a single endpoint. |
| Trigger | POST /api/ingest/event/{eventType} | Fan out a payload to every endpoint subscribed to an event type. |
| Send Batch | POST /api/ingest/batch | Up to 20 direct sends in a single request. |
| Trigger Batch | POST /api/ingest/event/batch | Up to 20 fan-outs in a single request. |
Base URL
https://us.api.nahook.comThe Ingestion API is regional. Today the US region (us) is the only one publicly available; additional regions are planned. Always send a request to the region matching your API key — the region is encoded in the key prefix (nhk_us_…).
Authentication
All requests require a workspace API key in the Authorization header:
Authorization: Bearer nhk_us_YOUR_API_KEYAPI keys are created in Settings → API Keys in the dashboard. Each key is scoped to a workspace and (optionally) to a specific environment.
API keys (nhk_…) are for the Ingestion API. Management tokens (nhm_…) are used by the Management API for managing workspace resources. They are not interchangeable.
Install
Every SDK exposes the same four methods (send, trigger, sendBatch, triggerBatch). The examples on each resource page show the SDK call alongside the raw cURL request.
npm install @nahook/clientpip install nahookgo get github.com/getnahook/nahook-go<dependency>
<groupId>com.nahook</groupId>
<artifactId>nahook-java</artifactId>
<version>0.2.0</version>
</dependency>dotnet add package Nahookcomposer require nahook/nahook-phpgem install nahookcargo add nahookSetup
# Every request needs your API key as a Bearer token.
curl https://us.api.nahook.com/api/ingest/ep_abc123 \
-H "Authorization: Bearer nhk_us_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "payload": { "hello": "world" } }'import { NahookClient } from "@nahook/client";
const nahook = new NahookClient("nhk_us_YOUR_API_KEY");from nahook import NahookClient
client = NahookClient("nhk_us_YOUR_API_KEY")import (
"context"
"github.com/getnahook/nahook-go/client"
)
c, _ := client.New("nhk_us_YOUR_API_KEY")import com.nahook.NahookClient;
var client = new NahookClient("nhk_us_YOUR_API_KEY");using Nahook;
var client = new NahookClient("nhk_us_YOUR_API_KEY");use Nahook\NahookClient;
$client = new NahookClient("nhk_us_YOUR_API_KEY");require "nahook"
client = Nahook::Client.new("nhk_us_YOUR_API_KEY")use nahook::{NahookClient, SendOptions, TriggerOptions};
let client = NahookClient::new("nhk_us_YOUR_API_KEY")?;Limits
Payload size
Each payload is capped by your plan. Requests exceeding the cap return 413 payload_too_large.
| Plan | Per-payload cap |
|---|---|
| Hobby | 32 KB |
| Starter | 64 KB |
| Pro | 256 KB |
| Scale | 256 KB |
| Enterprise | Custom — contact sales |
In batch operations the cap applies per-item, not to the whole batch envelope.
Other limits
| Limit | Value | Notes |
|---|---|---|
| Batch items | 1–20 | Applies to both send-batch and trigger-batch. |
| Metadata keys | 5 | Per trigger / trigger-batch call. Values must be strings. |
| Idempotency key window | 15 min | Direct send only. See Idempotency. |
| Ingest timeout | 5 s | Server-side. Beyond this the request returns 504. |
Idempotency
The direct Send and Send Batch operations accept an idempotencyKey. When supplied, two requests with the same key within 15 minutes are deduplicated — the second request returns the same deliveryId as the first instead of creating a new delivery. Without a key, every request creates a new delivery (even with identical payloads).
The fan-out operations behave differently:
- Trigger doesn't accept the field at all.
- Trigger Batch accepts the field for input-shape parity with
send-batch, but today the value is ignored — don't rely on dedup behavior ontrigger-batch.
Response semantics
Successful ingestion returns 202 Accepted. The body confirms what was accepted, but the delivery hasn't been attempted yet — the worker processes it asynchronously and you can follow up via the Management API or the dashboard delivery log.
Batch endpoints have two success codes:
202— every item succeeded.207— at least one item failed but the request itself was valid; per-item results live initems[].status/items[].error. The successful siblings have still been published.
The single fan-out endpoint (trigger) reports partial success differently: it returns 202 with a non-empty failures array. Successfully-fanned-out deliveries have still been queued; the failures array describes which subscribed endpoints couldn't be enqueued.
Errors
Errors share a common envelope:
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded. Retry in 30s."
}
}| Status | Code | When |
|---|---|---|
400 | invalid_api_key | Used a key that isn't workspace-scoped on a fan-out operation. |
401 | unauthorized | Missing, malformed, or revoked API key. |
404 | not_found | (Direct send only) The endpoint doesn't exist or isn't in your environment. |
413 | payload_too_large | Payload exceeded your plan's per-payload cap. |
429 | rate_limited | Workspace or per-API-key rate limit hit. Respect the Retry-After header. |
504 | ingest_timeout | Server-side ingest exceeded 5 s. Retry. |
Retryable status codes (429, 504) carry a Retry-After header where applicable. SDKs handle retries automatically with backoff; for direct HTTP callers, wait and replay the same request — using an idempotencyKey if you don't want to risk duplicates on the direct-send path.