For the complete documentation index, see llms.txt. This page is also available as Markdown.

Webhook for Tylt CrossRamp (Pay-in)


Overview

Tylt sends real-time transaction-status notifications to the callBackUrl supplied when the CAD pay-in instance is created.

A webhook is sent whenever the payment instance moves from one lifecycle state to another.

The webhook should be used as the primary mechanism for receiving transaction updates. Merchants may use the Get Instance Information endpoint to independently confirm the latest transaction status.


Setting Up the Webhook

1. Create a Callback Endpoint

The merchant must provide a publicly accessible HTTPS endpoint that:

  • Accepts HTTP POST requests.

  • Accepts a JSON request body.

  • Preserves the original raw request body.

  • Validates the X-TLP-SIGNATURE header.

  • Processes each status update idempotently.

  • Returns HTTP status 200 with the text ok in the response body.

2. Submit the Callback URL

Include the callback endpoint in the callBackUrl field when creating the pay-in instance.

3. Process Status Updates

Each webhook contains an eventId identifying the latest transaction state.

The merchant should perform customer crediting, order fulfilment or other irreversible actions only after receiving and validating eventId: 5.


Webhook Headers

Header
Description

Content-Type

application/json

X-TLP-SIGNATURE

HMAC-SHA256 signature generated from the exact raw webhook body using the merchant’s API Secret Key.

sign

Legacy signature header retained for compatibility.


Webhook Reponses ( Event Id: 1 through Event Id: 12)

1. Instance Created (eventId: 1)

Triggered when a payment instance is created. The step initiates the payment and settlement flow.

2. Order Created / Payment Pending (eventId: 2)

Triggered with an interac payment link is generated and the payment is pending.

Payment Processing (eventId: 3)

Triggered when the payment is initiated by the end-user and the payment is under processing.

4. Payment Fulfilled (eventId: 4)

Triggered when the payment is initiated by the end-user and the status is fullfiled. This status is not an intermediate step and does not signify completed or finality of the fiat payment.

5. Payment Completed (eventId: 5)

Triggered when the fiat payment by the end-user has been completed and settled.

6. Settlement Pending (eventId: 6)

Triggered when the fiat payment is completed and the on-chain settlement to the end-user wallet has been initiated. This process is triggered only at the settlement Time (T+1 etc) is elapsed.

7. Settlement Completed (eventId: 7)

Triggered directly via internal withdrawal sequences dispensing crypto natively. hash attaches.

8. Payment Failed (eventId: 8)

Triggered if the payment process fails or the settlement process fails.

9. Order Expired (eventId: 9)

Triggered when the Interac Payment Link expires due to non payment by the end-user. The link expires 48 hours after issuance.

10. Refund Initiated (eventId: 10)

Triggered actively when a manual admin refund is iniated.

11. Refund Completed (eventId: 11)

Hook triggers directly upon verifying the Interac refund securely reaching the user.

12. KYC Failed (eventId: 12)

Strictly triggered when the KYC processor natively responds with a formal rejection on the ID tier mappings for the specific instance user trace.


Webhook Fields

Field
Type
Description

data.instanceId

string

Unique pay-in instance identifier generated by Tylt.

data.isBuying

number

Indicates transaction direction. 1 represents a pay-in / on-ramp transaction.

data.callBackUrl

string

Callback URL configured for receiving transaction-status webhooks.

data.merchantOrderId

string

Unique transaction reference supplied by the merchant.

data.interacUrl

string or null

Interac payment URL associated with the transaction, where applicable. May be null before the Interac request is generated.

data.eventDetails

object

Current transaction lifecycle information.

data.eventDetails.eventId

number

Numeric identifier representing the current transaction state.

data.eventDetails.description

string

Human-readable description of the current transaction state.

data.accounts

object

Fiat, crypto, rate, fee and settlement-amount details for the transaction.

data.accounts.fiatCurrency

string

Fiat currency used for the transaction. For Canada pay-ins, this is CAD.

data.accounts.fiatAmount

number

Amount paid or to be paid by the end user in CAD.

data.accounts.cryptoCurrency

string

Crypto-asset used for settlement, such as USDC or USDT.

data.accounts.cryptoAmount

number

Gross crypto amount calculated from the fiat amount using the applicable conversion rate.

data.accounts.toReleaseAmount

number

Net crypto amount to be released or credited after applicable fees and transaction adjustments.

data.accounts.effectiveRate

number

Effective conversion rate applicable after incorporating the commercial pricing or spread applied to the transaction.

data.accounts.rate

number

Base CAD-to-crypto conversion rate used for the transaction calculation.

data.accounts.fees

number

Total transaction fees applied to the transaction, expressed in the settlement asset unless otherwise configured.

data.accounts.MDR

number

Merchant Discount Rate applied to the transaction.

data.cryptoSettlementDetails

object

Details relating to settlement of the crypto asset.

data.cryptoSettlementDetails.Status

string or null

Current crypto settlement status. May be null before settlement is initiated.

data.cryptoSettlementDetails.hash

string or null

Blockchain transaction hash for external settlement. null for transactions not yet settled or where no on-chain transaction is required.

data.cryptoSettlementDetails.address

string or null

Destination wallet address for external settlement. May be null for internal settlement.

data.cryptoSettlementDetails.Network

string or null

Blockchain or internal network identifier associated with settlement.

data.cryptoSettlementDetails.type

string

Settlement type. Typically internal or external.


Validating the Webhook Signature

Tylt signs the exact raw JSON webhook body using HMAC-SHA256 and the merchant’s API Secret Key.

The resulting lowercase hexadecimal digest is sent in the X-TLP-SIGNATURE header.

The merchant must:

  1. Read the exact raw request body.

  2. Generate an HMAC-SHA256 signature using the API Secret Key.

  3. Compare the generated signature with X-TLP-SIGNATURE.

  4. Use a constant-time comparison.

  5. Reject the webhook when the signatures do not match.

  6. Parse and process the JSON only after successful validation.

Do not parse and re-serialise the JSON before generating the signature. Changes to spacing, field order or encoding may change the calculated signature.


Node.js Webhook Example


Acknowledging the Webhook

After successfully validating and recording the webhook, return:

The callback is acknowledged only when Tylt receives HTTP status 200 and the response body ok.

Webhooks are not automatically retried when an acknowledgement is not received. Missed webhooks may be manually resent through the Tylt dashboard.


Webhook Processing Requirements

  • Always validate X-TLP-SIGNATURE.

  • Match the instanceId and merchantOrderId against the merchant’s records.

  • Store and process webhook events idempotently.

  • Do not assume that every intermediate event will always be received.

  • Do not credit the customer based on an intermediate status.

  • Treat eventId: 5 (Payment Completed),eventId: 6 (Settlement Pending), andeventId: 7 (Settlement Completed)as successful states. 7 is the ultimate terminal success state.

  • Treat event IDs8 (Failed), 9 (Expired), 10 (Refund Initiated), and 12 (KYC Failed)as terminal unsuccessful states.

  • Use the Get Instance Information endpoint to verify an uncertain or missing status.

  • Store the webhook body, signature, event ID, processing result and timestamp for reconciliation.

Last updated