Skip to content

Billing and quota

Hooks bills accepted inbound requests on /in/{publicId}. Console reads, test events, retries, and rejected requests are free, so an integration that mostly receives duplicate or unsigned traffic still stays inside its plan.

  • 1,000 accepted requests per verified identity, for life. The grant is tied to the verified email address, not the workspace: deleting and recreating a workspace reuses the same count.
  • Events are kept for 7 days.
  • One workspace, with the endpoint and destination limits shown on the pricing page.
  • When the grant is exhausted, /in/{publicId} returns 429 and stops accepting events until the workspace upgrades. There is no monthly reset.
  • $1 per 10,000 requests per month, sold as 3–100 blocks: $3 (30,000 requests) up to $100 (1,000,000 requests).
  • Requests reset at the end of each billing period and do not roll over.
  • Events are kept for 30 days.
  • Pro adds multiple workspaces, higher endpoint and destination limits, and the task engine surfaces gated to Pro.

Increases take effect immediately and are invoiced right away because the extra allowance is available at once. Decreases are scheduled for the end of the current period, so you keep the quota you already paid for.

Pro workspaces auto-upgrade by default: when a request would cross 100% of the current allowance, Hooks adds the next 10,000-request block, accepts the request, and syncs the new subscription quantity to Stripe within about a minute. The extra $1 lands on the next invoice.

spend_cap_blocks caps auto-upgrade. It defaults to min(100, max(20, current blocks × 2)). Once the allowance reaches the cap, requests get the Pro 429 until the period ends.

Owners can change both settings with PATCH /v1/billing/settings:

{ "autoUpgrade": false }
{ "spendCapBlocks": 40 }

Turning autoUpgrade off makes quota a hard cap. A failed Stripe sync never removes a block that was already granted locally; the queue retries the sync.

Request Counts
Accepted inbound event on /in/{publicId} 1
Signature failure, filtered event, duplicate event 0
Automatic retry, successful or not 0
Request rejected with 429 0
/t/* temporary addresses and /inspect/* 0
Manual replay beyond 10% of monthly inbound volume 0.5 each
Each destination beyond the first three per event 0.25 each
Each extra 64 KiB of payload 1

Free, and Pro at its spend cap, return 429 with a JSON body:

{
"error": "quota_exceeded",
"plan": "free",
"upgrade_url": "https://hooks.events/dashboard/billing",
"message": "Free plan request limit reached. Upgrade to Pro to keep receiving events."
}

The response carries X-Quota-Limit and X-Quota-Remaining. Free lifetime credit never resets, so there is no Retry-After; Pro at its spend cap gets Retry-After pointing at the end of the billing period. Rate-limit 429s are separate: they use 429 RATE_LIMIT_EXCEEDED with Retry-After; see rate limits.

  • Checkout and the Stripe Customer Portal are linked from the console’s Billing page.
  • The Customer Portal changes the block quantity within the same 3–100 range and cancels at period end.
  • A subscription grants Pro while it is active, or while it is past_due inside the 7-day grace window. When a cancellation takes effect, the workspace falls back to Free limits and used lifetime credit is never reissued.
  • Only workspace owners can change billing. Members can view usage.