{"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":3,"id":"webhooks","__idx":0},"children":["Webhooks"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Tyro machine EFTPOS payments and HealthPoint claims are synchronous transactions and details can be obtained from SDK callbacks. However, you can optionally set a webhook to receive transaction outcomes. ",{"$$mdtype":"Tag","name":"br","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To obtain automatic transaction updates, or for notifications were the response was not captured via the callbacks, Tyro Health supports the following events for each payment and/or HealthPoint transaction:"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"use-cases","__idx":1},"children":["Use cases"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The following webhook event notifications can be used:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["That an transaction has been completed (",{"$$mdtype":"Tag","name":"highlight","attributes":{"backgroundcolour":"grey","textcolour":"dark"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["invoiceCompleted"]}," "]},")"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["That an transaction has been cancelled (",{"$$mdtype":"Tag","name":"highlight","attributes":{"backgroundcolour":"grey","textcolour":"dark"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["invoiceCancelled"]}]},")"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["That an transaction has been created  (",{"$$mdtype":"Tag","name":"highlight","attributes":{"backgroundcolour":"grey","textcolour":"dark"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["invoiceCreated"]}]},")"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["That an transaction has been refunded (",{"$$mdtype":"Tag","name":"highlight","attributes":{"backgroundcolour":"grey","textcolour":"dark"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["invoiceRefunded"]}," "]},")"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["That an invoice has been paid  (",{"$$mdtype":"Tag","name":"highlight","attributes":{"backgroundcolour":"grey","textcolour":"dark"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["medipassPaidInvoice"]}," "]},") by Tyro Health to the settlement bank details."]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Additionally it is recommended as best practice to utilise the webhooks as a notification event and directly use the following to poll for the status of the transaction -"," ","https://stg-api-au.medipass.io/v3/transactions/{transactionId}"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"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":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"numberlabel","attributes":{"number":"1"},"children":[" URL (This is usually transaction specific)"]}," ",{"$$mdtype":"Tag","name":"numberlabel","attributes":{"number":"2"},"children":[" webhook event: one of the above listed events "]}," ",{"$$mdtype":"Tag","name":"numberlabel","attributes":{"number":"3"},"children":[" method: ",{"$$mdtype":"Tag","name":"highlight","attributes":{"backgroundcolour":"green"},"children":["POST/GET/PUT/DELETE"]}," "]}," ",{"$$mdtype":"Tag","name":"numberlabel","attributes":{"number":"4"},"children":["Any required headers "]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"example","__idx":3},"children":["Example"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"js","header":{"controls":{"copy":{}}},"source":"\nmedipassTransactionSDK.renderCreateTransaction({\n  ...\n  webhooks: [\n     {\n      url: 'https://your-site.com/transactions/your-transactionId/completed',\n      event: 'invoiceCompleted',\n      method: 'POST',\n      headers: { sessionKey: 'your required header' }\n    },\n    {\n      url: 'https://your-site.com/transactions/your-transactionId/cancelled',\n      event: 'invoiceCancelled',\n      method: 'POST',\n      headers: { sessionKey: 'your required header' }\n    },\n    {\n      url: 'https://your-site.com/transactions/your-transactionId/created',\n      event: 'invoiceCreated',\n      method: 'POST',\n      headers: { sessionKey: 'your required header' }\n    },\n    {\n      url: 'https://your-site.com/transactions/your-transactionId/refunded',\n      event: 'invoiceRefunded',\n      method: 'POST',\n      headers: { sessionKey: 'your required header' }\n    },\n    {\n      url: 'https://your-site.com/transactions/your-transactionId/paid',\n      event: 'medipassPaidInvoice',\n      method: 'POST',\n      headers: { sessionKey: 'your required header' }\n    }\n  ]\n\n  \n  ...\n})\n\n","lang":"js"},"children":[]},{"$$mdtype":"Tag","name":"blockquote","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Note all new partners should refer to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["transaction.businessStatus"]}," as ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["transaction.status"]}," is obsolete."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"event-handling","__idx":4},"children":["Event handling"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"retries","__idx":5},"children":["Retries"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["We will attempt to retry failed webhooks if a timeout or '500' response is received from your endpoint. Retries are performed every 15 minutes for up to 24 hours or until a successful response is received.",{"$$mdtype":"Tag","name":"br","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":4,"id":"sequencing--ordering","__idx":6},"children":["Sequencing & ordering"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["We do not guarantee delivery of webhook events in the order in which they are generated. Although it is rare, payment and invoice status events could be received out of sequence.",{"$$mdtype":"Tag","name":"br","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["To handle this, we suggest to use the modified timestamp to determine if an update to status is appropriate for a given transaction. Alternatively, you can use our ",{"$$mdtype":"Tag","name":"highlight","attributes":{"backgroundcolour":"babyblue"},"children":["GET"]},"  Invoice API to determine to current status.",{"$$mdtype":"Tag","name":"br","attributes":{},"children":[]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"webhook-signature-optional","__idx":7},"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 ",{"$$mdtype":"Tag","name":"highlight","attributes":{"backgroundcolour":"green"},"children":["POST"]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<base-url>/v3/auth/token"]}," webhook we sent. This will allow your server to ensure it’s only receiving requests coming from Tyro Health."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":5,"id":"setup","__idx":8},"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":"Heading","attributes":{"level":5,"id":"validating-requests-from-tyro-health-online","__idx":9},"children":["Validating requests from Tyro Health Online"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Once your secret token is set by Tyro Health Online, every ",{"$$mdtype":"Tag","name":"highlight","attributes":{"backgroundcolour":"green"},"children":["POST"]},"  ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["<base-url>/v3/auth/token"]}," request coming from Tyro Health Online will include two additional headers:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["X-Sender-Signature | A SHA-256 HMAC hash that's generated based on X-Sender-Timestamp value and JSON stringified payload."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["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."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"header":{"controls":{"copy":{}}},"source":"...\nX-Sender-Signature=215d022a9e9c95fab7ca7c618d0d7b8d9e6dca1055d544b3d2421312a16a5651\nX-Sender-Timestamp=\"2021-01-13T04:23:50.659Z\"\n"},"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","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 comprised 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":3},{"value":"Use cases","id":"use-cases","depth":4},{"value":"Steps to receive webhooks","id":"steps-to-receive-webhooks","depth":4},{"value":"Example","id":"example","depth":4},{"value":"Event handling","id":"event-handling","depth":3},{"value":"Retries","id":"retries","depth":4},{"value":"Sequencing & ordering","id":"sequencing--ordering","depth":4},{"value":"Webhook signature (optional)","id":"webhook-signature-optional","depth":3},{"value":"Setup","id":"setup","depth":5},{"value":"Validating requests from Tyro Health Online","id":"validating-requests-from-tyro-health-online","depth":5}],"frontmatter":{"title":"Webhooks ","seo":{"title":"Webhooks"}},"lastModified":"2025-04-07T05:49:16.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/developer-portal/mcp/webhooks","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}