Webhooks and Events
Listen for events on your Chariot account so your platform can automatically trigger reactions.
When something interesting happens on the nonprofit’s Chariot account, such as a Grant being created or its status being updated, Chariot can send a message to your application so that you can take action automatically.
The first step is to create an Event Subscription via the API. As part of this, you specify a URL for a server endpoint that will receive real-time events. Chariot will then send HTTPS requests to that URL to notify you of activity for certain events.
When a noteworthy event happens, Chariot first generates an Event. Next, we’ll send a POST request to your endpoint.
Note that you can create Event Subscriptions in Production and Sandbox. Sandbox Event Subscriptions will receive events for Sandbox events and vice versa.
Consuming Events
Individual Events don’t contain very much information on their own. This is by design, as the API structure can remain extremely stable and avoid difficult webhook migrations in the future as the Chariot API changes. If you need additional metadata, such as the amount or status of the Grant in the above example, make a GET request to the API for that information.
If you don’t want to use webhooks, or need to do some batch processing, you can also request Events from the Chariot API using the List Events API. Events will remain in the Chariot system for up to 30 days.
Secure your webhooks
After you’ve confirmed that your webhook endpoint connections works as expected, secure the connection by verifying the signature provided in the header of the webhook request.
In order to verify signatures for webhooks, you need to specify the signing secret that you will use in the Create Event Subscription API.
Chariot will include the Chariot-Webhook-Signature
header in each webhook request. This header will contain a timestamp and one or more signatures. The timestamp is prefixed by t=
, and each signature is prefixed by a scheme. Schemes start with v
, followed by an integer. Currently, the only valid live signature scheme is v1
.
Chariot generates signatures using a hash-based message authentication code (HMAC) with SHA-256. To prevent downgrade attacks, ignore all schemes that are not v1.
Verify Signatures Manually
Step 1: Extract the timestamp and signatures from the header
Split the header using the ,
character as the separator to get a list of elements. Then split each element using the =
character as the separator to get a prefix and value pair.
The value for the prefix t
corresponds to the timestamp, and v1
corresponds to the signature. You can discard all other elements.
Step 2: Prepare the signed payload
The signed_payload
string is created by concatenating:
- The timestamp (as a string)
- The character
.
- The actual JSON payload (that is, the request body)
Step 3: Determine the expected signature
Compute an HMAC with the SHA256 hash function. Use the Event Subscription’s signingSecret
as the key, and use the signed_payload
string as the message.
Step 4: Compare the Signatures
Compare the signature (or signatures) in the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.
To protect against timing attacks, use a constant-time-string comparison to compare the expected signature to each of the received signatures.
Failures and Retries
In production, if your application returns anything other than a 20x HTTP status code, we’ll retry it up to 10 times with exponentially increasing backoffs. In your webhook endpoint implementation, we recommend you place inbound Events into your application’s own queuing system for asynchronous event processing, and return a 200 response from your endpoint as quickly as possible. Because we can’t guarantee we’ll receive your 200 acknowledgement, your webhook implementation should gracefully handle receiving the same webhook multiple times.
To avoid queueing issues, we will not retry failed webhooks in the sandbox.
If all attempts to a webhook endpoint fail, after 5 days the endpoint will be disabled and we will stop sending event messages to that endpoint.
Best Practices
Review these best practices to make sure your webhooks remain secure and function well with your integration.
Handle Duplicate Events
Webhook endpoints might occasionally receive the same event more than once. You can guard against duplicated event receipts by making your event processing idempotent.
Only subscribe to event categories your integration requires
Configure your webhook endpoints to receive only the types of events required by your integration. Listening for extra events (or all events) puts undue strain on your server and we don’t recommend it.
You can Update an Event Subscription to change the event category for a webhook endpoint with the API.
Receive events with an HTTPS server
If you use an HTTPS URL for your webhook endpoint, Chariot validates that the connection to your server is secure before sending your webhook data. For this to work, your server must be correctly configured to support HTTPS with a valid server certificate. The Production environment requires HTTPS URLs.
Quickly return a 2xx response
Your endpoint must quickly return a successful status code (2xx) prior to any complex logic that could cause a timeout.
Verify webhook signatures
See the section above on verifying webhook signatures