Throughput and rate limits
The three separate limits in SolidHooks, what each one returns, and which are errors and which only slow things down.
"Rate limit" covers three different mechanisms here, and they behave differently. One limits calls to the management API, one limits inbound webhooks, and one paces outbound deliveries. Only the first two ever return an error.
API requests
An API key (sdhk_sk_...) is limited to 600 requests per minute per key. Beyond that the API returns 429. Back off and retry.
The dashboard's /auth/* account endpoints carry their own per-IP limits, which you will not meet when calling /v1 with a key.
Inbound webhooks
Two things can reject an inbound request at the ingest origin (https://sdhk.events/<maskId>), both before anything is stored.
Ingest throughput
| Limit | Scope | Notes |
|---|---|---|
Source rateLimit | One source | Requests per second. 0 means unlimited and is the default, so most sources never see it. Read-only on the API: support sets it. |
| Organisation clamp | Whole organisation | Can be applied to a whole organisation. Checked after the source's limit. |
When either trips, ingest responds 429 with code RATE_LIMITED, a body of data: { limit, remaining, retryAfterSeconds }, and the headers Retry-After, X-RateLimit-Limit and X-RateLimit-Remaining. The sender still holds the payload, so this is an error on purpose: back off for Retry-After seconds and resend.
Monthly delivery quota
Your plan includes a number of deliveries per usage window. The billable unit is the delivery (one event routed to one connection), so fan-out to three connections counts three. Retries are free, replays are billed, and duplicate (idempotent) requests are never counted.
What happens at the limit depends on the plan:
- Hard-capped plans (the free Hobby tier) reject ingest with
429 QUOTA_EXCEEDEDanddata: { limit, current, resetAt }until the window resets or you upgrade. Event replay is gated the same way. - Paid plans with overage enabled never hard-cap. Deliveries beyond the included quota are metered and billed as pay-as-you-go.
The window is the subscription's billing period for subscribed organisations and the UTC calendar month otherwise. GET /v1/billing/usage shows usage against the quota and resetAt.
Outbound delivery pacing
Delivery pacing limits how fast SolidHooks sends to your endpoint. It is never an error. A delivery over the rate is queued and sent when capacity frees up. Nothing is dropped, no retry attempt is consumed, and you do not need to act.
Two limits apply, layered:
- Plan pacing:
maxDeliveriesPerSecondandburstDeliveriesPerSecondin the plan's entitlements, across your whole organisation.nullmeans unlimited. - Destination pacing:
rateLimitandrateLimitPeriodon a destination, which you set to protect that endpoint.rateLimitPeriodissecond,minute,hourorday.
| Plan | maxDeliveriesPerSecond | burstDeliveriesPerSecond |
|---|---|---|
| Hobby | 10 | 20 |
| Launch | 50 | 100 |
| Scale | 200 | 400 |
| Enterprise | unlimited | unlimited |
curl -s -X PATCH "$API/v1/destinations/dest_..." \
-H "authorization: Bearer $SDHK_KEY" \
-H 'content-type: application/json' \
-d '{ "data": { "rateLimit": 100, "rateLimitPeriod": "minute" } }'A held delivery has status: "throttled" and throttledReason: "rate_limit". This is different from destination_busy, which is a delivery parked because your endpoint answered 429, 502 or 504 (see Retries). A delivery that was ever held keeps a throttledAt timestamp, even after it succeeds.
GET /v1/deliveries/stats returns the live queue as { pending, throttled }, the number of deliveries waiting right now. Historical outcome counts are in GET /v1/stats/dashboard.
Retrying a throttled delivery
POST /v1/deliveries/{id}/retry returns 409 CONFLICT for a throttled delivery. It is already queued and will send on its own.
Connector endpoints
The public connector endpoints (/v1/connectors/bootstrap and /v1/connectors/replicas/heartbeat) allow 5 requests per second per client IP with a burst of 20, applied before the token is checked. After the token resolves, bootstrap is limited to about one per 5 seconds per connector and heartbeats to one per second per replica. See Private delivery.
Next steps
- Retries — the retry schedule and how responses are interpreted
- Plans — entitlements and quota per plan
- Errors — error codes across the API
- Destinations — set
rateLimiton a destination