Webhook configuration
This topic describes how to use webhooks with the Rebilly API. For information on how to configure webhooks in the Rebilly UI, see Webhooks.
Use webhooks to notify your systems when certain events occur and to collect event information. Rebilly sends notifications through HTTP and HTTPS methods to a URL of your choice. To view webhooks operations, see the Webhooks API docs.
Each website that you add to Rebilly can have its own webhook configuration. This includes the URI to which you want to send the webhook, along with optional HTTP basic access authentication details.
Webhooks may be delayed or delivered multiple times. Keep this in mind if you intend to use webhooks to make actionable decisions. For more information, see Data validity.
Define events
To restrict a webhook to a specific event or event types, use the eventsFilter
field. To add more than one event type, set an array of system event types as follows:["gateway-account-requested", "subscription-canceled"]
. If you leave the eventsFilter
field empty blank all events are active for the webhook.
For a complete list of event types, see Global event types.
Security
Create webhook service credentials for your webhook host.
HTTP basic access authentication through HTTPS is highly recommended. This adds an extra layer of security for your webhook endpoint that can prevent undesired data injection by third parties.
Rebilly webhooks may be sent from these IP addresses. If you use HTTP basic access authentication, Rebilly also sends an authorization header along with the GET
, POST
, PUT
, PATCH
, or DELETE
request.
The following is an example of a header with HTTP basic access authentication enabled that uses username = rebilly, password = superman
:
POST /odt4xsod HTTP/1.1 User-Agent: Rebilly/20e49c5 Host: example.com Content-Type: application/json; charset=utf-8 Content-Length: 478 Connection: close Authorization: Basic cmViaWxseTpzdXBlcm1hbgo= Accept-Encoding: gzip, deflate
If you use base64 to decode the value decode(cmViaWxseTpzdXBlcm1hbgo=)
you receive rebilly:superman
.
Responses
Rebilly expects a HTTP 200 OK
response after a successful webhook transmission to your systems. If no response is received within 20 seconds, or the HTTP response code is not 200, the request is considered not sent and be marked for retry. The webhook is sent again automatically after 30 minutes. If no response is received, the webhook is attempted by an exponential back-off, at 1, 2, 4, 8, and 16 hours for a total of 6 retries attempts until successful. If still unsuccessful, it is not attempted again.
User agent
In Rebilly, all outgoing webhooks contain a User-Agent
header. The header value changes frequently. The value format is Rebilly/%release%
, where %release%
is a 7 character long alphanumeric string which matches the /^[a-z0-9]{7}$/
regular expression pattern.
Data validity
When a notification is triggered, Rebilly sends all available information to your endpoint at the time of the event. The data contained in the webhook reflects the state of Rebilly records at the time of the event. In the event of a delay, your records might be more up to date than the data that is sent by the webhook.
The following example describes a scenario where a delay occurs in recording of data between systems.
- A transaction triggers a webhook, and some relating customer information was not supplied at the time when the transaction occurred.
- The notification transmission is delayed for a short period.
- Your system modifies or adds this information before a notification is received.
- The notification for the transaction is received by your systems, but the customer information does not match your records.
Data authenticity
In Rebilly, all outgoing webhooks contain a Security-Signature
header. Use this header to ensure data authenticity. Signature verification is optional and is not required for your integration to work, but it is recommended.
The authenticity check uses JSON Web Tokens (JWTs) and JSON Web Keys (JWKs) to verify webhooks.
To authenticate webhook data:
- Locate, load, and cache Rebilly JWKs from the live or sandbox environments.
To ensure proper key rotation, Rebilly recommends a cache Time to Live (TTL) of no greater than 1 hour. - Extract the JWT from the
Security-Signature
header of the webhook. - Validate the JWT against your preferred JWT and JWK library for your chosen programming language.
- Decode the payload (second) segment of the JWT and verify the following checks:
If a webhook fails any of the following checks, consider the webhook invalid and discard it.
- The
iss
value is equal to the Rebilly API URL where you expect to receive webhooks. For example,https://api.rebilly.com/
orhttps://api-sandbox.rebilly.com/
. - The
aud
value is equal to your organization ID within Rebilly. - The
iat
value is greater or equal to the current Unix timestamp. Rebilly recommends a leeway of no greater than 10 seconds. - The
exp
value is less than the current Unix timestamp. This is an optional check to prevent replay attacks. Rebilly accepts webhooks that are received within a 5-minute timeframe between theiat
andexp
values. - The
requestBodyHash
is equal to the SHA256 hash of the raw webhook body.
Authenticity check example
The following example is of a webhook that is received at 2023-02-12 19:45:00 UTC
(formatting and spaces are preserved in the webhook body):
POST /odt4xsod HTTP/1.1 User-Agent: Rebilly/20e49c5 Host: example.com Content-Type: application/json; charset=utf-8 Content-Length: 478 Connection: close Security-Signature: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImI2MDNmMWY4Y2U0Y2RlMzc2NjExNzlkNGRmODNlYjZlODc0ZTRjZjRjNWNmNWRhMGIxYTY0NDUyMDJmNmJlNGIifQ.eyJpc3MiOiJodHRwczovL2FwaS1zYW5kYm94LnJlYmlsbHkuY29tLyIsImF1ZCI6ImE5ZjY4ZTZlLWUyZTYtNDNkZC1hMjdmLTgxMjAxMjFkNzQyOCIsImlhdCI6MTY3NjIzMDk3MiwiZXhwIjoxNjc2MjMxMjcyLCJyZXF1ZXN0Qm9keUhhc2giOiIyMjA1YThkMjU0M2M5N2E5YThkYzI5YTRmOWZkZjcxN2ZkOTQ3OGI5ODkxYWRmNTJhYmQ5YzA5ZjdhZmRlMDk0In0.ChVc_NAWxfZVEl4g7QhFFO8c5ZtUuTWlP60qQ7gEKtUQdWY70WyzYOREbGPodTbraSNggh1M98gaYSqcQM6vAk3op_9HQpeMtQEIGUOjNDMe2_BmwyeGtcc3_c3Ft0gsARUYatZcVCeeYi7i8Xwekj2xQKkxbkLYEkHHj3f_o2dHXdXaFVvgU2fNN9pmfq1iI2ROM_UXrpGDfsm1nfvZsFLk9cdCum3bBMpTeqelm02ojk6yHES9otoMTYqwGJ5ovyOKaPzMAUJT1tNv1xzf5YxxyBMj6CRqTMPkItrgU3nX6pPMdS5cbEWzhTUcm29WeWrXf90PqLUJTvSxIuMhUA Accept-Encoding: gzip, deflate {"dataExportId":"d9dd134f-0bee-46b1-bec0-992da3173336","fileId":"d348968b-41ed-4d7d-b534-02e5265c8912","eventType":"data-export-completed","_embedded":{"dataExport":{"id":"d9dd134f-0bee-46b1-bec0-992da3173336","name":"Preview","resource":"customers","format":"csv","arguments":null,"dateRange":null,"emailNotification":[],"fields":[],"recurring":null,"status":"pending","userId":"3d08e3f3-fa38-4731-9761-8a04400e05d3","recordCount":null,"scheduledTime":"2023-02-12T19:42:52+00:00","expiredTime":"2023-03-12T19:42:52+00:00","purgedTime":"2024-06-12T19:42:52+00:00","createdTime":"2023-02-12T19:42:52+00:00","updatedTime":"2023-02-12T19:42:52+00:00","_links":[{"rel":"self","href":"https:\/\/api-sandbox.rebilly.com\/organizations\/a9f68e6e-e2e6-43dd-a27f-8120121d7428\/experimental\/data-exports\/d9dd134f-0bee-46b1-bec0-992da3173336"},{"rel":"user","href":"https:\/\/api-sandbox.rebilly.com\/users\/3d08e3f3-fa38-4731-9761-8a04400e05d3"}]}},"_links":[{"rel":"dataExport","href":"https:\/\/api-sandbox.rebilly.com\/organizations\/a9f68e6e-e2e6-43dd-a27f-8120121d7428\/experimental\/data-exports\/d9dd134f-0bee-46b1-bec0-992da3173336"},{"rel":"download","href":"https:\/\/api-sandbox.rebilly.com\/organizations\/a9f68e6e-e2e6-43dd-a27f-8120121d7428\/files\/d348968b-41ed-4d7d-b534-02e5265c8912\/download"}]}
At 2023-02-12 19:45:00 UTC
the JWKs located at https://api-sandbox.rebilly.com/.well-known/keys contain the following key:
[ { "kty": "RSA", "n": "sT66o-HJLpVt5qifPS6MsFpu8dj-NZJWWJnoJMohCBHhGNL8v6EJm_kCNY43Czi0Bt5dbrFovPgcjdR1yq938hQ9Hi2SjNoddqcsvOUtThztsXitTKSutBKjVcInN_At_DxCpO8pardiR3aLR-bCClz8iSutmRaTenee6cMUkkZZRs0XRqI_gDPfAoN_f5HWZBXnu-VSUrBpT-PnzA4ICvR9ZaeU3EK3T64QhLnxuGa_o561__CR5oD79sEXILqJoD47uE22FydAvHvrgWqk0RMkBFtSdgmFkhylpAVgnGWAJqB2FLy-yLh5QMS02SxKtz89KRVRe0V4BVx5x3bTbw", "e": "AQAB", "alg": "RS256", "kid": "b603f1f8ce4cde37661179d4df83eb6e874e4cf4c5cf5da0b1a6445202f6be4b", "use": "sig" } ]
The JWT signature could be verified with the key whose kid
value is b603f1f8ce4cde37661179d4df83eb6e874e4cf4c5cf5da0b1a6445202f6be4b
as expected.
The decoded JWT payload segment provides:
{ "iss": "https://api-sandbox.rebilly.com/", "aud": "a9f68e6e-e2e6-43dd-a27f-8120121d7428", "iat": 1676230972, "exp": 1676231272, "requestBodyHash": "2205a8d2543c97a9a8dc29a4f9fdf717fd9478b9891adf52abd9c09f7afde094" }
Results of the verification checks:
- The
iss
value is equal to the sandbox API URL. - The
aud
value is equal to the organization IDa9f68e6e-e2e6-43dd-a27f-8120121d7428
. - The
iat
value is equal to2023-02-12 19:42:52 UTC
, which is less than the reception time of2023-02-12 19:45:00 UTC
. - The
exp
value is equal to2023-02-12 19:47:52 UTC
, which is greater than the reception time of2023-02-12 19:45:00 UTC
. - The
requestBodyHash
value is equal to the SHA256 hash of the raw webhook body:
sha256('{"dataExportId":"d9dd134f-0bee-46b1-bec0-992da3173336","fileId":"d348968b-41ed-4d7d-b534-02e5265c8912","eventType":"data-export-completed","_embedded":{"dataExport":{"id":"d9dd134f-0bee-46b1-bec0-992da3173336","name":"Preview","resource":"customers","format":"csv","arguments":null,"dateRange":null,"emailNotification":[],"fields":[],"recurring":null,"status":"pending","userId":"3d08e3f3-fa38-4731-9761-8a04400e05d3","recordCount":null,"scheduledTime":"2023-02-12T19:42:52+00:00","expiredTime":"2023-03-12T19:42:52+00:00","purgedTime":"2024-06-12T19:42:52+00:00","createdTime":"2023-02-12T19:42:52+00:00","updatedTime":"2023-02-12T19:42:52+00:00","_links":[{"rel":"self","href":"https://api-sandbox.rebilly.com/organizations/a9f68e6e-e2e6-43dd-a27f-8120121d7428/experimental/data-exports/d9dd134f-0bee-46b1-bec0-992da3173336"},{"rel":"user","href":"https://api-sandbox.rebilly.com/users/3d08e3f3-fa38-4731-9761-8a04400e05d3"}]}},"_links":[{"rel":"dataExport","href":"https://api-sandbox.rebilly.com/organizations/a9f68e6e-e2e6-43dd-a27f-8120121d7428/experimental/data-exports/d9dd134f-0bee-46b1-bec0-992da3173336"},{"rel":"download","href":"https://api-sandbox.rebilly.com/organizations/a9f68e6e-e2e6-43dd-a27f-8120121d7428/files/d348968b-41ed-4d7d-b534-02e5265c8912/download"}]}');
Test webhooks
This process describes how to test webhooks in the sandbox environment using the Rebilly API.
Obtain IDs and a secret API key
This step describes how to obtain your website ID, organization ID, and secret API key from your Rebilly sandbox account.
When you first log in to Rebilly, you create an organization as part of the setup process. A default website is created when a new organization is created. For more information, see Organizations and websites.
- Log in or sign up to Rebilly.
- Obtain your organization ID and website ID:
- In the left navigation bar, press Settings .
- In the Management section, press My organization & websites.
- In the Organization details section, note the ID value.
- In the Website section, note the ID value. For more information, see Organizations and websites.
- Obtain your secret API key:
- In the left navigation bar, press Automations .
- In the Development section, press API keys.
- Optionally, if you have not created a secret key:
- In top right of the screen, press Create API key.
- In the API key type section, select Secret.
- Optionally, in the Organizations dropdown, select the organizations that can use the API key.
- Optionally, in the Allowed IPs field, enter the IP addresses that are permitted to use the API key.
- Press Save API key.
- Go to the API keys page.
- Select a secret key and copy the Key value.
Create webhook credentials
This step describes uses an interactive component to create webhook credentials in the sandbox environment. For more information, see Create a service credential.
How to use the interactive example
- Enter your organization ID:
- Beneath the Environment field, press
{{server}}
. - Beneath the URL, press Show nested variables, then press Edit.
- In the Value field, enter your organization ID and press Save.
- Beneath the Environment field, press
- Specify that you want to create a service credential of type
webhook
:- Beneath the Environment field, press
{{type}}
. - Beneath the URL, press Show nested variables, then press Edit.
- In the Value field, enter
webhook
and press Save.
- Beneath the Environment field, press
- Enter your secret API key:
- Press Security.
- In the API key field, press
{{SecretApiKey}}
, then press Set value. - In the Value field, enter your secret Rebilly sandbox API key and press Save. For more information, see Obtain IDs and a secret API key.
- Press Send.
In the response, take note of thehash
value. You will use this value in the next step.
Loading...- Enter your organization ID:
Trigger a webhook
This step describes uses an interactive component to trigger a test webhook in the sandbox environment. For more information, see Trigger a test webhook.
How to use the interactive example
- Enter your organization ID:
- Beneath the Environment field, press
{{server}}
. - Beneath the URL, press Show nested variables, then press Edit.
- In the Value field, enter your organization ID and press Save.
- Beneath the Environment field, press
- Enter your secret API key:
- Press Security.
- In the API key field, press
{{SecretApiKey}}
, then press Set value. - In the Value field, enter your secret Rebilly sandbox API key and press Save.
- Enter your webhook credentials hash:
- Press Body.
- In the credentialHash field, enter the hash value you obtained when you created webhook credentials (Step 2).
- Press Send.
Loading...- Enter your organization ID:
Alternatively, use the Rebilly UI to test a webhook.
If you leave the eventsFilter
field empty all events are active for the webhook.
Example event notification
All events are described in the Rebilly API documentation. for an example, see the invoice paid event.
For more information on Rebilly resources, see Concepts.
Retry policy for webhooks
When a webhook is triggered and an HTTP 200 OK response is not received, the webhook is marked for retry.
In both the sandbox and live environments, the webhook is automatically resent after 30 minutes, and then at exponentially increasing intervals of: 1, 2, 4, 8, and 16 hours, for a total of 6 retry attempts until successful. If still unsuccessful, it is not attempted again.
In the sandbox environment, if the webhook is unsuccessful after 48 hours and 70 consecutive attempts, the corresponding webhook subscriber is disabled.