Quickstart
Get up and running with the Cloud API in under 5 minutes. This guide uses curl -- no SDK required.
If your POS runs on-premise, on tablets, or needs offline support, see the SDK Quickstart instead.
Base URL
https://api.zyntem.dev
For local development:
http://localhost:8080
1. Create an account
Create an account to receive your API key. This is a public endpoint -- no authentication required.
For a typical user-signup flow, send the user's GDPR Art. 7(1) consent capture along with the account fields. Both terms_accepted_at (the wall-clock time the user accepted) and privacy_policy_version (the version of the policy text shown) are required and travel together.
curl -X POST https://api.zyntem.dev/v1/accounts \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Corp",
"billing_email": "admin@acme.com",
"terms_accepted_at": "2026-03-08T12:00:00Z",
"privacy_policy_version": "v1.0"
}'
If you provision accounts from a backend that captured consent out-of-band (e.g. an existing onboarding flow), omit both terms_accepted_at and privacy_policy_version. The request body is a oneOf: either both consent fields are present, or both are absent — partial pairs are rejected with 400 Bad Request.
Response:
{
"account": {
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "Acme Corp",
"billing_email": "admin@acme.com",
"status": "active",
"created_at": "2026-03-08T12:00:00Z"
},
"api_key": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"key_prefix": "zyn_test_",
"key": "zyn_test_abc123def456...",
"environment": "test",
"created_at": "2026-03-08T12:00:00Z"
}
}
The plaintext API key is returned only on creation and cannot be retrieved again. Store it securely.
2. Create a location
Use your API key to create a merchant location. Here's a Spanish location with TicketBAI:
country_config is parsed and validated against the country-specific schema at the moment you register the location. Invalid config returns 400 Bad Request immediately — there is no fallback "try again at transaction time". Once accepted, the config is sealed and cannot be partially overridden per transaction. Required fields differ per country; see the API reference for the full list of 400 errors.
curl -X POST https://api.zyntem.dev/v1/locations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer zyn_test_abc123def456..." \
-d '{
"name": "Madrid Office",
"country": "ES",
"address": "Calle Gran Vía 1, 28013 Madrid",
"tax_id": "B12345674",
"country_config": {
"system": "ticketbai",
"territory_code": "48"
}
}'
Response:
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"account_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
"name": "Madrid Office",
"country": "ES",
"address": "Calle Gran Vía 1, 28013 Madrid",
"tax_id": "B12345674",
"country_config": {
"system": "ticketbai",
"territory_code": "48"
},
"status": "active",
"created_at": "2026-03-08T12:00:00Z",
"updated_at": "2026-03-08T12:00:00Z"
}
3. List your locations
curl https://api.zyntem.dev/v1/locations \
-H "Authorization: Bearer zyn_test_abc123def456..."
Response:
{
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Madrid Office",
"country": "ES",
"status": "active"
}
],
"total": 1,
"limit": 20,
"offset": 0
}
4. Update a location
curl -X PATCH https://api.zyntem.dev/v1/locations/550e8400-e29b-41d4-a716-446655440000 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer zyn_test_abc123def456..." \
-d '{
"name": "Madrid HQ"
}'
5. Delete a location (optional)
curl -X DELETE https://api.zyntem.dev/v1/locations/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer zyn_test_abc123def456..."
Returns 204 No Content on success.
6. Submit a transaction
Submit a sale for fiscalization. Zyntem never blocks the cash register -- the response is always 201 Created with the fiscal ID and receipt data populated immediately. Submission to the tax authority is handled automatically in the background.
On zyn_test_* keys, the request below works as-is: Zyntem synthesises a stubbed authority response without uploading a sandbox certificate or making a network call to the regulator. To exercise the real regulator sandbox instead (requires POST /v1/certificates first), opt in with the X-Zyntem-Sandbox header:
-H "X-Zyntem-Sandbox: authority" \
See the Sandbox modes guide for the full emulator vs authority story and the X-Zyntem-Test-Scenario catalog for driving error paths.
curl -X POST https://api.zyntem.dev/v1/transactions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer zyn_test_abc123def456..." \
-H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
-d '{
"location_id": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-03-09T14:30:00Z",
"items": [
{"description": "Café con leche", "quantity": 2, "unit_price": 250, "tax_rate": 21.0, "tax_amount": 105, "total_amount": 605},
{"description": "Tostada", "quantity": 1, "unit_price": 300, "tax_rate": 21.0, "tax_amount": 63, "total_amount": 363}
],
"pretax_amount": 800,
"tax_amount": 168,
"total_amount": 968,
"currency": "EUR",
"payment_method": "card"
}'
unit_price is pretax in minor currency units (cents). Each line's tax_amount is quantity × unit_price × tax_rate / 100, and total_amount is quantity × unit_price + tax_amount. The request-level totals must equal the sum of the per-line values.
Response:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"type": "sale",
"status": "pending",
"amount": 968,
"currency": "EUR",
"environment": "test",
"created_at": "2026-03-09T14:30:01Z"
}
7. Check transaction status
Poll for the fiscalization result:
curl https://api.zyntem.dev/v1/transactions/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Authorization: Bearer zyn_test_abc123def456..."
Response (once fiscalized):
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "success",
"fiscal_id": "TBAI-12345678",
"environment": "test",
"submitted_at": "2026-03-09T14:30:02Z",
"completed_at": "2026-03-09T14:30:03Z"
}
Configure a webhook to receive fiscalization.completed events instead of polling for status.
Next steps
- SDK Overview -- Compare Cloud API vs Embedded Local SDKs
- SDK Quickstart -- Embedded Local quickstart for Python, .NET, Android, and more
- Authentication guide -- API key management and test vs live mode
- Sandbox routing -- Understand test vs live mode
- Sandbox modes -- Emulator vs authority and the
X-Zyntem-Test-Scenariocatalog - API Reference -- Full endpoint documentation
- Spain guide -- TicketBAI, Verifactu, and SII configuration
- Italy guide -- FatturaPA and SDI electronic invoicing
- France guide -- NF525 compliance with signature chains and audit logging
- Webhooks -- Set up real-time notifications
- Error handling -- Understanding error responses