Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.offthehook.dev/llms.txt

Use this file to discover all available pages before exploring further.

Use this endpoint to create a new subscription that delivers webhook events to your HTTPS endpoint. Once created, Off the Hook immediately begins matching on-chain activity against the subscription’s address filters and queues deliveries signed with the subscription’s secret. The secret is returned only in this response — store it somewhere safe before the request completes.

Request

POST /v1/subscriptions

Headers

HeaderRequiredDescription
AuthorizationYesBearer oth_YOUR_API_KEY
Content-TypeYesapplication/json
Idempotency-KeyNoUnique string to make this request idempotent. Re-sending the same key returns the original response without creating a second subscription.

Body

destination
object
required
Webhook delivery target. Only HTTPS is supported today; additional destination types (SQS, Pub/Sub) are planned.
events
string[]
required
One or more event kinds to subscribe to. Must be non-empty. Example: ["wallet.transfer.broadcasted"]. See Supported events for valid values.
status
string
default:"enabled"
Whether the subscription should immediately receive events. Accepted values: "enabled" or "disabled". Defaults to "enabled" when omitted.
description
string
A human-readable label for your own reference. Not interpreted by Off the Hook.

Supported events

Event kindStatus
wallet.transfer.broadcastedAvailable
service.pingAvailable (fired by /test)
wallet.transfer.confirmedPlanned
wallet.transfer.failedPlanned

Example request

curl -X POST https://api.offthehook.dev/v1/subscriptions \
  -H "Authorization: Bearer oth_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: my-unique-key-123" \
  -d '{
    "destination": {
      "type": "https",
      "url": "https://your-server.example.com/webhooks"
    },
    "events": ["wallet.transfer.broadcasted"],
    "status": "enabled",
    "description": "Production wallet monitor"
  }'

Response

201 Created
{
  "id": "sub_2QkP9aB7xN...",
  "destination": {
    "type": "https",
    "url": "https://your-server.example.com/webhooks",
    "secret": "whsec_..."
  },
  "events": ["wallet.transfer.broadcasted"],
  "filters": {
    "addresses": [],
    "hasMore": false
  },
  "status": "enabled",
  "description": "Production wallet monitor",
  "dateCreated": "2026-05-08T12:00:00Z",
  "dateUpdated": "2026-05-08T12:00:00Z"
}
The secret field is only returned when creating a subscription or rotating the secret. Store it immediately — subsequent GET requests will not include it.

Response fields

id
string
required
Unique subscription identifier. Always prefixed with sub_.
destination
object
required
Webhook delivery target.
events
string[]
required
The event kinds this subscription will receive.
filters
object
required
Address filters attached to this subscription.
status
string
required
"enabled" or "disabled".
description
string
required
The human-readable label supplied at creation time. Empty string if none was provided.
dateCreated
string
required
ISO 8601 timestamp of when the subscription was created.
dateUpdated
string
required
ISO 8601 timestamp of the most recent update.

Errors

CodeDescription
invalid_requestThe request body is missing a required field, contains an invalid value, or the JSON is malformed.
ssrf_blockedThe destination.url resolved to a private or reserved IP range. The error detail includes the blocked IP and CIDR.
unsupported_eventOne or more entries in events are not recognized. The error detail names the unsupported value.
description_too_longThe description field exceeds the maximum allowed length.
idempotency_in_flightAnother request with the same Idempotency-Key is still being processed. Wait and retry.
idempotency_conflictA completed request with the same Idempotency-Key exists but had a different request body. Use a new key.
unauthorizedThe Authorization header is missing or the API key is invalid.