Documentation
Browse documentation

Webhooks

Subscribe an HTTPS endpoint to signed thin events.
View as Markdown

Event Destinations send account events to external systems. FiscalRail currently supports webhook destinations; later destination types can use the same resource.

Read Receiving events with webhooks for an end-to-end setup, signature verification and processing workflow.

Destinations belong to exactly one Live or Test account. Each account can create up to 20 destinations. A destination can subscribe to up to 20 exact event types, or use "*" to receive every event type.

Webhook bodies are thin Events: they contain the event ID, type, occurrence time and related resource, but omit the immutable data snapshot. Retrieve the Event or related resource through the API when processing requires more data.

Verify signatures

Each destination has a readable signing secret beginning with whsec_. FiscalRail sends a signature header with every attempt:

FiscalRail-Signature: t=1786451696,v1=4f32...

Compute an HMAC-SHA256 using the destination's signing secret over the timestamp, a period, and the exact raw request body:

HMAC-SHA256(secret, timestamp + "." + raw_body)

Compare the hexadecimal result with v1 using a constant-time comparison and reject timestamps more than five minutes from the current time. Verify the raw bytes before parsing JSON. Every retry receives a new timestamp and signature.

Return any HTTP 2xx response quickly to acknowledge delivery. FiscalRail attempts each event up to five times. Deliveries are at least once and are not ordered, so use the Event ID for deduplication.

If every attempted delivery fails for 24 hours, FiscalRail disables the destination. Fix the endpoint and enable it again through the API or dashboard.

The Event Destination object

Properties
id string
Opaque identifier for the event destination.
object string
String identifying this as an Event Destination object. Always event_destination.
live boolean
True when the object belongs to the live environment; false for test data.
account string
Live or Test account that owns this destination.
name string
Human-readable destination name.
type string
Transport used by this destination. Currently always webhook. Always webhook.
status enum
Whether matching events are currently delivered.
Possible values
enabled
disabled
enabled_events array of strings
Exact subscribed event types, or a single asterisk for all events.
webhook object
Webhook-specific URL and signing configuration.
Show child propertiesHide child properties
url string
Public HTTPS endpoint that receives event deliveries.
signing_secret string or null
Readable on create and retrieve; null in list responses.
disabled_reason enum or null
Why this destination was disabled, or null while enabled.
Possible values
user
delivery_failures
created_at string
When the destination was created.
updated_at string
When the destination was last updated.
Event Destination object
{
  "id": null,
  "object": "event_destination",
  "live": null,
  "account": "acct_14Vxtqg2nwvPR75TpsGH8N",
  "name": null,
  "type": "webhook",
  "status": null,
  "enabled_events": [],
  "webhook": {
    "url": null,
    "signing_secret": null
  },
  "disabled_reason": null,
  "created_at": null,
  "updated_at": null
}

Create an event destination

POST/v1/event-destinations

Creates a webhook endpoint. An account can have at most 20 event destinations.

Request body
name string required
Human-readable destination name.
url string required
Public HTTPS endpoint that receives deliveries.
enabled_events array of strings required
One to 20 exact event types, or a single asterisk for all events.
Example request
curl --request POST \
  'https://api.fiscalrail.com/v1/event-destinations' \
  --header "Authorization: Bearer ak_test_..."
Example response — 201
{
  "id": null,
  "object": "event_destination",
  "live": null,
  "account": "acct_14Vxtqg2nwvPR75TpsGH8N",
  "name": null,
  "type": "webhook",
  "status": null,
  "enabled_events": [],
  "webhook": {
    "url": null,
    "signing_secret": null
  },
  "disabled_reason": null,
  "created_at": null,
  "updated_at": null
}

Retrieve an event destination

GET/v1/event-destinations/{id}

Returns the destination and its readable signing secret.

Path parameters
id string required
The opaque event destination ID.
Responses

200 An Event Destination object. JSON

Example request
curl --request GET \
  'https://api.fiscalrail.com/v1/event-destinations/example' \
  --header "Authorization: Bearer ak_test_..."
Example response — 200
{
  "id": null,
  "object": "event_destination",
  "live": null,
  "account": "acct_14Vxtqg2nwvPR75TpsGH8N",
  "name": null,
  "type": "webhook",
  "status": null,
  "enabled_events": [],
  "webhook": {
    "url": null,
    "signing_secret": null
  },
  "disabled_reason": null,
  "created_at": null,
  "updated_at": null
}

Update an event destination

PATCH/v1/event-destinations/{id}
Path parameters
id string required
The opaque event destination ID.
Request body
name string
Human-readable destination name.
url string
Public HTTPS endpoint that receives deliveries.
enabled_events array of strings
One to 20 exact event types, or a single asterisk for all events.
Responses

200 The updated Event Destination. JSON

Example request
curl --request PATCH \
  'https://api.fiscalrail.com/v1/event-destinations/example' \
  --header "Authorization: Bearer ak_test_..."
Example response — 200
{
  "id": null,
  "object": "event_destination",
  "live": null,
  "account": "acct_14Vxtqg2nwvPR75TpsGH8N",
  "name": null,
  "type": "webhook",
  "status": null,
  "enabled_events": [],
  "webhook": {
    "url": null,
    "signing_secret": null
  },
  "disabled_reason": null,
  "created_at": null,
  "updated_at": null
}

Enable an event destination

POST/v1/event-destinations/{id}/enable
Path parameters
id string required
The opaque event destination ID.
Responses

200 The enabled Event Destination. JSON

Example request
curl --request POST \
  'https://api.fiscalrail.com/v1/event-destinations/example/enable' \
  --header "Authorization: Bearer ak_test_..."
Example response — 200
{
  "id": null,
  "object": "event_destination",
  "live": null,
  "account": "acct_14Vxtqg2nwvPR75TpsGH8N",
  "name": null,
  "type": "webhook",
  "status": null,
  "enabled_events": [],
  "webhook": {
    "url": null,
    "signing_secret": null
  },
  "disabled_reason": null,
  "created_at": null,
  "updated_at": null
}

Disable an event destination

POST/v1/event-destinations/{id}/disable
Path parameters
id string required
The opaque event destination ID.
Responses

200 The disabled Event Destination. JSON

Example request
curl --request POST \
  'https://api.fiscalrail.com/v1/event-destinations/example/disable' \
  --header "Authorization: Bearer ak_test_..."
Example response — 200
{
  "id": null,
  "object": "event_destination",
  "live": null,
  "account": "acct_14Vxtqg2nwvPR75TpsGH8N",
  "name": null,
  "type": "webhook",
  "status": null,
  "enabled_events": [],
  "webhook": {
    "url": null,
    "signing_secret": null
  },
  "disabled_reason": null,
  "created_at": null,
  "updated_at": null
}

Delete an event destination

DELETE/v1/event-destinations/{id}
Path parameters
id string required
The opaque event destination ID.
Responses

204 The destination was deleted.

Example request
curl --request DELETE \
  'https://api.fiscalrail.com/v1/event-destinations/example' \
  --header "Authorization: Bearer ak_test_..."

List event destinations

GET/v1/event-destinations

Returns destinations for the authenticated Live or Test account. Signing secrets are null in list responses.

Query parameters
limit integer
Maximum number of resources to return. Defaults to 25.
starting_after string
Return destinations older than this destination ID.
ending_before string
Return destinations newer than this destination ID.
Example request
curl --request GET \
  'https://api.fiscalrail.com/v1/event-destinations?limit=25' \
  --header "Authorization: Bearer ak_test_..."
Example response — 200
{
  "object": "list",
  "has_more": null,
  "data": [
    {
      "id": null,
      "object": "event_destination",
      "live": null,
      "account": "acct_14Vxtqg2nwvPR75TpsGH8N",
      "name": null,
      "type": "webhook",
      "status": null,
      "enabled_events": [],
      "webhook": {
        "url": null,
        "signing_secret": null
      },
      "disabled_reason": null,
      "created_at": null,
      "updated_at": null
    }
  ]
}