Skip to main content

Webhooks

O
Written by Ondřej Průša
Updated over a week ago

Webhooks are a way to receive real-time notifications from Retino about various events. Instead of periodically querying the API, you can create a webhook and Retino will automatically send you information about changes to the URL you specify.

Note: Webhooks are a premium feature included in the "API & Webhooks" extension. If you have this extension active, you can find webhook settings in Settings > API > Webhooks.

For information about the shipping.ordered webhook, see the Shipping Order Webhook article.

Creating a Webhook

  1. Prepare a URL endpoint on your server to receive webhooks (e.g., your-store.com/webhook-retino)

  2. Click "Create webhook"

  3. Enter the URL of your endpoint

  4. Select the events you want to subscribe to

  5. Save the settings

Webhooks are configured at the account level and are not limited to individual users. After creating a webhook, you can send a test event from the webhook detail to verify the correct configuration.

Security

Each webhook includes an authentication token in the request header to verify that the request is actually from Retino:

X-Retino-Secret: <token>

You can find this token in the individual webhook settings. When receiving webhooks, you should always verify that the header contains the correct token matching your webhook.

Renewing the Secret Token

IMPORTANT! If you renew the webhook token, your server will not be able to receive webhooks until you implement the new token on your side.

HTTPS

We strongly recommend using the encrypted HTTPS protocol for communication. If your webhook uses the insecure HTTP protocol, Retino will notify you about this risk in the settings.

Event Types for Tickets

A webhook can be linked to several event types simultaneously. Each event sends information about the ticket, products, shipping, and the associated order.

Event

Description

ticket.created

Creation of a new ticket

ticket.updated

Any modification of the ticket

ticket.product.created

Creation of a new product in the ticket

ticket.product.updated

Updating a product in the ticket

ticket.shipping.created

Creation of new shipping in the ticket

ticket.shipping.updated

Shipping modification or status update

ticket.refund.created

Creation of a refund

ticket.refund.updated

Modification of a refund

Sample Data for Events

ticket.created / ticket.updated

Sent when a ticket is created or modified.

{
  "event_type": "ticket.created",
  "created_at": "2020-09-24T10:28:10.010Z",
  "ticket": {
    "id": "8fad1c8d-3740-4aab-a224-c0ef379ea216",
    "code": "20210001",
    "state": "4531636a-108f-4ae3-abff-367901418600",
    "tags": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ],
    "type": "44c88eec-b995-4c84-b269-2ff06c8fe5d5",
    "owner": "e342f794-7b11-4acc-a46e-784a74a30af2",
    "bound_order": null,
    "customer": {
      "name": "Vladimír Remek",
      "email": "[email protected]",
      "phone": "987654321"
    },
    "currency": "CZK",
    "language": "cs",
    "country": "CZ",
    "order_id": "234567",
    "order_date": "2020-09-09T00:00:00.000Z",
    "customer_rating": null,
    "customer_rating_comment": null,
    "custom_fields": {
      "resolve_by": "2020-10-08"
    },
    "verification_state": "VERIFIED_AUTOMATICALLY",
    "is_unread": false,
    "created_at": "2020-09-24T11:30:53.210107+02:00",
    "updated_at": "2020-09-24T11:30:53.525472+02:00",
    "closed_at": null
  }
}

ticket.product.created / ticket.product.updated

Sent when a product is added or updated in the ticket.

{
  "event_type": "ticket.product.created",
  "created_at": "2020-09-24T10:28:10.010Z",
  "ticket_id": "8fad1c8d-3740-4aab-a224-c0ef379ea216",
  "product": {
    "id": "09c69980-299d-4d37-81d5-ed18c9565856",
    "bound_order_item": null,
    "price": {
      "with_vat": "990000000.0000",
      "without_vat": null,
      "vat": null
    },
    "files": [],
    "name": "Apollo 11",
    "manufacturer": "NASA",
    "category": "Rakety",
    "product_id": "#1",
    "variant": "XL",
    "ean": "",
    "serial": null,
    "amount": "1.0000",
    "custom_fields": {
      "1b8508b0-ba85-427c-b23c-ae739453b0cd": "74ea523e-ea95-44d4-85ff-758c485ff77d"
    }
  }
}

ticket.shipping.created / ticket.shipping.updated

Sent when shipping is created or updated.

{
  "event_type": "ticket.shipping.created",
  "created_at": "2020-09-24T10:28:10.010Z",
  "ticket_id": "8fad1c8d-3740-4aab-a224-c0ef379ea216",
  "shipping": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "vendor_id": "PPL",
    "shipping_type": "Parcel",
    "state": "WAITING_FOR_PICKUP",
    "trace_url": "http://example.com/tracking/123",
    "sender": {
      "name": "Vladimír Remek",
      "email": "[email protected]",
      "phone": "987654321",
      "address": {
        "street": "Kosmonautů 10",
        "city": "Praha",
        "zip": "16000",
        "country": "CZ"
      }
    },
    "recipient": {
      "name": "Your Store",
      "email": "[email protected]",
      "phone": "123456789",
      "address": {
        "street": "Hlavní 123",
        "city": "Praha",
        "zip": "11000",
        "country": "CZ"
      }
    },
    "created_at": "2020-09-24T10:28:10.010Z",
    "updated_at": "2020-09-24T10:28:10.010Z"
  }
}

ticket.refund.created / ticket.refund.updated

Sent when a refund is created or updated.

{
  "event_type": "ticket.refund.created",
  "created_at": "2020-09-24T10:28:10.010Z",
  "ticket_id": "8fad1c8d-3740-4aab-a224-c0ef379ea216",
  "refund": {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "amount": "990000000.0000",
    "currency": "CZK",
    "state": "WAITING_FOR_APPROVAL",
    "type": "BANK_ACCOUNT",
    "bank_account": {
      "account_number": "123456789/1010",
      "iban": "CZ1234567890123456789012",
      "bic": "GIBACZPX"
    },
    "created_at": "2020-09-24T10:28:10.010Z",
    "updated_at": "2020-09-24T10:28:10.010Z"
  }
}

Implementing Webhook Reception

To receive webhooks, you need to implement an endpoint on your server that handles HTTP POST requests. Here's a simple example implementation in Node.js:

const express = require('express');
const bodyParser = require('body-parser');
const app = express();app.use(bodyParser.json());app.post('/webhook-retino', (req, res) => {
  // Check secret token
  const token = req.headers['x-retino-secret'];
  if (token !== 'your_secret_token') {
    return res.status(403).send('Invalid token');
  }  // Process event
  const event = req.body;
  console.log(`Received event: ${event.event_type}`);  // Process data based on event type
  switch (event.event_type) {
    case 'ticket.created':
      // Process ticket creation
      console.log(`New ticket created: ${event.ticket.code}`);
      break;
    case 'ticket.product.created':
      // Process product addition
      console.log(`Product added to ticket: ${event.product.name}`);
      break;
    // other event types...
  }  // Server response
  res.status(200).send('OK');
});app.listen(3000, () => {
  console.log('Webhook receiving server running on port 3000');
});

Best Practices

  1. Token Verification - Always verify the token in the X-Retino-Secret header for security.

  2. Fast Response - Respond to the webhook as quickly as possible (ideally within 5 seconds) and perform more complex processing asynchronously.

  3. Error Handling - Implement robust error handling to make your endpoint resilient to invalid data.

  4. Logging - Log received webhooks for later analysis and debugging.

  5. Idempotence - Design webhook processing to be idempotent (repeated processing of the same event does not cause problems).

Testing Webhooks

For testing webhooks, you can use the following options:

  1. Use a service like webhook.site or requestbin.com to capture and inspect webhook requests.

  2. Use local tunneling tools like ngrok to test webhooks in your local development environment.

  3. Send a test event directly from the webhook detail in the Retino administration.

For more information on other integration options with Retino, visit the Tickets API documentation.

Did this answer your question?