Source: https://billingmart.com/developers/api/webhooks # Webhooks Endpoints BillingMart signs and posts events to, and the log of every attempt. [All sections](https://billingmart.com/developers/api) [Authentication](https://billingmart.com/developers/authentication) **On this page** - GET List - GET List - GET List - POST Create - PATCH Update - DELETE Delete - POST Rotate secret - GET List - POST Redeliver - OBJ WebhookEndpoint - OBJ WebhookDelivery On this page - GET List - GET List - GET List - POST Create - PATCH Update - DELETE Delete - POST Rotate secret - GET List - POST Redeliver - OBJ WebhookEndpoint - OBJ WebhookDelivery webhook endpoints ## List GET `/v1/admin/webhook-endpoints` List webhook endpoints for an admin reader. The signing secret is never returned. Scope `admin:read` Effect Read only MCP tool `list_webhook_endpoints` Retries Safe to repeat ### Parameters List parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `limit`optional | query | `integer` | min 1 · max 50 | | `cursor`optional | query | `string` | up to 256 chars | ### Returns `data`: [`WebhookEndpoint[]`](https://billingmart.com/developers/api/webhooks#object-WebhookEndpoint) . Pass `meta.cursor` back as `cursor` for the next page. Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/admin/webhook-endpoints" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` webhook deliveries ## List GET `/v1/admin/webhook-deliveries` List recent webhook deliveries and their outcomes. Scope `admin:read` Effect Read only MCP tool `list_webhook_deliveries` Retries Safe to repeat ### Parameters List parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `limit`optional | query | `integer` | min 1 · max 50 | | `cursor`optional | query | `string` | up to 256 chars | | `endpointId`optional | query | `id` | — | ### Returns `data`: [`WebhookDelivery[]`](https://billingmart.com/developers/api/webhooks#object-WebhookDelivery) . Pass `meta.cursor` back as `cursor` for the next page. Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/admin/webhook-deliveries" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` webhooks ## List GET `/v1/webhooks` List webhook endpoints. The signing secret is never returned. Scope `webhooks:manage` Effect Writes a draft or record MCP tool None — REST and API keys only Retries Safe to repeat ### Parameters List parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `limit`optional | query | `integer` | min 1 · max 50 | | `cursor`optional | query | `string` | up to 256 chars | ### Returns `data`: [`WebhookEndpoint[]`](https://billingmart.com/developers/api/webhooks#object-WebhookEndpoint) . Pass `meta.cursor` back as `cursor` for the next page. Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/webhooks" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` webhooks ## Create POST `/v1/webhooks` Register an endpoint. https only, SSRF-checked here and again at every delivery. The signing secret is returned ONCE, in this response, and never again. A `job.adjustmentIssued` or `job.adjustmentVoided` event carries the work record (its usual `job.*` body, no new fields); read the record's changes at `GET /v1/jobs/{id}/adjustments`. Scope `webhooks:manage` Effect Writes a draft or record MCP tool None — REST and API keys only Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Request body JSON. Money is an integer count of minor units beside its currency; quantities are thousandths. Create request body | Field | Type | Notes | | --- | --- | --- | | `url`required | `string` | at least 8 chars · up to 2048 chars | | `events`required | `enum[]` | Each one of 28 values · up to 32 items · at least 1 | | `description`optional | `string` | up to 200 chars | ### Returns `data`: `object` Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/webhooks" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" \ -H "Content-Type: application/json" \ -d '{"url":"","events":[]}' ``` webhooks ## Update PATCH `/v1/webhooks/{endpointId}` Change which events an endpoint receives, its description, or switch it off. Scope `webhooks:manage` Effect Writes a draft or record MCP tool None — REST and API keys only Retries No Idempotency-Key on this route ### Parameters Update parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `endpointId`required | path | `id` | — | ### Request body JSON. Money is an integer count of minor units beside its currency; quantities are thousandths. Update request body | Field | Type | Notes | | --- | --- | --- | | `events`optional | `enum[]` | Each one of 28 values · up to 32 items · at least 1 | | `description`optional | `string` | up to 200 chars | | `active`optional | `boolean` | — | ### Returns `data`: [`WebhookEndpoint`](https://billingmart.com/developers/api/webhooks#object-WebhookEndpoint) Example request Sample ``` curl -X PATCH "https://api.billingmart.com/v1/webhooks/{endpointId}" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` webhooks ## Delete DELETE `/v1/webhooks/{endpointId}` Delete an endpoint. Pending deliveries to it stop. Scope `webhooks:manage` Effect Writes a draft or record MCP tool None — REST and API keys only Retries No Idempotency-Key on this route ### Parameters Delete parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `endpointId`required | path | `id` | — | ### Returns `data`: [`WebhookEndpoint`](https://billingmart.com/developers/api/webhooks#object-WebhookEndpoint) Example request Sample ``` curl -X DELETE "https://api.billingmart.com/v1/webhooks/{endpointId}" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` webhooks ## Rotate secret POST `/v1/webhooks/{endpointId}/rotate-secret` Issue a new signing secret. The previous one stays valid for 24 h and deliveries carry a signature under both, so a receiver can roll without a gap. Scope `webhooks:manage` Effect Writes a draft or record MCP tool None — REST and API keys only Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Parameters Rotate secret parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `endpointId`required | path | `id` | — | ### Returns `data`: `object` Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/webhooks/{endpointId}/rotate-secret" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` deliveries ## List GET `/v1/webhook-deliveries` Delivery attempts, newest first: status, response code, retries and dead letters. Scope `webhooks:manage` Effect Writes a draft or record MCP tool None — REST and API keys only Retries Safe to repeat ### Parameters List parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `limit`optional | query | `integer` | min 1 · max 50 | | `cursor`optional | query | `string` | up to 256 chars | | `endpointId`optional | query | `id` | — | | `status`optional | query | `enum` | One of `pending`, `delivered`, `retrying`, `deadLettered` | ### Returns `data`: [`WebhookDelivery[]`](https://billingmart.com/developers/api/webhooks#object-WebhookDelivery) . Pass `meta.cursor` back as `cursor` for the next page. Example request Sample ``` curl -X GET "https://api.billingmart.com/v1/webhook-deliveries" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" ``` deliveries ## Redeliver POST `/v1/webhook-deliveries/{deliveryId}/redeliver` Send a delivery again. The body is rebuilt from the subject record, so the payload hash proves it is the same event — not a stored copy replayed. Scope `webhooks:manage` Effect Writes a draft or record MCP tool None — REST and API keys only Retries Send an Idempotency-Key; a repeat replays the stored answer for 24 hours ### Parameters Redeliver parameters | Name | In | Type | Notes | | --- | --- | --- | --- | | `deliveryId`required | path | `id` | — | ### Returns `data`: `object` Example request Sample ``` curl -X POST "https://api.billingmart.com/v1/webhook-deliveries/{deliveryId}/redeliver" \ -H "Authorization: Bearer $BILLINGMART_API_KEY" \ -H "Idempotency-Key: $(uuidgen)" ``` Object ## WebhookEndpoint Where a tenant wants events delivered. `url` is checked for SSRF at registration AND at every delivery — re-resolved, refusing private, link-local and cloud-metadata ranges — because a DNS answer can change between the two. WebhookEndpoint fields | Field | Type | Notes | | --- | --- | --- | | `id`required | `Id` | — | | `tenant`required | `TenantRef` | — | | `url`required | `Url` | https only. SSRF-checked at registration and at each delivery. | | `description`optional | `string` | Untrusted text A person's note about the endpoint. | | `events`required | `WebhookEvent[]` | Which events this endpoint receives. Empty means none — subscribing is explicit. | | `active`required | `boolean` | Switched off by the tenant, or by the server after 50 consecutive failures (recorded in the audit log). | | `signingSecret`required | `EncryptedCredentialSet` | Signs `X-BillingMart-Signature: t=, v1=`. Receivers reject a t older than 5 minutes. | | `previousSigningSecret`optional | `EncryptedCredentialSet` | Kept for 24 h after rotation; deliveries carry a v1 signature under both. | | `secretRotatedAt`optional | `IsoTimestamp` | — | | `lastDeliveryAt`optional | `IsoTimestamp` | — | | `lastDeliveryStatus`optional | `WebhookDeliveryStatus` | — | | `consecutiveFailures`optional | `integer` | SERVER-WRITTEN. Reset to 0 on a delivered attempt. | | `createdAt`required | `IsoTimestamp` | — | | `updatedAt`optional | `IsoTimestamp` | — | | `createdBy`optional | `Id` | From the verified ID token, or the API key id when registered through the API with webhooks:manage. | Object ## WebhookDelivery One event's delivery to one endpoint: attempts, retries, the dead letter. WebhookDelivery fields | Field | Type | Notes | | --- | --- | --- | | `id`required | `Id` | — | | `tenant`required | `TenantRef` | — | | `endpointId`required | `Id` | — | | `event`required | `WebhookEvent` | — | | `subjectId`required | `Id` | The invoice, estimate, payment, client or agent action the event is about. | | `payloadHash`required | `string` | SHA-256 of the signed body. | | `attempt`required | `integer` | The attempt number of the latest try. | | `maxAttempts`required | `integer` | 8 by default, exponential backoff between them. | | `status`required | `WebhookDeliveryStatus` | — | | `responseStatusCode`optional | `integer` | — | | `responseTimeMs`optional | `integer` | Milliseconds. Deliveries time out at 10 s. | | `nextAttemptAt`optional | `IsoTimestamp` | — | | `deliveredAt`optional | `IsoTimestamp` | — | | `deadLetteredAt`optional | `IsoTimestamp` | — | | `lastError`optional | `string` | Untrusted text Masked before storage, like every other logged string. | | `createdAt`required | `IsoTimestamp` | — | | `updatedAt`optional | `IsoTimestamp` | — | Next section ## Work setup and job types How a business sets up its work records: its terminology, the record types it can use, and the industry packs it can adopt. A record type is saved here as a draft; publishing it is an approved action. [Continue to Work setup and job types →](https://billingmart.com/developers/api/work-setup) ## Try it against your sandbox Create a bmk_test_ key in the console. It can only reach your sandbox workspace. [Start free](https://app.billingmart.com/sign-up) [All sections](https://billingmart.com/developers/api) --- This is the Markdown copy of https://billingmart.com/developers/api/webhooks. Live plans, prices and limits are published as JSON at https://billingmart.com/plans.json and https://billingmart.com/agent-info.json.