Catch API Reference
All endpoints require a Bearer token unless noted. See Authentication.
See Rate Limits for per-minute limits and panic mode.
Bucket endpoints
POST /v1/catch/buckets
Create a webhook bucket.
| Parameter | Type | Required | Description |
|---|---|---|---|
target_url | string | Yes | HTTPS URL to forward webhooks to |
provider | string | No | stripe, github, shopify, or svix |
signing_secret | string | No | Provider’s webhook signing secret |
curl -X POST "https://api.solenoid.systems/v1/catch/buckets" \
-H "Authorization: Bearer sm_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"target_url": "https://your-app.com/webhooks", "provider": "stripe"}'
201 Created. Returns the new bucket with state: "paused". Bucket IDs use adjective-noun-number format.
Bucket limits by tier: Free (1), Starter (5), Pro (25), Scale (100).
GET /v1/catch/buckets
List all buckets for the authenticated user.
curl "https://api.solenoid.systems/v1/catch/buckets" \
-H "Authorization: Bearer sm_your_api_key_here"
GET /v1/catch/buckets/:bucket_id
Get a single bucket.
curl "https://api.solenoid.systems/v1/catch/buckets/brave-elephant-42" \
-H "Authorization: Bearer sm_your_api_key_here"
PATCH /v1/catch/buckets/:bucket_id
Update bucket configuration. All fields optional.
| Parameter | Type | Description |
|---|---|---|
state | string | live or paused |
target_url | string | New forwarding URL |
signing_secret | string | New signing secret |
curl -X PATCH "https://api.solenoid.systems/v1/catch/buckets/brave-elephant-42" \
-H "Authorization: Bearer sm_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{"state": "live"}'
DELETE /v1/catch/buckets/:bucket_id
Delete a bucket and all stored events. Returns 204 No Content.
curl -X DELETE "https://api.solenoid.systems/v1/catch/buckets/brave-elephant-42" \
-H "Authorization: Bearer sm_your_api_key_here"
Ingestion endpoint
POST /v1/catch/:bucket_id
Auth: None. This endpoint is public so webhook providers can send to it directly.
Accepts any JSON payload. Always returns 200 OK to prevent sender retries.
Provider is auto-detected from signature headers:
| Provider | Header |
|---|---|
| Stripe | stripe-signature |
| GitHub | x-hub-signature-256 |
| Shopify | x-shopify-hmac-sha256 |
| Svix | svix-signature, svix-id, svix-timestamp |
Response fields:
verification—valid,invalid, ornone- Invalid signatures are stored but marked
invalid - Rate-limited requests return
200withstatus: "rate_limited" - Panic mode (5x limit exceeded) returns
200withstatus: "panic_mode"for 10 minutes
Event endpoints
GET /v1/catch/:bucket_id/events
List events in a bucket.
| Query param | Type | Description |
|---|---|---|
limit | number | Max events (default 20, max 100) |
cursor | string | Pagination cursor |
provider | string | Filter by provider |
status | string | pending, delivered, or failed |
curl "https://api.solenoid.systems/v1/catch/brave-elephant-42/events?limit=10" \
-H "Authorization: Bearer sm_your_api_key_here"
Pass cursor from the response to fetch the next page. null means no more results.
GET /v1/catch/:bucket_id/events/:event_id
Get a single event including full payload and headers.
curl "https://api.solenoid.systems/v1/catch/brave-elephant-42/events/01HX1234567890ABCDEF" \
-H "Authorization: Bearer sm_your_api_key_here"
POST /v1/catch/:bucket_id/events/:event_id/replay
Replay a single event to the bucket’s target_url. Bucket must be in live state.
curl -X POST "https://api.solenoid.systems/v1/catch/brave-elephant-42/events/01HX1234567890ABCDEF/replay" \
-H "Authorization: Bearer sm_your_api_key_here"
Returns status: "replayed" on success or status: "failed" with the target’s HTTP status code.
DELETE /v1/catch/:bucket_id/events
Bulk delete events.
| Query param | Type | Description |
|---|---|---|
before | string | Delete events before this ISO 8601 timestamp |
curl -X DELETE "https://api.solenoid.systems/v1/catch/brave-elephant-42/events?before=2026-02-01T00:00:00Z" \
-H "Authorization: Bearer sm_your_api_key_here"
Returns {"deleted_count": 42}.
Replay signatures
When Catch replays events to your target_url, it adds these headers:
X-Solenoid-Signature—t=<timestamp>,v1=<hmac>X-Solenoid-Event-Id— original event IDX-Solenoid-Timestamp— original event timestamp
Verify with HMAC-SHA256 over {timestamp}.{payload}:
const crypto = require('crypto')
function verifyReplaySignature(payload, signature, secret) {
const [tPart, v1Part] = signature.split(',')
const timestamp = tPart.split('=')[1]
const expected = v1Part.split('=')[1]
const computed = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${payload}`)
.digest('hex')
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(computed))
}
Retention and limits
See Pricing for tier details.
| Tier | Retention | Max events per bucket |
|---|---|---|
| Free | 24 hours | 100 |
| Starter | 3 days | 1,000 |
| Pro | 30 days | 10,000 |
| Scale | 90 days | 100,000 |
Oldest events are deleted when the per-bucket limit is exceeded.
Metering
| Operation | Cost |
|---|---|
| Webhook ingestion | 1 credit |
| Successful replay | 1 credit |
| Failed replay | Free |
| List/get events | 1 credit |
| Bucket management | Free |
See Pricing for monthly allocations.