When the scheduled time arrives, Posthook sends an HTTP POST request to your endpoint. This page covers the request format, how to handle deliveries, and production best practices. The destination URL combines your Project Domain (configured in settings) with the Path specified when scheduling the hook.Documentation Index
Fetch the complete documentation index at: https://docs.posthook.io/llms.txt
Use this file to discover all available pages before exploring further.
api.myapp.com(Domain) +/webhooks/remind(Path) =https://api.myapp.com/webhooks/remind(HTTPS is enforced)
The Request
Posthook sends aPOST request containing your data along with scheduling metadata.
Headers
| Header | Description |
|---|---|
Content-Type | application/json |
Posthook-Id | Unique hook ID (e.g. e5405623-2c1c-460e-9737-c884f7f59035) |
Posthook-Timestamp | Unix timestamp (seconds) of when the hook was posted |
Posthook-Signature | One or more v1,<hex> signatures, space-separated |
Posthook-Ack-URL | Async ack callback URL (async hooks) |
Posthook-Nack-URL | Async nack callback URL (async hooks) |
X-Ph-Signature | Legacy HMAC-SHA256 signature (hex-encoded). See Legacy Header. |
User-Agent | Posthook/1.0 |
Framework Examples
Complete webhook handlers showing how to receive a delivery, verify the signature, and return a response. Each example uses the official SDK for signature verification.Retries
Posthook guarantees at-least-once delivery. If your endpoint returns a non-2xx status code or times out (10-second limit), Posthook retries the delivery based on your project’s retry configuration. You can configure:- Max Retries: Up to 15 attempts (plan-dependent).
- Retry Delay: 5 to 60 seconds between attempts.
Per-hook retry override
Individual hooks can override your project’s retry settings via theretryOverride field.
fixed for constant delay or exponential for increasing delays with backoffFactor, maxDelaySecs, and jitter. See Scheduling: Per-hook retry override for the full field reference.
Idempotency
Because at-least-once delivery can produce rare duplicates under failure conditions, your hook handler should be idempotent. The right approach varies by use case. Some operations are naturally idempotent (e.g., setting a value in a database). Others need explicit deduplication. For cases that need it, include a unique ID in your payload (e.g.,idempotency_key, event_id, or your own business logic ID like reminder_id). You can also use the id field from the hook delivery itself as your idempotency key.
sendReminder errors), the transaction rolls back, the idempotency key is not recorded, and the hook is retried.
For more background on at-least-once delivery and idempotent design, see Twilio’s Exactly-once delivery and Stripe’s Designing with Idempotency.
Handling Long-Running Tasks
Posthook enforces a 10-second timeout on webhook delivery. If your task takes longer than 10 seconds (e.g., generating a PDF, processing a video), your request will time out and be retried. You have two options:Option 1: Async Hooks (Recommended)
Enable Async Hooks on your project and return HTTP 202. Posthook will wait for your ack/nack callback instead of timing out. This gives you built-in timeout management, retry on failure, and visibility into async processing status in the dashboard.Option 2: Queue Locally
If you prefer to manage your own job queue:- Receive the webhook.
- Push the job to an internal background queue (e.g., Redis, SQS, BullMQ).
- Return
200 OKimmediately to Posthook. - Process the job asynchronously in your worker.