Skip to content
Gave

Webhook endpoints

Register the endpoint your webhooks go to. You have one endpoint for now. Gave generates its signing secret and shows it once, when the endpoint is created or its secret is rotated: store it straight away.

Register your endpoint

Give it an ID of your choice and an https URL with a public host name: no IP address, local or internal name, credentials or fragment. Gave doesn't follow redirects: a 3xx answer is a failed delivery, retried.

curl https://api.sandbox.gave.sh/v1/webhook-endpoints \
  -H "x-api-key: $GAVE_API_KEY" \
  -H "content-type: application/json" \
  -d @create-endpoint.json
create-endpoint.json
{ "id": "main", "url": "https://hooks.acme.example/gave" }

It answers 201 Created, with the signing secret:

WebhookEndpointCreated
{
  "endpoint": { "id": "main", "url": "https://hooks.acme.example/gave", "createdAt": "2026-10-11T09:00:00.000Z" },
  "secret": "gave_whsec_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
  "duplicate": false
}

The same request again answers duplicate: true, without the secret; the same ID with another URL is a 409, and a second endpoint a 422. Deliveries start within a minute.

Change its URL

curl -X PATCH https://api.sandbox.gave.sh/v1/webhook-endpoints/main \
  -H "x-api-key: $GAVE_API_KEY" \
  -H "content-type: application/json" \
  -d '{ "url": "https://hooks.acme.example/gave/v2" }'

The secret doesn't change. Deliveries follow within a minute.

Rotate its secret

curl -X POST https://api.sandbox.gave.sh/v1/webhook-endpoints/main/rotate-secret \
  -H "x-api-key: $GAVE_API_KEY"
WebhookSecretRotated
{
  "endpoint": {
    "id": "main",
    "url": "https://hooks.acme.example/gave",
    "createdAt": "2026-10-11T09:00:00.000Z",
    "previousSecretExpiresAt": "2026-10-12T10:00:00.000Z"
  },
  "secret": "gave_whsec_fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210"
}

The new secret signs deliveries within a minute. Each secret it replaces keeps signing for 24 hours from its rotation, up to four of them, until previousSecretExpiresAt for the last: the x-gave-signature header carries one v1 per secret. Accept any you hold while you deploy the new one; the signature check does. Each call makes a new secret: if a rotation's answer is lost, rotate again, and the secret you still use keeps working. To drop a leaked secret, rotate five times: the leaked one goes.

Read it, delete it

GET /v1/webhook-endpoints lists your endpoints, and GET /v1/webhook-endpoints/{id} reads one; neither shows the secret. DELETE /v1/webhook-endpoints/{id} deletes it: deliveries stop within a minute. Without an endpoint, Gave delivers nothing, and your users' state stays readable through the API.