Skip to main content

Webhooks

11 operations in the Tolvi API, version 1. Paths are relative to https://api.tolvi.co.uk. Every amount is integer pence.

List the webhook event types

GET/api/v1/webhooks/event-types

Scopes
webhooks:manage
Role
Firm admin

The event catalogue you can subscribe to.

Responses

200 OK, application/json

Body: array of WebhookEventTypeInfo.

200 OK response for GET /api/v1/webhooks/event-types
FieldTypeDescription
[].​typerequiredstring (WebhookEventType)

One of: engagement.stage_changed, section.signed_off, review_point.raised, review_point.cleared, tb.imported, sync.change_detected, self_assessment.filed, accounts.approved, corporation_tax.filed

[].​descriptionrequiredstring

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).

List webhook subscriptions

GET/api/v1/webhooks

Scopes
webhooks:manage
Role
Firm admin

Responses

200 OK, application/json

Body: array of WebhookSubscription.

200 OK response for GET /api/v1/webhooks
FieldTypeDescription
[].​idrequiredstring (uuid)
[].​urlrequiredstring (uri)

example "https://hooks.example.co.uk/tolvi"

[].​descriptionrequiredstringnullable
[].​eventTypesrequiredarray of WebhookEventType

One of: engagement.stage_changed, section.signed_off, review_point.raised, review_point.cleared, tb.imported, sync.change_detected, self_assessment.filed, accounts.approved, corporation_tax.filed

at least 1 items

[].​statusrequiredstring (WebhookSubscriptionStatus)

One of: active, disabled

[].​disabledReasonrequiredstringnullable

Why it was disabled: by hand, or automatically after repeated failed deliveries.

[].​disabledAtrequiredstring (date-time)nullable
[].​consecutiveFailuresrequiredinteger

Failed attempts in a row. Reaching the limit disables the subscription and tells the firm’s admins.

at least 0

[].​secretPrefixrequiredstring

First characters of the signing secret.

example "whsec_AbC1"

[].​createdByrequiredstring (uuid)nullable
[].​createdAtrequiredstring (date-time)
[].​updatedAtrequiredstring (date-time)

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).

Create a webhook subscription

POST/api/v1/webhooks

Scopes
webhooks:manage
Role
Firm admin

Returns the signing secret once. Each delivery is a POST with a JSON body and a Tolvi-Signature: t=<unix seconds>,v1=<hex> header, where v1 is HMAC-SHA256 of <t>.<raw body> keyed with the subscription’s secret. Reject a delivery whose signature does not match or whose t is more than 5 minutes from now, and de-duplicate on Tolvi-Event-Id. Answer 2xx within 10 seconds; anything else is retried with exponential backoff (30 s doubling to 6 h, 12 attempts). After 20 failed attempts in a row the subscription is disabled and the firm’s admins are told.

Request body

Required. application/json: object (CreateWebhookSubscription).

Request body for POST /api/v1/webhooks
FieldTypeDescription
urlrequiredstring (uri)

An https URL on a public host. Private, loopback and link-local addresses are refused.

up to 2048 characters

eventTypesrequiredarray of WebhookEventType

One of: engagement.stage_changed, section.signed_off, review_point.raised, review_point.cleared, tb.imported, sync.change_detected, self_assessment.filed, accounts.approved, corporation_tax.filed

at least 1 items

descriptionstringnullable

up to 200 characters

Responses

201 Created, application/json

Body: object (CreatedWebhookSubscription).

The signing secret is shown only once. Use it to verify the Tolvi-Signature header.

201 Created response for POST /api/v1/webhooks
FieldTypeDescription
subscriptionrequiredobject (WebhookSubscription)
subscription.​idrequiredstring (uuid)
subscription.​urlrequiredstring (uri)

example "https://hooks.example.co.uk/tolvi"

subscription.​descriptionrequiredstringnullable
subscription.​eventTypesrequiredarray of WebhookEventType

One of: engagement.stage_changed, section.signed_off, review_point.raised, review_point.cleared, tb.imported, sync.change_detected, self_assessment.filed, accounts.approved, corporation_tax.filed

at least 1 items

subscription.​statusrequiredstring (WebhookSubscriptionStatus)

One of: active, disabled

subscription.​disabledReasonrequiredstringnullable

Why it was disabled: by hand, or automatically after repeated failed deliveries.

subscription.​disabledAtrequiredstring (date-time)nullable
subscription.​consecutiveFailuresrequiredinteger

Failed attempts in a row. Reaching the limit disables the subscription and tells the firm’s admins.

at least 0

subscription.​secretPrefixrequiredstring

First characters of the signing secret.

example "whsec_AbC1"

subscription.​createdByrequiredstring (uuid)nullable
subscription.​createdAtrequiredstring (date-time)
subscription.​updatedAtrequiredstring (date-time)
secretrequiredstring

example "whsec_…"

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).

Get a webhook subscription

GET/api/v1/webhooks/{id}

Scopes
webhooks:manage
Role
Firm admin

Parameters

Parameters for GET /api/v1/webhooks/{id}
NameInTypeDescription
idrequiredpathstring (uuid)

Webhook subscription id.

Responses

200 OK, application/json

Body: object (WebhookSubscription).

200 OK response for GET /api/v1/webhooks/{id}
FieldTypeDescription
idrequiredstring (uuid)
urlrequiredstring (uri)

example "https://hooks.example.co.uk/tolvi"

descriptionrequiredstringnullable
eventTypesrequiredarray of WebhookEventType

One of: engagement.stage_changed, section.signed_off, review_point.raised, review_point.cleared, tb.imported, sync.change_detected, self_assessment.filed, accounts.approved, corporation_tax.filed

at least 1 items

statusrequiredstring (WebhookSubscriptionStatus)

One of: active, disabled

disabledReasonrequiredstringnullable

Why it was disabled: by hand, or automatically after repeated failed deliveries.

disabledAtrequiredstring (date-time)nullable
consecutiveFailuresrequiredinteger

Failed attempts in a row. Reaching the limit disables the subscription and tells the firm’s admins.

at least 0

secretPrefixrequiredstring

First characters of the signing secret.

example "whsec_AbC1"

createdByrequiredstring (uuid)nullable
createdAtrequiredstring (date-time)
updatedAtrequiredstring (date-time)

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).

Update a webhook subscription

PATCH/api/v1/webhooks/{id}

Scopes
webhooks:manage
Role
Firm admin

Change the URL, event types or description, or disable it. Setting status to active re-enables a disabled subscription and resets its failure count.

Parameters

Parameters for PATCH /api/v1/webhooks/{id}
NameInTypeDescription
idrequiredpathstring (uuid)

Webhook subscription id.

Request body

Required. application/json: object (UpdateWebhookSubscription).

Request body for PATCH /api/v1/webhooks/{id}
FieldTypeDescription
urlstring (uri)

up to 2048 characters

eventTypesarray of WebhookEventType

One of: engagement.stage_changed, section.signed_off, review_point.raised, review_point.cleared, tb.imported, sync.change_detected, self_assessment.filed, accounts.approved, corporation_tax.filed

at least 1 items

descriptionstringnullable

up to 200 characters

statusstring (WebhookSubscriptionStatus)

active re-enables a disabled subscription and resets its failure count.

One of: active, disabled

Responses

200 OK, application/json

Body: object (WebhookSubscription).

The fields are as shown above.

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).

Delete a webhook subscription

DELETE/api/v1/webhooks/{id}

Scopes
webhooks:manage
Role
Firm admin

Deletes it with its delivery log. Pending deliveries are not sent.

Parameters

Parameters for DELETE /api/v1/webhooks/{id}
NameInTypeDescription
idrequiredpathstring (uuid)

Webhook subscription id.

Responses

204 No content

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).

Send a test event to an endpoint

POST/api/v1/webhooks/test

Scopes
webhooks:manage
Role
Firm admin

Before subscribing: checks the URL as a subscription would (https, public addresses only) and POSTs one ping event to it, then says what came back. The test is signed with a one-off key, so your endpoint can’t verify its signature; it only needs to answer 2xx within 10 seconds. Nothing is stored or retried.

Request body

Required. application/json: object (TestWebhookEndpoint).

Request body for POST /api/v1/webhooks/test
FieldTypeDescription
urlrequiredstring (uri)

An https URL on a public host, checked exactly as a subscription’s is.

up to 2048 characters

Responses

200 OK, application/json

Body: object (WebhookEndpointTest).

What happened when Tolvi sent a test event (type ping) to an endpoint. Nothing is stored.

200 OK response for POST /api/v1/webhooks/test
FieldTypeDescription
okrequiredboolean

The endpoint answered 2xx within 10 seconds.

statusrequiredintegernullable

The HTTP status it answered with; null when nothing came back.

errorrequiredstringnullable

Why it failed, in words: a refused address, a timeout, no answer.

durationMsrequiredinteger

How long it took, in milliseconds.

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).

Rotate the signing secret

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

Scopes
webhooks:manage
Role
Firm admin

Returns the new secret once. The old one stops working at once, including for retries already scheduled.

Parameters

Parameters for POST /api/v1/webhooks/{id}/rotate-secret
NameInTypeDescription
idrequiredpathstring (uuid)

Webhook subscription id.

Responses

200 OK, application/json

Body: object (CreatedWebhookSubscription).

The signing secret is shown only once. Use it to verify the Tolvi-Signature header.

The fields are as shown above.

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).

List a subscription’s deliveries, newest first

GET/api/v1/webhooks/{id}/deliveries

Scopes
webhooks:manage
Role
Firm admin

The delivery log: status, attempts and the last response code.

Parameters

Parameters for GET /api/v1/webhooks/{id}/deliveries
NameInTypeDescription
idrequiredpathstring (uuid)

Webhook subscription id.

limitqueryinteger
cursorquerystring
statusquerystring (WebhookDeliveryStatus)

One of: pending, succeeded, failed

Responses

200 OK, application/json

Body: object (WebhookDeliveryPage).

200 OK response for GET /api/v1/webhooks/{id}/deliveries
FieldTypeDescription
rowsrequiredarray of WebhookDelivery
rows[].​idrequiredstring (uuid)

Sent as Tolvi-Delivery-Id.

rows[].​subscriptionIdrequiredstring (uuid)
rows[].​eventIdrequiredstring (uuid)

Sent as Tolvi-Event-Id and as id in the body: the same on retries and replays.

rows[].​eventTyperequiredstring (WebhookEventType)

One of: engagement.stage_changed, section.signed_off, review_point.raised, review_point.cleared, tb.imported, sync.change_detected, self_assessment.filed, accounts.approved, corporation_tax.filed

rows[].​statusrequiredstring (WebhookDeliveryStatus)

One of: pending, succeeded, failed

rows[].​attemptsrequiredinteger

at least 0

rows[].​nextAttemptAtrequiredstring (date-time)nullable

When the next attempt is due (pending deliveries only).

rows[].​lastAttemptAtrequiredstring (date-time)nullable
rows[].​responseStatusrequiredintegernullable
rows[].​errorrequiredstringnullable
rows[].​replayOfrequiredstring (uuid)nullable

The delivery this one replays.

rows[].​createdAtrequiredstring (date-time)
nextCursorrequiredstringnullable

Opaque cursor for the next page (pass as cursor); null on the last page.

pageSizerequiredinteger

The page size that was used.

1 to 100

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).

Get a delivery with its payload and every attempt

GET/api/v1/webhooks/{id}/deliveries/{deliveryId}

Scopes
webhooks:manage
Role
Firm admin

Parameters

Parameters for GET /api/v1/webhooks/{id}/deliveries/{deliveryId}
NameInTypeDescription
idrequiredpathstring (uuid)

Webhook subscription id.

deliveryIdrequiredpathstring (uuid)

Delivery id.

Responses

200 OK, application/json

Body: object (WebhookDeliveryDetail).

200 OK response for GET /api/v1/webhooks/{id}/deliveries/{deliveryId}
FieldTypeDescription
idrequiredstring (uuid)

Sent as Tolvi-Delivery-Id.

subscriptionIdrequiredstring (uuid)
eventIdrequiredstring (uuid)

Sent as Tolvi-Event-Id and as id in the body: the same on retries and replays.

eventTyperequiredstring (WebhookEventType)

One of: engagement.stage_changed, section.signed_off, review_point.raised, review_point.cleared, tb.imported, sync.change_detected, self_assessment.filed, accounts.approved, corporation_tax.filed

statusrequiredstring (WebhookDeliveryStatus)

One of: pending, succeeded, failed

attemptsrequiredinteger

at least 0

nextAttemptAtrequiredstring (date-time)nullable

When the next attempt is due (pending deliveries only).

lastAttemptAtrequiredstring (date-time)nullable
responseStatusrequiredintegernullable
errorrequiredstringnullable
replayOfrequiredstring (uuid)nullable

The delivery this one replays.

createdAtrequiredstring (date-time)
payloadrequiredstring

The exact JSON body that is signed and sent.

attemptLogrequiredarray of WebhookDeliveryAttempt
attemptLog[].​attemptrequiredinteger

at least 1

attemptLog[].​atrequiredstring (date-time)
attemptLog[].​responseStatusrequiredintegernullable

HTTP status, or null when no response came back.

attemptLog[].​responseBodyrequiredstringnullable

First 1 KB of the response body.

attemptLog[].​errorrequiredstringnullable

Network error, timeout or refused address.

attemptLog[].​durationMsrequiredinteger

at least 0

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).

Replay a delivery

POST/api/v1/webhooks/{id}/deliveries/{deliveryId}/replay

Scopes
webhooks:manage
Role
Firm admin
Retries
Send an Idempotency-Key to make retries safe.

Queues the same event again as a new delivery, sent within seconds. The event id is unchanged, so receivers that de-duplicate on it ignore a copy they already processed.

Parameters

Parameters for POST /api/v1/webhooks/{id}/deliveries/{deliveryId}/replay
NameInTypeDescription
idrequiredpathstring (uuid)

Webhook subscription id.

deliveryIdrequiredpathstring (uuid)

Delivery id.

Idempotency-Keyheaderstring

A unique key (1-255 visible characters) to make retries safe. Replayed for 24 hours.

1 to 255 characters

Responses

202 Accepted, application/json

Body: object (WebhookDelivery).

202 Accepted response for POST /api/v1/webhooks/{id}/deliveries/{deliveryId}/replay
FieldTypeDescription
idrequiredstring (uuid)

Sent as Tolvi-Delivery-Id.

subscriptionIdrequiredstring (uuid)
eventIdrequiredstring (uuid)

Sent as Tolvi-Event-Id and as id in the body: the same on retries and replays.

eventTyperequiredstring (WebhookEventType)

One of: engagement.stage_changed, section.signed_off, review_point.raised, review_point.cleared, tb.imported, sync.change_detected, self_assessment.filed, accounts.approved, corporation_tax.filed

statusrequiredstring (WebhookDeliveryStatus)

One of: pending, succeeded, failed

attemptsrequiredinteger

at least 0

nextAttemptAtrequiredstring (date-time)nullable

When the next attempt is due (pending deliveries only).

lastAttemptAtrequiredstring (date-time)nullable
responseStatusrequiredintegernullable
errorrequiredstringnullable
replayOfrequiredstring (uuid)nullable

The delivery this one replays.

createdAtrequiredstring (date-time)

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 409 Conflict, 422 Unprocessable content, 429 Too many requests, as problem details (application/problem+json).