Skip to main content

Webhooks

To integrate with Tippy, your API will need to receive REST calls from our API.

When you sign up, you can specify a URL where our API can reach out to you. We'll issue REST calls to notify you of events happening on Tippy system. Every call will be equipped with eventTopic in a body and X-Event-Topic in the header. Additionally the headers will include X-Event-Id.

All calls will be encoded as application/json and sent with the POST method. They will include a signature in the X-Request-Signature-SHA-256 header which you can use to verify that the call actually originated from us.

Validating Webhooks#

When you receive calls to your webhook URL, you'll always want to make sure that it's really Tippy making the call, and not an impersonator. Tippy signs each webhook event with your app secret. The signature is contained in the X-Request-Signature-SHA-256 header and is a SHA256 HMAC hash of the request body with the key being your app secret.

You can validate the webhook by generating the same SHA256 HMAC hash and comparing it to the signature sent with the payload.

TS Example

import crypto from 'crypto';
// Validates a webhook call's body by comparing it to a provided signature.
// Returns `true` if valid and `false` if invalid.
function validateWebhookCall(body: string, signature: string): boolean {
return (
signature ===
crypto
.createHmac('sha256', process.env.YOUR_TIPPY_APP_SECRET)
.update(body)
.digest('hex')
);
}

Event Reference#

Listed below are all the possible events that Tippy's API can emit.

tips_selected#

With Display Integration, when customers select tips on our device, we'll use this event to let you know which tips they selected and the fees that Tippy will charge for them.

Event topic: tips_selected

Products: Display Integration

Event body structure (TS notation)

interface TipsSelectedWebhook {
eventTime: string; // The time when this endpoint was called, in ISO8601 format
eventId: string; // A unique identifier for the call, used for debug purposes
eventTopic: "tips_selected";
data: {
fees: {
tippy: number; // Tippy's fee for the transaction
pos: number; // The PoS's fee for the transaction
total: number; // The total fee for the transaction
};
chargeAmount: number; // The total charge amount
totalTips: number; // The total amount of the tips
transactionId: string; // The transaction id
accountToken: string; // Integration token of business account being terminated
tips: {
employeeId: string; // The employeeId that uniquely identifies a staff member between you and Tippy
tipAmount: number; // The selected tip amount
level: "low" | "medium" | "high" | "custom"; // Which tip suggestion the user selected
}[] // This is an array of objects, each representing a tip selection for one staff member
}
}

Event example

POST ${WEBHOOK_URL} HTTP/1.1
Host: ${YOUR_API_ROOT}
X-Request-Signature-SHA-256: ${SHA_256_SIGNATURE}
Content-Type: application/json
{
"eventTime": "2021-04-11T21:41:53.569Z",
"eventId": "f1de6a40-2612-45f6-909a-ab9a7587b497",
"eventTopic": "tips_selected",
"data": {
"fees": {
"tippy": 1.47,
"pos": 0.48,
"total": 1.95
},
"chargeAmount": 167.01,
"totalTips": 40,
"transactionId": "transactionId_12",
"tips": [
{
"employeeId": "3402-23232",
"tipAmount": 30,
"level": "high",
"fee": 1.46
},
{
"employeeId": "3402-23231",
"tipAmount": 10,
"level": "low",
"fee": 0.49
}
]
}
}

tips_split#

Staff members may opt to split tips after they've received them. They do this if two or more staff members worked on a service, but only one of them received a tip. Example: Mary receives a $30 tip, but wants to give $5 from that tip to Walter and $10 to Candace, as they helped her with her work.

We'll issue this event when staff members split tips between them. The person that's initiating the split will have a negative tipAmount, while recipients will have a positive amount.

Event topic: tips_split

Products: Display Integration, Data Integration

Event body structure (TS notation)

interface TipsSplitWebhook {
eventTime: string; // The time when this endpoint was called, in ISO8601 format
eventId: string; // A unique identifier for the call, used for debug purposes
eventTopic: "tips_split";
data: {
transactionId: string; // The transaction id
accountToken: string; // Integration token of business account being terminated
locationIdentifier: string; // Location id
tips: {
employeeId: string; // The employeeId that uniquely identifies a staff member between you and Tippy
tipAmount: number; // The amount that's being sent/received in the split
}[] // This is an array of objects, each representing a sender or recipient of a split
}
}

Event example

POST ${WEBHOOK_URL} HTTP/1.1
Host: ${YOUR_API_ROOT}
X-Request-Signature-SHA-256: ${SHA_256_SIGNATURE}
Content-Type: application/json
{
"eventTime": "2021-04-15T11:12:14.038Z",
"eventId": "86df3d70-789d-42b4-9a5f-d86e22f7ad8f",
"eventTopic": "tips_split",
"data": {
"tips": [
{
"employeeId": "65ASSTY67K006TV3",
"tipAmount": -15,
},
{
"employeeId": "Y67K006TV365ASST",
"tipAmount": 10,
},
{
"employeeId": "Y67K006TV363ASDD",
"tipAmount": 5,
}
]
}
}

tip_refunded#

This webhook event is dispatched when an Owner or Manager initiates a tip refund through the Tippy dashboard. This action triggers our system to automatically send a webhook to the designated URL, delivering comprehensive details about the refunded transaction, including information on the specific employee involved and the refund amount.

Event topic: tip_refunded

Products: Display Integration, Data Integration

Event body structure (TS notation)

interface TipRefundedWebhook {
eventTime: string; // The time when this endpoint was called, in ISO8601 format
eventId: string; // A unique identifier for the call, used for debug purposes
eventTopic: "tip_refunded";
data: {
accountToken: string; // Integration token of business account
locationIdentifier: string; // Location id
transactionId: string; // The transaction id being refunded
amount: string; // Refunded amount
employeeId: string; // Employee id being refunded
tipId: number // Refunded tip id
}
}

Event example

POST ${WEBHOOK_URL} HTTP/1.1
Host: ${YOUR_API_ROOT}
X-Request-Signature-SHA-256: ${SHA_256_SIGNATURE}
Content-Type: application/json
{
"eventTime": "2021-04-15T11:12:14.038Z",
"eventId": "86df3d70-789d-42b4-9a5f-d86e22f7ad8f",
"eventTopic": "tip_refunded",
"data": {
"transactionId": "3-1787-12185979-ae099",
"amount": 5,
"employeeId": "Y67K006TV363ASDD",
}
}

integration_terminated#

Accounts may choose to stop using Tippy services or integration might become disabled for various reasons. When this happens we will send an integration_terminated event with matching accountToken.

After sending this event Tippy will no longer accept tip requests with this accountToken and POS should fallback to a checkout flow without Tippy.

Event topic: integration_terminated

Products: Display Integration, Data Integration

Event body structure (TS notation)

interface IntegrationTerminatedWebhook {
eventTime: string; // The time when this endpoint was called, in ISO8601 format
eventId: string; // A unique identifier for the call, used for debug purposes
eventTopic: "integration_terminated";
data: {
accountToken: string; // Integration token of business account being terminated
}
}

Event example

POST ${WEBHOOK_URL} HTTP/1.1
Host: ${YOUR_API_ROOT}
X-Request-Signature-SHA-256: ${SHA_256_SIGNATURE}
Content-Type: application/json
{
"eventTime": "2021-04-15T11:12:14.038Z",
"eventId": "86df3d70-789d-42b4-9a5f-d86e22f7ad8f",
"eventTopic": "integration_terminated",
"data": {
"accountToken": "1dhjp1qhckmad2547"
}
}

transaction_canceled#

Depending on POS implementation, from time to time devices can find themselves in an unstable state. If that happens, admins and owners have an option to clear the state of the device which will cancel any pending (incomplete) transactions and emit a webhook to notify POS.

Event topic: transaction_canceled

Products: Display Integration

Event body structure (TS notation)

interface TransactionCanceledWebhook {
eventTime: string; // The time when this endpoint was called, in ISO8601 format
eventId: string; // A unique identifier for the call, used for debug purposes
eventTopic: "transaction_canceled";
data: {
transactionId: string; // The transaction id
}
}

Event example

POST ${WEBHOOK_URL} HTTP/1.1
Host: ${YOUR_API_ROOT}
X-Request-Signature-SHA-256: ${SHA_256_SIGNATURE}
Content-Type: application/json
{
"eventTime": "2021-04-15T11:12:14.038Z",
"eventId": "86df3d70-789d-42b4-9a5f-d86e22f7ad8f",
"eventTopic": "transaction_canceled",
"data": {
"transactionId": "3-1787-12185979-ae099"
}
}