# Webhooks Management

## Overview

Yavin sends a standardized webhook after a transaction has passed the acceptance phase, with a consistent structure for both proxi (in-store) and ecommerce transactions. Use it to be notified of transaction results without polling.

> ⚠️ This standardized webhook may break integrations that depended on the older structure or on keys that have been updated or removed. Review the structure below to ensure compatibility with your existing webhook handlers, and contact support if you need help adapting.

## Delivery

- The webhook is sent to the configured URLs of the company associated with the transaction. URLs are configured in [MyYavin](https://my.yavin.com/): Settings > API > Webhook tab (ecommerce checkouts can also pass a webhook_url per link)

- It is sent only upon acceptance of the transaction, for both proxi and ecommerce transactions

- The structure is designed to be stable and consistent going forward

Delivery rules (URL constraints, retries at 1 minute, 10 minutes, 1 hour, 8 hours, then deactivation) are described on the API pages that emit the webhook: [Cloud API](https://app.notion.com/p/3bc9a8f4fd9a81518b1bda59179c4d1b) and [Webservices API](https://app.notion.com/p/3bc9a8f4fd9a81529b21d135de85f424).

## Payload structure

All fields are optional unless specified. Amounts are integers in cents.

| Parameter | Type | Description |
| --- | --- | --- |
| trs_id | String | Transaction identifier on the Yavin server |
| local_id | String | Terminal-side identifier |
| status | String | ok, ko, pending |
| type | String | DEBIT, CREDIT, REVERSAL, REFUND |
| asked_amount | Integer | Amount requested, in cents |
| gift_amount | Integer | Tip or donation, in cents |
| total_amount | Integer | Total amount, in cents |
| currency_code | String | ISO 4217 code |
| created_at | String | Creation timestamp |
| device_datetime | String | Timestamp on the device |
| device_timestamp | Integer | Unix timestamp on the device |
| server_timestamp | Integer | Unix timestamp on the server |
| serial_number | String | Terminal identifier |
| medium | String | CARD, VAD_MOTO, PAYMENT_LINK, eDebit, WIRE, CASH, ANCV, myyavin, RESTOFLASH |
| scheme | String | AMEX, CONECS, CB, ANCV, MASTERCARD, VISA, MAESTRO |
| payment_application | String | AMEX, ANCV, CASH, CONECS_CONTACT, CONECS_CONTACTLESS, DISCOVER, EMV_CONTACT, EMV_CONTACTLESS, EMV_MOTO, EMV_PAYMENT_LINK, RESTOFLASH, OTHER, VAD_NEPTING_REFUND, WIRE |
| pan | String | Masked card PAN |
| card_token | String | Unique token of the customer card |
| reference | String | Waiter or person who performed the transaction |
| client_ticket | String | Customer ticket |
| company_ticket | String | Merchant ticket |
| receipt_ticket | Object | Receipt content (data, format) |
| app_version | String | Yavin Pay app version |
| company_id | Integer | Yavin internal company ID |
| company_external_id | Integer | External company ID |

Raw field list

```python
created_at: str
device_datetime: str
device_timestamp: int
asked_amount: int
gift_amount: int
total_amount: int
status: Literal['ok', 'ko', 'pending']
trs_id: str
serial_number: str
currency_code: str
client_ticket: str
company_ticket: str
receipt_ticket: Dict
type: Literal["DEBIT", "CREDIT", "REVERSAL", "REFUND"]
reference: str
medium: Literal["CARD", "VAD_MOTO", "PAYMENT_LINK", "eDebit", "WIRE", "CASH", "ANCV", "myyavin", "RESTOFLASH"]
scheme: Literal["AMEX", "CONECS", "CB", "ANCV", "MASTERCARD", "VISA", "MAESTRO"]
payment_application: Literal["AMEX", "ANCV", "CASH", "CONECS_CONTACT", "CONECS_CONTACTLESS", "DISCOVER", "EMV_CONTACT", "EMV_CONTACTLESS", "EMV_MOTO", "EMV_PAYMENT_LINK", "RESTOFLASH", "OTHER", "VAD_NEPTING_REFUND", "WIRE"]
app_version: str
pan: str
company_id: int
company_external_id: int
card_token: str
local_id: str
server_timestamp: int
```

## Securing your webhook endpoint

Webhook requests are not signed today. Until a signature mechanism is available, protect your endpoint:

- Use a hard-to-guess URL containing a secret token (eg https://mydomain.com/webhooks/yavin/{random_token}) and reject requests on any other path

- Never trust the webhook alone for money-related decisions: on receipt, re-verify server-side via /get_cart_information/ (ecommerce) or GET /v5/transaction/?transactionId= (proxi) before marking an order as paid

- Deduplicate: retries can deliver the same event more than once. Use trs_id (proxi) or checkout_external_id + action (ecommerce) as your idempotency key

## Related pages

[In-store payment: Cloud API](https://app.notion.com/p/3bc9a8f4fd9a81518b1bda59179c4d1b)

[Online payment: Ecommerce API](https://app.notion.com/p/3bc9a8f4fd9a810687ace255171064a7)

[Webservices API](https://app.notion.com/p/3bc9a8f4fd9a81529b21d135de85f424)
