Ingestion API

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:

OperationPathWhat it does
SendPOST /api/ingest/{endpointId}Deliver a payload to a single endpoint.
TriggerPOST /api/ingest/event/{eventType}Fan out a payload to every endpoint subscribed to an event type.
Send BatchPOST /api/ingest/batchUp to 20 direct sends in a single request.
Trigger BatchPOST /api/ingest/event/batchUp to 20 fan-outs in a single request.

Base URL

https://us.api.nahook.com

The 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_KEY

API 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/client
pip install nahook
go get github.com/getnahook/nahook-go
<dependency>
  <groupId>com.nahook</groupId>
  <artifactId>nahook-java</artifactId>
  <version>0.2.0</version>
</dependency>
dotnet add package Nahook
composer require nahook/nahook-php
gem install nahook
cargo add nahook

Setup

# 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.

PlanPer-payload cap
Hobby32 KB
Starter64 KB
Pro256 KB
Scale256 KB
EnterpriseCustom — contact sales

In batch operations the cap applies per-item, not to the whole batch envelope.

Other limits

LimitValueNotes
Batch items1–20Applies to both send-batch and trigger-batch.
Metadata keys5Per trigger / trigger-batch call. Values must be strings.
Idempotency key window15 minDirect send only. See Idempotency.
Ingest timeout5 sServer-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 on trigger-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 in items[].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."
  }
}
StatusCodeWhen
400invalid_api_keyUsed a key that isn't workspace-scoped on a fan-out operation.
401unauthorizedMissing, malformed, or revoked API key.
404not_found(Direct send only) The endpoint doesn't exist or isn't in your environment.
413payload_too_largePayload exceeded your plan's per-payload cap.
429rate_limitedWorkspace or per-API-key rate limit hit. Respect the Retry-After header.
504ingest_timeoutServer-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.