Skip to content
vinieta.md Developers

Quickstart

The canonical happy path — quote, order, pay and retrieve a vignette, worked end to end.

This is the canonical happy path, worked end to end with an EU vignette (vignette:eu) for an MD-registered vehicle. The same 4-step sequence applies to every product — only the get-offers / product body shape changes.

Replace PARTNER_ID and the signature in each X-Hmac-Signature header with your own partner id and a freshly computed HMAC-SHA512(rawBody, partnerSecret) for that specific request body. The signatures shown are placeholders — see Authentication.

Ask for offers for a Bulgarian EU vignette on an MD vehicle:

get-offers
curl -X POST https://api.vinieta.md/v1/get-offers \
-H "Content-Type: application/json" \
-H "X-Hmac-Signature: PARTNER_ID:SIGNATURE_OVER_THIS_BODY" \
-d '{
"product": "vignette:eu",
"country": "bg",
"vehicle": "123456789",
"start_date": "2026-06-10"
}'

Each offer carries the validity option id you pass back to create-order, and a price in MDL:

Response
{
"offers": [
{
"product": "vignette:eu",
"country": "bg",
"country_name": "Bulgaria",
"validity": "bg-7d",
"duration": 7,
"name": "Vinietă Europa - Bulgaria, 7 zile",
"price": 179.15,
"currency": "MDL",
"reference_price": "8.82 EUR",
"reference_exchange_rate": "1 EUR 19.27 MDL",
"min_start_date": "2026-06-10"
}
]
}

Pick an offer; pass its country + validity:

create-order
curl -X POST https://api.vinieta.md/v1/create-order \
-H "Content-Type: application/json" \
-H "X-Hmac-Signature: PARTNER_ID:SIGNATURE_OVER_THIS_BODY" \
-d '{
"customer": {
"name": "John Doe",
"email": "[email protected]",
"phone": "+37379000000"
},
"products": [
{
"product": "vignette:eu",
"vehicle": "123456789",
"start_date": "2026-06-10",
"country": "bg",
"validity": "bg-7d"
}
]
}'

Note the id (you need it for every later call) and status: "draft":

Response
{
"id": "EUV001002ABC",
"status": "draft",
"description": "Vinietă Europa, BG, 7 zile, BMW X7 ISG313",
"start_date": "2026-06-10",
"price": 179.15,
"currency": "MDL"
}

Collect price MDL from the customer, then submit the payment receipt. This is only allowed while the order is draft:

confirm-order
curl -X POST https://api.vinieta.md/v1/confirm-order \
-H "Content-Type: application/json" \
-H "X-Hmac-Signature: PARTNER_ID:SIGNATURE_OVER_THIS_BODY" \
-d '{
"id": "EUV001002ABC",
"payment": {
"receipt_id": "1234567890",
"transaction_id": "1234567890",
"paid_at": 1749513600000,
"amount": 179.15,
"currency": "MDL",
"pos_id": "terminal001"
}
}'

The order moves to paid (for EU vignette it then transitions to processing while the provider issues the vignette asynchronously):

Response
{
"id": "EUV001002ABC",
"status": "paid",
"description": "Vinietă Europa, BG, 7 zile, BMW X7 ISG313",
"start_date": "2026-06-10",
"end_date": "2026-06-16",
"price": 179.15,
"currency": "MDL"
}

EU vignette issuance + PDF generation is asynchronous, so the order goes paidprocessingcompleted. Poll get-order (or wait for the completion webhook). When status is completed, the vignette PDF appears under products[].file:

get-order
curl -X POST https://api.vinieta.md/v1/get-order \
-H "Content-Type: application/json" \
-H "X-Hmac-Signature: PARTNER_ID:SIGNATURE_OVER_THIS_BODY" \
-d '{ "id": "EUV001002ABC" }'
Response
{
"id": "EUV001002ABC",
"status": "completed",
"description": "Vinietă Europa, BG, 7 zile, BMW X7 ISG313",
"start_date": "2026-06-10",
"end_date": "2026-06-16",
"price": 179.15,
"currency": "MDL",
"products": [
{
"product": "vignette:eu",
"country": "bg",
"validity": "bg-7d",
"plate_number": "ISG313",
"car_model": "BMW X7",
"vin": "WVWZZZ1JZXW000001",
"registration_country": "md",
"document_number": "ORD-0000000000",
"transaction_id": "ORD-0000000000",
"start_date": "2026-06-10",
"end_date": "2026-06-16",
"reference_price": "8.82 EUR",
"reference_exchange_rate": "1 EUR = 19.27 MDL",
"price": 179.15,
"currency": "MDL",
"file": "https://firebasestorage.googleapis.com...."
}
]
}

That is the full lifecycle: quote → draft → paid → (processing) → completed, with the vignette PDF at products[].file. For synchronously-issued products the completed state (and file) is available shortly after confirm without a processing stage.

Statuses: draft, paid, processing, failed, completed, refunded, expired.

create-order → draft
confirm-order (pay) → paid
(issuance) → processing (only when issuance/PDF is asynchronous, e.g. vignette:eu)
issued OK → completed (products[].file PDF available)
issuance failed → failed

Other terminal/transition states:

  • expired — a draft order not paid before 23:59:59 EEST the same day is automatically expired and can no longer be confirmed.
  • refunded — a previously paid/completed order that was refunded.

Rules to enforce in your integration:

  • Only confirm (pay) an order while it is in draft. Confirming any other status is invalid.
  • Accept customer payment only for draft orders.
  • vignette:ro and vignette:md typically complete shortly after confirm; vignette:eu always goes through processing because issuance + PDF re-hosting is asynchronous (usually completes within a minute).
  • To get the issued vignette: either poll get-order until status === "completed" and read products[].file, or register a webhook and react to the completed event (then call get-order).
  • Wallet partners may replace the confirm-order step with pay-order-from-balance.