Skip to content

Webhooks API

Get notified when envelopes and recipients change. Deliveries are signed with your endpoint secret.

On this page

List webhook endpoints

GET/v1/webhooks

Your webhook endpoints (up to 20 per account).

Required scope:webhooks:read

Query parameters

  • pageinteger

    Page number, starting at 1.

    default 1

  • per_pageinteger

    Items per page.

    default 20

Response

200A page of endpoints.
Response objectWebhookEndpointList

A page of webhook endpoints.

  • objectstring= "list"
  • dataarray of WebhookEndpoint
    Child attributes (WebhookEndpoint)
    • objectstring= "webhook_endpoint"
    • idstring · uuid
    • urlstring · uri
    • descriptionstring | null
    • eventsarray of string
    • enabledboolean

      Switched off automatically after 20 consecutive failed deliveries.

    • failure_countinteger

      Consecutive failed attempts; reset by a success.

    • last_success_atstring · date-time | null
    • last_failure_atstring · date-time | null
    • created_atstring · date-time
  • pageinteger
  • per_pageinteger
  • totalinteger
  • has_moreboolean

    Whether another page follows.

Response headers: X-Request-Id, Signkoi-Version, X-RateLimit-Limit, X-RateLimit-Remaining.

Errors

  • 401Missing, invalid, expired or revoked API key (api_key_missing, invalid_api_key).
  • 403The key lacks a required scope (insufficient_scope) or the account is suspended (account_suspended).
  • 429Too many requests (rate_limited): your key's per-minute limit, or an endpoint's own limit. Wait for Retry-After seconds.
  • 500Something went wrong on our side (internal_error). Safe to retry with the same Idempotency-Key.

Every error uses the error object.

Example request

curl https://signkoi.com/api/v1/webhooks \
  -H "Authorization: Bearer $SIGNKOI_API_KEY"

Example response

200 · application/json
{
  "object": "list",
  "data": [
    {
      "object": "webhook_endpoint",
      "id": "6d1e9f3a-4b2c-4a87-9e5d-0f7b3c8a2d54",
      "url": "https://example.com/webhooks/signkoi",
      "description": "Production CRM sync",
      "events": [
        "envelope.completed",
        "envelope.declined",
        "recipient.completed"
      ],
      "enabled": true,
      "failure_count": 0,
      "last_success_at": "2026-11-14T09:31:02Z",
      "last_failure_at": null,
      "created_at": "2026-11-01T08:00:00Z"
    }
  ],
  "page": 1,
  "per_page": 20,
  "total": 1,
  "has_more": false
}

Create a webhook endpoint

POST/v1/webhooks

Registers an HTTPS URL to receive the events you choose. The response includes the signing secret — the only time it is shown. Up to 20 endpoints per account.

Required scope:webhooks:write

Headers

  • Idempotency-Keystring

    Any unique string (1–255 chars), e.g. a UUID. Retrying with the same key and body within 24 hours returns the original response instead of repeating the action.

Request body application/json

Body (required)CreateWebhookRequest
  • urlstring · urirequired

    Public HTTPS URL. Private, loopback and link-local addresses are refused.

    max 2048 chars

  • descriptionstring | null

    max 255 chars

  • eventsarray of stringrequired

    min 1 items

  • enabledboolean

    default true

Response

201The endpoint, with its secret.
Response objectWebhookEndpointWithSecret

Returned only on create and rotate-secret: the only time you see the signing secret.

  • objectstring= "webhook_endpoint"
  • idstring · uuid
  • urlstring · uri
  • descriptionstring | null
  • eventsarray of string
  • enabledboolean

    Switched off automatically after 20 consecutive failed deliveries.

  • failure_countinteger

    Consecutive failed attempts; reset by a success.

  • last_success_atstring · date-time | null
  • last_failure_atstring · date-time | null
  • created_atstring · date-time
  • secretstring

    Signing secret (whsec_…). Store it securely; it is not shown again.

Response headers: X-Request-Id, Signkoi-Version, X-RateLimit-Limit, X-RateLimit-Remaining.

Errors

  • 401Missing, invalid, expired or revoked API key (api_key_missing, invalid_api_key).
  • 403The key lacks a required scope (insufficient_scope) or the account is suspended (account_suspended).
  • 422Invalid request (validation_failed, e.g. a private or non-HTTPS url), or you already have 20 endpoints (webhook_limit_reached, param url).
  • 429Too many requests (rate_limited): your key's per-minute limit, or an endpoint's own limit. Wait for Retry-After seconds.
  • 500Something went wrong on our side (internal_error). Safe to retry with the same Idempotency-Key.

Every error uses the error object.

Example request

curl -X POST https://signkoi.com/api/v1/webhooks \
  -H "Authorization: Bearer $SIGNKOI_API_KEY" \
  -H "Idempotency-Key: 5f1d7c1e-0b8a-4c2e-9f3d-61a2b7e4c905" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks/signkoi",
    "description": "Production CRM sync",
    "events": [
      "envelope.completed",
      "envelope.declined",
      "recipient.completed"
    ]
  }'

Example response

201 · application/json
{
  "object": "webhook_endpoint",
  "id": "6d1e9f3a-4b2c-4a87-9e5d-0f7b3c8a2d54",
  "url": "https://example.com/webhooks/signkoi",
  "description": "Production CRM sync",
  "events": [
    "envelope.completed",
    "envelope.declined",
    "recipient.completed"
  ],
  "enabled": true,
  "failure_count": 0,
  "last_success_at": "2026-11-14T09:31:02Z",
  "last_failure_at": null,
  "created_at": "2026-11-01T08:00:00Z",
  "secret": "whsec_3vY9pQ2mK7tR1xW8cL5nB0dF4hJ6gS2aZ"
}

Retrieve a webhook endpoint

GET/v1/webhooks/{id}

Required scope:webhooks:read

Path parameters

  • idstring · uuidrequired

    Webhook endpoint id.

Response

200The endpoint.
Response objectWebhookEndpoint
  • objectstring= "webhook_endpoint"
  • idstring · uuid
  • urlstring · uri
  • descriptionstring | null
  • eventsarray of string
  • enabledboolean

    Switched off automatically after 20 consecutive failed deliveries.

  • failure_countinteger

    Consecutive failed attempts; reset by a success.

  • last_success_atstring · date-time | null
  • last_failure_atstring · date-time | null
  • created_atstring · date-time

Response headers: X-Request-Id, Signkoi-Version, X-RateLimit-Limit, X-RateLimit-Remaining.

Errors

  • 401Missing, invalid, expired or revoked API key (api_key_missing, invalid_api_key).
  • 403The key lacks a required scope (insufficient_scope) or the account is suspended (account_suspended).
  • 404No such resource, or it belongs to someone else (resource_missing, e.g. "No such envelope." / "No such recipient.").
  • 429Too many requests (rate_limited): your key's per-minute limit, or an endpoint's own limit. Wait for Retry-After seconds.
  • 500Something went wrong on our side (internal_error). Safe to retry with the same Idempotency-Key.

Every error uses the error object.

Example request

curl https://signkoi.com/api/v1/webhooks/6d1e9f3a-4b2c-4a87-9e5d-0f7b3c8a2d54 \
  -H "Authorization: Bearer $SIGNKOI_API_KEY"

Example response

200 · application/json
{
  "object": "webhook_endpoint",
  "id": "6d1e9f3a-4b2c-4a87-9e5d-0f7b3c8a2d54",
  "url": "https://example.com/webhooks/signkoi",
  "description": "Production CRM sync",
  "events": [
    "envelope.completed",
    "envelope.declined",
    "recipient.completed"
  ],
  "enabled": true,
  "failure_count": 0,
  "last_success_at": "2026-11-14T09:31:02Z",
  "last_failure_at": null,
  "created_at": "2026-11-01T08:00:00Z"
}

Update a webhook endpoint

PATCH/v1/webhooks/{id}

Change the URL, description or events, or switch the endpoint on or off.

Required scope:webhooks:write

Path parameters

  • idstring · uuidrequired

    Webhook endpoint id.

Request body application/json

Body (required)UpdateWebhookRequest
  • urlstring · uri

    max 2048 chars

  • descriptionstring | null

    max 255 chars

  • eventsarray of string

    min 1 items

  • enabledboolean

    Re-enable an endpoint that was switched off after repeated failures (resets the failure count).

Response

200The updated endpoint.

Returns the WebhookEndpoint object — its attributes are listed under Retrieve a webhook endpoint.

Response headers: X-Request-Id, Signkoi-Version, X-RateLimit-Limit, X-RateLimit-Remaining.

Errors

  • 401Missing, invalid, expired or revoked API key (api_key_missing, invalid_api_key).
  • 403The key lacks a required scope (insufficient_scope) or the account is suspended (account_suspended).
  • 404No such resource, or it belongs to someone else (resource_missing, e.g. "No such envelope." / "No such recipient.").
  • 422Invalid parameters (validation_failed, with param and errors) or a business rule failed (e.g. missing_signature_field).
  • 429Too many requests (rate_limited): your key's per-minute limit, or an endpoint's own limit. Wait for Retry-After seconds.
  • 500Something went wrong on our side (internal_error). Safe to retry with the same Idempotency-Key.

Every error uses the error object.

Example request

curl -X PATCH https://signkoi.com/api/v1/webhooks/6d1e9f3a-4b2c-4a87-9e5d-0f7b3c8a2d54 \
  -H "Authorization: Bearer $SIGNKOI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      "envelope.completed",
      "envelope.declined",
      "envelope.voided"
    ],
    "enabled": true
  }'

Example response

200 · application/json
{
  "object": "webhook_endpoint",
  "id": "6d1e9f3a-4b2c-4a87-9e5d-0f7b3c8a2d54",
  "url": "https://example.com/webhooks/signkoi",
  "description": "Production CRM sync",
  "events": [
    "envelope.completed",
    "envelope.declined",
    "envelope.voided"
  ],
  "enabled": true,
  "failure_count": 0,
  "last_success_at": "2026-11-14T09:31:02Z",
  "last_failure_at": null,
  "created_at": "2026-11-01T08:00:00Z"
}

Delete a webhook endpoint

DEL/v1/webhooks/{id}

Stops all deliveries to the endpoint and deletes it with its delivery history.

Required scope:webhooks:write

Path parameters

  • idstring · uuidrequired

    Webhook endpoint id.

Response

204Deleted.

Response headers: X-Request-Id, Signkoi-Version, X-RateLimit-Limit, X-RateLimit-Remaining.

Errors

  • 401Missing, invalid, expired or revoked API key (api_key_missing, invalid_api_key).
  • 403The key lacks a required scope (insufficient_scope) or the account is suspended (account_suspended).
  • 404No such resource, or it belongs to someone else (resource_missing, e.g. "No such envelope." / "No such recipient.").
  • 429Too many requests (rate_limited): your key's per-minute limit, or an endpoint's own limit. Wait for Retry-After seconds.
  • 500Something went wrong on our side (internal_error). Safe to retry with the same Idempotency-Key.

Every error uses the error object.

Example request

curl -X DELETE https://signkoi.com/api/v1/webhooks/6d1e9f3a-4b2c-4a87-9e5d-0f7b3c8a2d54 \
  -H "Authorization: Bearer $SIGNKOI_API_KEY"

Rotate the signing secret

POST/v1/webhooks/{id}/rotate-secret

Replaces the signing secret. The new secret is returned once; deliveries are signed with it from now on, so update your receiver straight away.

Required scope:webhooks:write

Path parameters

  • idstring · uuidrequired

    Webhook endpoint id.

Headers

  • Idempotency-Keystring

    Any unique string (1–255 chars), e.g. a UUID. Retrying with the same key and body within 24 hours returns the original response instead of repeating the action.

Response

200The endpoint, with its new secret.

Returns the WebhookEndpointWithSecret object — its attributes are listed under Create a webhook endpoint.

Response headers: X-Request-Id, Signkoi-Version, X-RateLimit-Limit, X-RateLimit-Remaining.

Errors

  • 401Missing, invalid, expired or revoked API key (api_key_missing, invalid_api_key).
  • 403The key lacks a required scope (insufficient_scope) or the account is suspended (account_suspended).
  • 404No such resource, or it belongs to someone else (resource_missing, e.g. "No such envelope." / "No such recipient.").
  • 429Too many requests (rate_limited): your key's per-minute limit, or an endpoint's own limit. Wait for Retry-After seconds.
  • 500Something went wrong on our side (internal_error). Safe to retry with the same Idempotency-Key.

Every error uses the error object.

Example request

curl -X POST https://signkoi.com/api/v1/webhooks/6d1e9f3a-4b2c-4a87-9e5d-0f7b3c8a2d54/rotate-secret \
  -H "Authorization: Bearer $SIGNKOI_API_KEY"

Example response

200 · application/json
{
  "object": "webhook_endpoint",
  "id": "6d1e9f3a-4b2c-4a87-9e5d-0f7b3c8a2d54",
  "url": "https://example.com/webhooks/signkoi",
  "description": "Production CRM sync",
  "events": [
    "envelope.completed",
    "envelope.declined",
    "recipient.completed"
  ],
  "enabled": true,
  "failure_count": 0,
  "last_success_at": "2026-11-14T09:31:02Z",
  "last_failure_at": null,
  "created_at": "2026-11-01T08:00:00Z",
  "secret": "whsec_3vY9pQ2mK7tR1xW8cL5nB0dF4hJ6gS2aZ"
}

Send a test event

POST/v1/webhooks/{id}/test

Sends a signed ping event to the endpoint right away (no retries) and returns the delivery, so you can check your receiver and signature verification. Limited to 10 calls a minute.

Required scope:webhooks:write

Path parameters

  • idstring · uuidrequired

    Webhook endpoint id.

Headers

  • Idempotency-Keystring

    Any unique string (1–255 chars), e.g. a UUID. Retrying with the same key and body within 24 hours returns the original response instead of repeating the action.

Response

200The ping delivery.
Response objectWebhookDelivery
  • objectstring= "webhook_delivery"
  • idstring · uuid
  • eventstring
  • statusstring

    pending: not attempted yet; delivered: your endpoint returned 2xx; retrying: the last attempt failed and another is scheduled (next_retry_at); failed: every retry failed.

    One ofpendingdeliveredretryingfailed

  • attemptsinteger
  • response_statusinteger | null

    HTTP status your endpoint returned on the last attempt.

  • response_excerptstring | null

    First 1,000 characters of your response body, or why the request could not be sent.

    max 1000 chars

  • delivered_atstring · date-time | null
  • next_retry_atstring · date-time | null
  • created_atstring · date-time

Response headers: X-Request-Id, Signkoi-Version, X-RateLimit-Limit, X-RateLimit-Remaining.

Errors

  • 401Missing, invalid, expired or revoked API key (api_key_missing, invalid_api_key).
  • 403The key lacks a required scope (insufficient_scope) or the account is suspended (account_suspended).
  • 404No such resource, or it belongs to someone else (resource_missing, e.g. "No such envelope." / "No such recipient.").
  • 429More than 10 tests a minute (rate_limited), or your key's rate limit.
  • 500Something went wrong on our side (internal_error). Safe to retry with the same Idempotency-Key.

Every error uses the error object.

Example request

curl -X POST https://signkoi.com/api/v1/webhooks/6d1e9f3a-4b2c-4a87-9e5d-0f7b3c8a2d54/test \
  -H "Authorization: Bearer $SIGNKOI_API_KEY"

Example response

200 · application/json
{
  "object": "webhook_delivery",
  "id": "a2c5e8f1-6b3d-4d9a-8c7e-1f4b0a9d3e62",
  "event": "ping",
  "status": "delivered",
  "attempts": 1,
  "response_status": 200,
  "response_excerpt": "ok",
  "delivered_at": "2026-11-14T10:05:00Z",
  "next_retry_at": null,
  "created_at": "2026-11-14T10:05:00Z"
}

List deliveries

GET/v1/webhooks/{id}/deliveries

Recent delivery attempts to the endpoint, newest first.

Required scope:webhooks:read

Path parameters

  • idstring · uuidrequired

    Webhook endpoint id.

Query parameters

  • pageinteger

    Page number, starting at 1.

    default 1

  • per_pageinteger

    Items per page.

    default 20

Response

200A page of deliveries.
Response objectWebhookDeliveryList

Recent deliveries, newest first.

  • objectstring= "list"
  • dataarray of WebhookDelivery
    Child attributes (WebhookDelivery)
    • objectstring= "webhook_delivery"
    • idstring · uuid
    • eventstring
    • statusstring

      pending: not attempted yet; delivered: your endpoint returned 2xx; retrying: the last attempt failed and another is scheduled (next_retry_at); failed: every retry failed.

      One ofpendingdeliveredretryingfailed

    • attemptsinteger
    • response_statusinteger | null

      HTTP status your endpoint returned on the last attempt.

    • response_excerptstring | null

      First 1,000 characters of your response body, or why the request could not be sent.

      max 1000 chars

    • delivered_atstring · date-time | null
    • next_retry_atstring · date-time | null
    • created_atstring · date-time
  • pageinteger
  • per_pageinteger
  • totalinteger
  • has_moreboolean

    Whether another page follows.

Response headers: X-Request-Id, Signkoi-Version, X-RateLimit-Limit, X-RateLimit-Remaining.

Errors

  • 401Missing, invalid, expired or revoked API key (api_key_missing, invalid_api_key).
  • 403The key lacks a required scope (insufficient_scope) or the account is suspended (account_suspended).
  • 404No such resource, or it belongs to someone else (resource_missing, e.g. "No such envelope." / "No such recipient.").
  • 429Too many requests (rate_limited): your key's per-minute limit, or an endpoint's own limit. Wait for Retry-After seconds.
  • 500Something went wrong on our side (internal_error). Safe to retry with the same Idempotency-Key.

Every error uses the error object.

Example request

curl https://signkoi.com/api/v1/webhooks/6d1e9f3a-4b2c-4a87-9e5d-0f7b3c8a2d54/deliveries \
  -H "Authorization: Bearer $SIGNKOI_API_KEY"

Example response

200 · application/json
{
  "object": "list",
  "data": [
    {
      "object": "webhook_delivery",
      "id": "a2c5e8f1-6b3d-4d9a-8c7e-1f4b0a9d3e62",
      "event": "envelope.completed",
      "status": "delivered",
      "attempts": 1,
      "response_status": 200,
      "response_excerpt": "ok",
      "delivered_at": "2026-11-15T14:02:43Z",
      "next_retry_at": null,
      "created_at": "2026-11-15T14:02:42Z"
    }
  ],
  "page": 1,
  "per_page": 20,
  "total": 1,
  "has_more": false
}

List event types

GET/v1/webhook-events

Every event a webhook endpoint can subscribe to (the ping test event is not listed).

Required scope:webhooks:read

Response

200The event catalogue.
Response objectWebhookEventList

Every event you can subscribe to.

  • objectstring= "list"
  • dataarray of WebhookEvent
    Child attributes (WebhookEvent)
    • objectstring= "webhook_event"
    • namestring
    • descriptionstring

Response headers: X-Request-Id, Signkoi-Version, X-RateLimit-Limit, X-RateLimit-Remaining.

Errors

  • 401Missing, invalid, expired or revoked API key (api_key_missing, invalid_api_key).
  • 403The key lacks a required scope (insufficient_scope) or the account is suspended (account_suspended).
  • 429Too many requests (rate_limited): your key's per-minute limit, or an endpoint's own limit. Wait for Retry-After seconds.
  • 500Something went wrong on our side (internal_error). Safe to retry with the same Idempotency-Key.

Every error uses the error object.

Example request

curl https://signkoi.com/api/v1/webhook-events \
  -H "Authorization: Bearer $SIGNKOI_API_KEY"

Example response

200 · application/json
{
  "object": "list",
  "data": [
    {
      "object": "webhook_event",
      "name": "envelope.sent",
      "description": "The envelope was sent and the first recipients were invited."
    },
    {
      "object": "webhook_event",
      "name": "envelope.completed",
      "description": "Every recipient finished; the signed PDF and certificate are ready to download."
    },
    {
      "object": "webhook_event",
      "name": "envelope.declined",
      "description": "A recipient declined to sign, which closes the envelope."
    },
    {
      "object": "webhook_event",
      "name": "envelope.voided",
      "description": "The sender voided the envelope."
    },
    {
      "object": "webhook_event",
      "name": "recipient.sent",
      "description": "A recipient was invited (it is their turn in the routing order)."
    },
    {
      "object": "webhook_event",
      "name": "recipient.viewed",
      "description": "A recipient opened the envelope."
    },
    {
      "object": "webhook_event",
      "name": "recipient.completed",
      "description": "A recipient signed, approved or viewed as required."
    },
    {
      "object": "webhook_event",
      "name": "recipient.declined",
      "description": "A recipient declined to sign."
    },
    {
      "object": "webhook_event",
      "name": "recipient.delegated",
      "description": "A recipient handed their part to someone else (see data.delegated_to)."
    }
  ]
}