Webservices API
Overview
The Webservices API is for server-to-server integrations over HTTPS: retrieve transaction data, refund transactions, and receive transaction events via webhooks. Choose it for reporting, reconciliation and refund workflows, independently of how the payments were made.
At a glance
| Base URL | Production: https://api.yavin.com/api/v5. Sandbox: https://api.sandbox.yavin.com/api/v5 |
| Authentication | API key in the Yavin-Secret header |
| Naming convention | Depends on the endpoint: Fetch transactions uses camelCase (startDate, serialNumbers) with two snake_case exceptions (only_pending, exclude_e_commerce); Refund uses snake_case (user_email). Refer to each parameters table |
| Current version | v5 |
| Result delivery | Synchronous for fetch endpoints; refunds are synchronous with a webhook on final acceptance or rejection |
Endpoints
| Endpoint | Method | Purpose |
|---|---|---|
/pos/transactions/ | POST | Fetch a batch of transactions |
/transaction/ | GET | Fetch a single transaction |
/transaction/{id}/refund/ | POST | Refund a transaction |
Before you start
Authentication and headers. Every request must carry your company API key in the Yavin-Secret header and declare Content-Type: application/json. You can find your API key on my.yavin.com in the API tab.
Timezones. On the fetch endpoint, startTime and endTime must be provided without any timezone designator (no trailing Z) and are interpreted in the timezone you provide. Always set the timezone parameter to get correct data.
Transient errors. Occasional 502 responses on heavy calls are transient gateway errors, not application errors: retry with exponential backoff. For historical imports, chunk requests day by day rather than fetching large windows.
Webhook delivery.
- Webhook URL must be HTTPS and must not attempt a redirection
- Yavin expects an HTTP 200 acknowledgement. On failure the webhook is retried at: 1 minute, 10 minutes, 1 hour, 8 hours later. After the retries are exhausted, the webhook is deactivated
For the standardized transaction webhook payload, see Webhooks Management.
Fetch a batch of transactions
https://api.yavin.com/api/v5/pos/transactions/Retrieves the transactions of a Yavin account. Use limit and offset for pagination, and the filters (dates, terminals, schemes) to retrieve only what you need. If no date filters are set, the last 30 days are fetched.
Transactions are returned in reverse chronological order (most recent first). When paginating while new transactions arrive, fix endDate and endTime to a point in the past so pages stay consistent (no duplicates, no gaps).
Parameters
startDateString- Earliest date to include, yyyy-MM-dd, inclusive. If no date filters are set, the last 30 days are fetched
endDateString- Latest date to include, yyyy-MM-dd, inclusive (the whole day unless endTime is set)
startTimeStringdefault 00:00:00- Start time on startDate, HH:mm:ss, no timezone designator, interpreted in timezone
endTimeStringdefault 23:59:59- End time on endDate, HH:mm:ss, no timezone designator, interpreted in timezone
timezoneString- Timezone ID of the caller (eg Europe/Paris). Strongly advised
limitIntegerdefault 20- Max transactions returned, up to 200
offsetIntegerdefault 0- Pagination offset
serialNumbersArray- Terminal identifiers to filter on (visible in Yavin Services)
referencesArray- References to filter on
schemesArray- Schemes to filter on
currencyCodeString- ISO 4217 code
only_pendingBooleandefault false- true: only pending transactions
exclude_e_commerceBooleandefault false- true: exclude ecommerce transactions
Request
url = 'https://api.yavin.com/api/v5/pos/transactions/'
headers = {
'Content-Type': 'application/json',
'Yavin-Secret': 'YAVIN_API_KEY'
}
params = {
"serialNumbers": ["123456789"],
"timezone": "Europe/Paris",
"startDate": "2022-01-01",
"endDate": "2022-02-01",
"startTime": "00:00:00",
"endTime": "23:59:59",
"limit": 100
}curl -X POST 'https://api.yavin.com/api/v5/pos/transactions/' \
-H 'Yavin-Secret: YAVIN_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"serialNumbers": [
"123456789"
],
"timezone": "Europe/Paris",
"startDate": "2022-01-01",
"endDate": "2022-02-01",
"startTime": "00:00:00",
"endTime": "23:59:59",
"limit": 100
}'(async () => {
const response = await fetch("https://api.yavin.com/api/v5/pos/transactions/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Yavin-Secret": process.env.YAVIN_API_KEY,
},
body: JSON.stringify({
"serialNumbers": [
"123456789"
],
"timezone": "Europe/Paris",
"startDate": "2022-01-01",
"endDate": "2022-02-01",
"startTime": "00:00:00",
"endTime": "23:59:59",
"limit": 100
}),
});
if (!response.ok) throw new Error(`Yavin API error ${response.status}`);
const data = await response.json();
console.log(data);
})();import os
import requests
headers = {
"Content-Type": "application/json",
"Yavin-Secret": os.environ["YAVIN_API_KEY"],
}
payload = {
"serialNumbers": [
"123456789"
],
"timezone": "Europe/Paris",
"startDate": "2022-01-01",
"endDate": "2022-02-01",
"startTime": "00:00:00",
"endTime": "23:59:59",
"limit": 100
}
response = requests.post(
"https://api.yavin.com/api/v5/pos/transactions/",
headers=headers,
json=payload,
)
response.raise_for_status()
data = response.json()Response
{
"total": 356,
"limit": 100,
"offset": 0,
"count": 100,
"transactions": [
{
"amount": 100,
"createdAt": "2022-05-10T14:09:06",
"customer": { "email": "", "phone": "0612345687" },
"giftAmount": 0,
"issuer": "BNP",
"scheme": "CB",
"status": "ok",
"transactionId": "IEqoLmjuRqfq",
"type": "debit",
"serialNumber": "123456789"
}
]
}Fetch a transaction
https://api.yavin.com/api/v5/transaction/Retrieves the details of a single transaction. The transaction must belong to the company associated with the API key; otherwise an error is returned.
Parameters
transactionIdStringrequired- Unique identifier of the transaction, passed in the query string
Request
curl -X GET 'https://api.yavin.com/api/v5/transaction/?transactionId=<transactionId>' \
-H 'Yavin-Secret: YAVIN_API_KEY'(async () => {
const response = await fetch("https://api.yavin.com/api/v5/transaction/?transactionId=<transactionId>", {
method: "GET",
headers: {
"Yavin-Secret": process.env.YAVIN_API_KEY,
},
});
if (!response.ok) throw new Error(`Yavin API error ${response.status}`);
const data = await response.json();
console.log(data);
})();import os
import requests
headers = {
"Yavin-Secret": os.environ["YAVIN_API_KEY"],
}
response = requests.get(
"https://api.yavin.com/api/v5/transaction/?transactionId=<transactionId>",
headers=headers,
)
response.raise_for_status()
data = response.json()Response
{
"transactionDetails": {
"askedAmount": 1000,
"giftAmount": 0,
"totalAmount": 1000,
"serverDatetime": "2022-05-10T14:09:06",
"deviceDatetime": "2022-05-10T14:09:06",
"issuer": "BNP",
"scheme": "CB",
"status": "ok",
"transactionId": "mk8wHcHUeQol",
"type": "debit",
"serialNumber": "123456789",
"clientTicket": "ticket_client_123",
"companyTicket": "ticket_merchant_123",
"receiptTicket": { "data": "receipt_data", "format": "text" },
"reference": "server_reference_123"
}
}Refund a transaction
https://api.yavin.com/api/v5/transaction/{original_transaction_id}/refund/Initiates a refund of a previously processed transaction.
Refund conditions. The point of sale must have "refunds by API" activated. The original transaction was processed by the same establishment, has no refund associated yet (multi-refunds on the same transaction are not possible), and the refund amount is greater than 0 and equal to or less than the original transaction amount. AMEX, CUP, Cash, ANCV, Conecs, Edenred and Swile transactions are not refundable. Since only one refund per transaction is possible, a partial refund makes the remaining amount permanently non-refundable via API: refund the full intended amount in a single call.
If user_email is not known in the Yavin database or has no access to MyYavin BO, an approval email is sent to all admin users of the merchant backoffice, and the refund stays in waiting until approved.
Parameters
amountIntegerrequired- Refund amount in cents, must be positive
user_emailStringrequired- Email of the user initiating the refund
vendorVendorrequired- Software editor information
Show Vendor parametersHide Vendor parameters
vendor.software_nameStringrequired- Name of the POS software
vendor.software_versionStringrequired- Version of the POS software
prioritise_tipBooleandefault false- On a partial refund: false (default), the transaction amount is refunded first; true, the tip is refunded first
Request
{
"amount": 1000,
"user_email": "user@example.com",
"vendor": {
"software_name": "MyPOS",
"software_version": "1.0"
}
}curl -X POST 'https://api.yavin.com/api/v5/transaction/{original_transaction_id}/refund/' \
-H 'Yavin-Secret: YAVIN_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"amount": 1000,
"user_email": "user@example.com",
"vendor": {
"software_name": "MyPOS",
"software_version": "1.0"
}
}'(async () => {
const response = await fetch("https://api.yavin.com/api/v5/transaction/{original_transaction_id}/refund/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Yavin-Secret": process.env.YAVIN_API_KEY,
},
body: JSON.stringify({
"amount": 1000,
"user_email": "user@example.com",
"vendor": {
"software_name": "MyPOS",
"software_version": "1.0"
}
}),
});
if (!response.ok) throw new Error(`Yavin API error ${response.status}`);
const data = await response.json();
console.log(data);
})();import os
import requests
headers = {
"Content-Type": "application/json",
"Yavin-Secret": os.environ["YAVIN_API_KEY"],
}
payload = {
"amount": 1000,
"user_email": "user@example.com",
"vendor": {
"software_name": "MyPOS",
"software_version": "1.0"
}
}
response = requests.post(
"https://api.yavin.com/api/v5/transaction/{original_transaction_id}/refund/",
headers=headers,
json=payload,
)
response.raise_for_status()
data = response.json()Response
All outcomes in one view:
| HTTP code | status | Meaning | Extra fields |
|---|---|---|---|
| 201 | refunded | The refund was processed | message = ok, transaction_id (refund transaction) |
| 202 | pending | Received, further verifications required before processing | message = ok, transaction_id |
| 202 | waiting | Received, manual approval required in the backoffice | message = ok, transaction_id, approval_url (backoffice URL to review the refund) |
| 400 | Request malformed: JSON object keyed by field, eg "amount": ["cannot be greater than the transaction's total amount"] | ||
| 400 | Refund not possible: error field, eg This transaction has already been refunded | ||
| 422 | not_possible | Refused by the issuer | message = The refund was refused by the issuer |
A webhook is sent only when the refund has been accepted or rejected, since a pending state is already known from the synchronous response. Its body is the RefundWebhook object documented below.
Set up
- Ecommerce transaction: the
webhook_urlgiven at link creation is called back - Proxi transaction: ask the Yavin Support team to configure a webhook URL for each onboarded company
The Transaction object
Returned in the list by the batch fetch endpoint.
Attributes
amountInteger- Amount in cents
giftAmountInteger- Tip or donation in cents
createdAtString- Creation date, ISO 8601
currencyCodeString- ISO 4217 code
statusString- Transaction status
transactionIdString- Unique identifier
typeString- Transaction type (eg debit)
serialNumberString- Terminal identifier
schemeString- Acceptance network (eg CB)
issuerString- Card issuer
referenceString- Waiter or person who performed the transaction
cartIdString- Order reference from the POS
customerCustomer- Customer details when available
Show Customer parametersHide Customer parameters
customer.first_nameString- First name
customer.last_nameString- Last name
customer.emailStringcustomer.phoneString- International format starting with + (eg +33612345678)
customer.birth_dateString- Birthdate
{
"amount": 100,
"giftAmount": 0,
"createdAt": "2022-05-10T14:09:06",
"currencyCode": "EUR",
"status": "ok",
"transactionId": "IEqoLmjuRqfq",
"type": "debit",
"serialNumber": "123456789",
"scheme": "CB",
"issuer": "BNP",
"reference": "Luke",
"cartId": "ORDER-2026-000123",
"customer": { "email": "", "phone": "0612345687" }
}The TransactionDetails object
Returned by the single fetch endpoint, under transactionDetails. Richer than the Transaction object: it carries the tickets and both timestamps.
Attributes
askedAmountInteger- Amount requested, in cents
giftAmountInteger- Tip or donation, in cents
totalAmountInteger- Total amount, in cents
serverDatetimeString- Creation timestamp on the server, ISO 8601
deviceDatetimeString- Creation timestamp on the device, ISO 8601
issuerString- Card issuer (eg BNP)
schemeString- Acceptance network (eg CB, VISA)
statusString- Transaction status (eg ok)
transactionIdString- Unique identifier
typeString- debit, credit, ...
serialNumberString- Terminal serial number
clientTicket / companyTicketString- Customer and merchant tickets
receiptTicketObject- Receipt content: data and format
referenceString- Reference linked to the transaction (eg waiter)
{
"askedAmount": 1000,
"giftAmount": 0,
"totalAmount": 1000,
"serverDatetime": "2022-05-10T14:09:06",
"deviceDatetime": "2022-05-10T14:09:06",
"issuer": "BNP",
"scheme": "CB",
"status": "ok",
"transactionId": "mk8wHcHUeQol",
"type": "debit",
"serialNumber": "123456789",
"clientTicket": "ticket_client_123",
"companyTicket": "ticket_merchant_123",
"receiptTicket": { "data": "receipt_data", "format": "text" },
"reference": "server_reference_123"
}The RefundWebhook object
Sent to your webhook when a refund has been accepted or rejected. Carries both the original transaction and the refund transaction, so you can reconcile without a second call.
Attributes
original_transactionObject- Details of the original transaction: transaction_id, asked_amount, gift_amount, total_amount (cents), pan (masked), date (ISO 8601)
refund_transactionObject- Same fields for the refund transaction
statusString- success or rejected
request_user_emailString- Email of the user who initiated the refund
sourceString- api or myyavin
{
"original_transaction": {
"transaction_id": "txn_1234567890",
"asked_amount": 5000,
"gift_amount": 500,
"total_amount": 5500,
"pan": "411111******1111",
"date": "2025-01-10T14:32:45Z"
},
"refund_transaction": {
"transaction_id": "txn_refund_0987654321",
"asked_amount": 5000,
"gift_amount": 500,
"total_amount": 5500,
"pan": "411111******1111",
"date": "2025-01-11T09:12:03Z"
},
"status": "success",
"request_user_email": "user@example.com",
"source": "api"
}The Customer object
Customer details attached to a transaction, when available.
Attributes
first_nameString- First name
last_nameString- Last name
emailStringphoneString- International format starting with + (eg +33612345678)
birth_dateString- Birthdate
{
"customer": {
"first_name": "John",
"last_name": "Doe",
"email": "john@yavin.com",
"phone": "+33612345678"
}
}The Vendor object
Identifies your software on a refund request. Required, and in snake_case on this endpoint.
Attributes
software_nameStringrequired- Name of the POS software
software_versionStringrequired- Version of the POS software
{
"vendor": {
"software_name": "MyPOS",
"software_version": "1.0"
}
}