{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Webhooks","description":"Tyro Health Docs","keywords":"redocly developer portal, api portal starter, api reference docs","lang":"en-US","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"webhooks","__idx":0},"children":["Webhooks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A webhook enables you to obtain automatic transaction updates, or for notifications where the response is delayed."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["It allows you to send real-time data from one application to another whenever a given event occurs."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"use-cases","__idx":1},"children":["Use cases"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use webhook event notifications to alert you:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["That an invoice has been created(",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["invoiceCreated"]}," ) - Optional"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["That an invoice has been completed (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["invoiceCompleted"]},") - ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Required"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["That an invoice has been canceled (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["invoiceCancelled"]},") - Optional"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"steps-to-receive-webhooks","__idx":2},"children":["Steps to receive webhooks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Use the webhooks attribute and provide:"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["URL (This is usually transaction specific)"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["webhook event: one of the above listed events"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["method: POST/GET/PUT/DELETE"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"request-example","__idx":3},"children":["Request example"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"js","header":{"controls":{"copy":{}}},"source":"\"webhooks\":[\n\n{\n\n\"method\": \"get\",\n\n\"url\": \"https://0a9c7748486fec.m.pipedream.net/transactions/updates\",\n\n\"event\": \"invoiceCompleted\"\n\n},\n\n{\n\n\"method\": \"get\",\n\n\"url\": \"https://0a9c77481236fec.m.pipedream.net/transactions/updates\",\n\n\"event\": \"invoiceCancelled\"\n\n}\n\n]\n\n\n","lang":"js"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"webhook-signature-optional","__idx":4},"children":["Webhook signature (optional)"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To enhance the webhook security further, we support signing the payload with SHA-256 hmac signature for each of the POST webhook we sent. This will allow your server to ensure it's only receiving requests coming from Tyro Health Online."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Setup"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To set up the webhook signing, please contact the customer support to apply for a secret token that will be used for signature signing. Once the secret key is generated, it will be delivered either via keybase (preferred) or secure email."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Validating request from Tyro Health Online"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Once your secret token is set by Tyro Health Online, every POST requests coming from Tyro Health Online will include two additional headers:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"js","header":{"controls":{"copy":{}}},"source":"- X-Sender-Signature | A SHA-256 HMAC hash that's generated based on X-Sender-Timestamp value and JSON stringified payload.\n- X-Sender-Timestamp | Date in ISO date string format. It represents the date the request was sent. Also, It will be used for HMAC hash calculation.\n\n| ...\n X-Sender-Signature=215d022a9e9c95fab7ca7c618d0d7b8d9e6dca1055d544b3d2421312a16a5651\n X-Sender-Timestamp=\"2021-01-13T04:23:50.659Z\" \n","lang":"js"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To verify the hmac signature, you will need to compute your own SHA-256 HMAC signature and compare it with the signature provided in the header. So the code will be something like this:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"js","header":{"controls":{"copy":{}}},"source":"const hmacSignature = Crypto.createHmac(\"sha256\", SECRET\\_TOKEN)\n .update(`${headers[\"X-Sender-Timestamp\"]}${JSON.stringify(payload)}`)\n .digest(\"hex\");\nreturn Crypto.timingSafeEqual(new Buffer.from(hmacSignature, \"utf-8\"), new Buffer.from(headers[\"X-Sender-Signature\"], \"utf-8\")); \n\n","lang":"js"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Implementation between different languages might be different. However, things to note above are:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The HMAC function has to use SHA256 method"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["The base for computing the hash is consisted of the timestamp in the header and stringified payload in the request"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Try to use timingSafeEqual equivalent function to compare the HMAC result to avoid timing attack on large string comparison"]}]}]},"headings":[{"value":"Webhooks","id":"webhooks","depth":1},{"value":"Use cases","id":"use-cases","depth":2},{"value":"Steps to receive webhooks","id":"steps-to-receive-webhooks","depth":2},{"value":"Request example","id":"request-example","depth":2},{"value":"Webhook signature (optional)","id":"webhook-signature-optional","depth":2}],"frontmatter":{"title":"Webhooks ","seo":{"title":"Webhooks"}},"lastModified":"2024-03-27T23:49:44.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/developer-portal/checkout/webhooks","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}