https://api.rrr.lt
Companion to: the endpoint reference in this documentation
Support: [email protected]
Ovoko (also written RRR — the two names refer to the same platform, and both appear in URLs, field values, and documentation) is a marketplace for used car parts. The API gives you access to your own CRM within this platform.
The data model has two levels, and the ordering matters:
Car → Part. A car is the donor vehicle. Parts belong to a car. You cannot create a part without an existing car, so every listing flow starts with a car import even if the car itself is of no interest to you.
Beyond that sit orders (a buyer purchases your part), order returns, and refunds.
The endpoints are grouped three ways:
| Group | Purpose |
|---|---|
| CRM Import | Create and modify cars, parts, invoices, shipment data |
| CRM Export | Read cars, parts, orders, returns, invoices, logs |
| CRM Info | Fetch the enumerations you need to build valid import requests — car models, categories, fuel types, statuses, and so on |
NOTE: CRM Info is the group first-time integrators overlook. Nearly every field on a car or part is an integer ID drawn from an Ovoko-controlled list, and those lists are only available from the API. Plan for a sync job, not a hardcoded mapping.
These apply to every endpoint. They are unusual enough that skipping this section will cost you an afternoon.
There are no GET endpoints. Retrieving a car is a POST. This includes all of CRM Export and CRM Info.
Requests must be application/x-www-form-urlencoded (or
multipart/form-data for file upload).
Sending Content-Type: application/json will not work.
Responses, confusingly, are JSON.
username, password, and user_token go in the form body of
every call, including reads. There is no session, no login endpoint, no token exchange.
There are 2 layers in handling errors:
$httpCode)
$response['status_code'] and
$response['msg'] as in the example below:
// This handles infrastructure errors
if ($httpCode === 200) { /* ... */ }
// This handles application-level errors
$response = json_decode(curl_exec($ch), true);
if ($response['status_code'] !== 'R200') {
// handle failure; $response['msg'] carries the reason
}
Possible output values of $response['status_code']
(also listed in Status codes, errors):
| Code | Explanation |
|---|---|
R001 | User name not found |
R002 | Bad password |
R003 | User is inactive |
R004 | No cars found |
R005 | No sold items |
R006 | Bad date format - from |
R007 | Bad date format - to |
R008 | Too many connections |
R009 | Empty user name |
R010 | Empty user password |
R011 | Empty user token |
R012 | Wrong user token |
R013 | Wrong IP address |
R200 | OK |
R202 | OK with a warning |
R400 | Bad data |
R404 | Not found |
R500 | System error |
To send multiple values, repeat the key with []:
photos[]=https://example.com/img1.jpg photos[]=https://example.com/img2.jpg
Requests take integers. Responses return them as strings — "id": "242",
"price": "12.22", "car_years": "2007". Parse accordingly and do not
assume symmetry between what you send and what you get back.
Empty timestamps are returned as the MySQL zero date "0000-00-00 00:00:00", not as
null. This crashes strict date parsers in most languages — handle it explicitly.
Optional fields may be null, "", or "0" depending on the
field, with no discernible rule. Treat all three as absent.
IMPORTANT! Every single endpoint in this API requires 3 mandatory fields:
'username' => 'your_username', 'password' => 'your_password', 'user_token' => 'your_token',
Before building anything, confirm your credentials work. /get/car_brands is a good
probe: it needs nothing but authentication.
Example PHP / cURL Request
$post = [
'username' => 'your_username',
'password' => 'your_password',
'user_token' => 'your_token',
];
$ch = curl_init('https://api.rrr.lt/get/car_brands');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
// Expect: ['list' => [['id' => '120', 'name' => 'AC'], ...], 'msg' => 'OK', 'status_code' => 'R200']
If status_code is R200, you're connected. If not, check that you sent
form data rather than JSON — that's the most common first failure.
Ovoko publishes an OpenAPI 3.0 spec, so you can generate a client:
openapi-generator generate \ -i https://api.rrr.lt/openapi/swagger.yaml \ -g php \ -o /path/for/client \ --enable-post-process-file \ --global-property skipFormModel=false
WARNING: The skipFormModel=false override is mandatory — the
generated client will not work without it.
The end-to-end path from nothing to a part visible on the marketplace.
This is the real work of the integration, and it is worth doing before you write any request code. Ovoko identifies almost everything by internal integer ID, so you need a mapping from your system's concepts to theirs.
WARNING: The more time you invest here, the better sales results you will get. Ovoko buyers need to find your parts and this is very important.
Field Mapping Reference
| Your concept | Ovoko field | Where the IDs come from |
|---|---|---|
| Part type | category_id |
/get/categories — level 3 only |
| Vehicle model | car_model |
/get/car_models/{brand_id},
brands from /get/car_brands |
| Fuel type | car_fuel |
/get/fuel |
| Engine size | car_engine_cubic_capacity |
free integer |
| Engine power | car_engine_power |
free integer, kW not hp |
Category Constraints
Two things to know about categories. Only third-level categories can be assigned to a part — the
response includes level and parent_id, so filter on
level == 3. And certain categories require additional fields beyond the standard
set; the dependency matrix is published as a
spreadsheet.
See "Sources for car/part main attributes" in the
Introduction
section.
NOTE: The enumeration endpoints return labels in eight languages: en,
lv, ru, lt, pl, es,
fr, it.
Endpoint
POST https://api.rrr.lt/crm/importCar (reference)
Parameters
Required beyond the three credentials:
| Field | Type | Notes |
|---|---|---|
car_model |
integer | From /get/car_models/{brand_id} |
car_years |
string | e.g. 2012 |
status |
integer | From /get/car_status. Use 6 (Added) unless you have a reason otherwise |
Photos! Parts sell better when photos of the donor car are present so make sure you add them, even though they are not mandatory.
Worth setting even though optional: car_fuel,
car_engine_cubic_capacity, car_engine_power,
car_body_type, car_class, car_gearbox_type,
car_mileage, car_color, car_body_number. Buyers filter on
these, and some are mandatory for particular part categories.
Response
{"car_id": 292, "msg": "OK", "status_code": "R200"}
Aborted responses have the same structure.
Store car_id. You need it for every part on this vehicle.
Making Car Import Idempotent
Two fields let you avoid duplicate cars on retry:
external_id (string) — your own identifier. If a car with this
external_id already exists, the import is aborted. This is the one to use.
id_bridge (integer) — the older
equivalent. If a car with this id_bridge exists, the import is aborted and the
existing car ID is returned. external_id overrides it.
NOTE: Use external_id. id_bridge is explicitly deprecated on
the part and car endpoints.
Endpoint
POST https://api.rrr.lt/crm/importPart (reference)
Parameters
Required beyond credentials:
| Field | Type | Notes |
|---|---|---|
category_id |
integer | Level 3 only |
car_id |
integer | From Step 1. The car must exist |
quality |
integer | From /get/part_quality. Use 0 (Used) for used parts |
status |
integer | From /get/part_status. Use 0 to appear on the marketplace |
Marketplace Visibility Requirements
To actually appear in the shop, you also need:
price greater than 0.00
WARNING: Both are optional at the schema level, so a part can import successfully with
R200 and still be invisible to buyers. This is the most common "it worked but
nothing happened" case.
Response
{"part_id": 288651, "msg": "OK", "status_code": "R200"}
Photos are supplied as URLs that Ovoko fetches — raw image upload is not supported.
Rules
.jpg, .jpeg, or .pngphotos[] arrayphotos[] repeated for the full galleryphoto must also be the first value of photos[]
— this is required for the main photo and thumbnail to generate correctly. This only applies
if you use photos[] AND photo in the same request.
photo=https://cdn.example.com/part1-main.jpg photos[]=https://cdn.example.com/part1-main.jpg photos[]=https://cdn.example.com/part1-side.jpg photos[]=https://cdn.example.com/part1-rear.jpg
There is a /crm/deletePartPhotos endpoint that removes all photos from a part. There
is no documented way to remove a single photo — re-import the full gallery instead.
Several code fields accept free text but are silently cleaned: manufacturer_code,
visible_code, other_code, and the optional_codes[] array
are all documented as "incorrect code will be truncated." Values that fail Ovoko's format
expectations are shortened rather than rejected, and the request still returns R200.
NOTE: Read the part back after import if code accuracy matters to you.
| Action | Endpoint |
|---|---|
| Update part | /crm/updatePart (requires part_id) |
| Change status only | /crm/changePartStatus (part_id, status 0–9) |
| Delete part | /crm/deletePart |
| Remove all photos | /crm/deletePartPhotos |
| Update car | /crm/updateCar (requires car_id) |
| Delete car | /crm/deleteCar |
| Remove all car photos | /crm/deleteCarPhotos |
Important: Part and/or Status can not be updated if
NOTE: /crm/changePartStatus accepts status values 0–9, a wider range than
/get/part_status may return. Fetch the list rather than hardcoding.
Parts that are tyres or rims use a dedicated set of fields — tires,
rims (both 0/1 flags), plus tires_width, tires_height,
tires_tread_depth, tires_quantity, rims_spacing,
rims_fixing_points, rims_central_diameter, rims_quantity.
WARNING: The dimension fields are not measurements: they are IDs into
enumeration lists (/get/wheels_width, /get/wheels_height, and so
on). A tires_width of 1 is the first entry in that list, not one
millimetre.
The field for a right-hand-drive part is named english — set it to 1.
The naming is historical.
The fulfillment lifecycle, from order ingestion to dispatch.
[ Primary: Webhook ] [ Fallback: Polling ]
order.created event OR POST /v2/get/orders/{from}/{to}
│ │
└───────────────────┬──────────────────┘
│
▼
Fetch full order details
POST /v2/get/order/{id}
│
▼
Upload your invoice
POST /crm/importInvoice
│
▼
Submit package dimensions (advances status)
POST /crm/importPostData
│
▼
Generate shipping label
POST /get/print_shipping_label/{id}
│
▼
Request courier (Ovoko web UI)
│
▼
Status becomes "Sent" (Automatic setting)
When integrating your application (such as a DMS or ERP) with Ovoko, you must decide how your system receives new orders and status updates. The recommended architecture uses event-driven webhooks as the primary synchronization mechanism, backed by scheduled polling as a fallback strategy for restricted environments.
order.created or order.cancelled). This approach guarantees
immediate order ingestion and real-time inventory adjustments across all your connected sales
channels.
POST https://api.rrr.lt/v2/get/orders/{date_from}/{date_to} using date parameters
formatted as YYYY-MM-DD (e.g., 2026-08-06).
Because bulk polling retrieves all orders created within the specified date range, your
integration must perform an idempotency check against your local database using
order_id to prevent creating duplicate sales records.
NOTE: Always use /v2/get/orders/{date_from}/{date_to} for polling. The
legacy V1 endpoint (/get/orders/...) is deprecated and does not support
multi-currency pricing, order statuses, tax breakdown objects, or payment method details.
Ovoko uses HTTPS to send webhook notifications to your application as JSON payloads. Webhook
payloads carry lightweight identifiers (order_id or part_id) rather
than full order objects, acting as an asynchronous signal to trigger a subsequent API lookup for
complete data. See also Webhooks introduction
and Events.
Webhook Setup & Authorization
X-Ovoko-Webhook-Token: your_secret_token) in your backend.
2xx response code prior to executing heavy background logic to prevent request
timeouts.
Retry Policy
If your server fails to return a 2xx status code or times out, Ovoko automatically
retries delivery up to 3 times with backoff intervals of 7 seconds, 35 seconds,
and 175 seconds.
Order Event Catalog
POST /v2/get/order/{order_id} and create the order in your system.
{
"event_id": "101aa6a1-ed22-42f0-84ca-1f8a028a2d28",
"event_type": "order.created",
"timestamp": "2026-08-06T07:06:37+02:00",
"event_data": {
"order_id": "9072389"
}
}
{
"event_id": "101aa6a1-ed22-42f0-84ca-1f8a028a2d28",
"event_type": "order.cancelled",
"timestamp": "2026-08-06T08:12:00+02:00",
"event_data": {
"order_id": "9072389"
}
}
DELIVERED.
{
"event_id": "101aa6a1-ed22-42f0-84ca-1f8a028a2d28",
"event_type": "order.delivered",
"timestamp": "2026-08-08T11:45:10+02:00",
"event_data": {
"order_id": "9072389"
}
}
PREPARED status,
indicating that shipment preparation has been completed.
{
"event_id": "101aa6a1-ed22-42f0-84ca-1f8a028a2d28",
"event_type": "order.prepared",
"timestamp": "2026-08-06T09:30:00+02:00",
"event_data": {
"order_id": "9072389"
}
}
SENT status after it has
been handed over for delivery.
{
"event_id": "101aa6a1-ed22-42f0-84ca-1f8a028a2d28",
"event_type": "order.sent",
"timestamp": "2026-08-06T15:45:00+02:00",
"event_data": {
"order_id": "9072389"
}
}
Role of part.status.changed
The part.status.changed event tracks individual inventory states
(in_warehouse, reserved, sold, returned,
written_off, unknown_stock_status). While legacy integrations
previously used part.status.changed (with status "sold") as an order
entry signal, it should now be treated strictly as an inventory availability update across sales
channels rather than the primary order processing trigger.
Order sources and identifiers
Orders can originate from various sales channels, including, but not limited to, Ovoko,
Allegro, eBay, and offline sales. Use order_source to identify the sales channel;
do not infer it from the ID format. Treat order_id as a string throughout your
integration, including database storage, webhook processing, and API requests. For example,
Ovoko IDs typically contain only digits, Allegro IDs are commonly UUID-style strings, eBay IDs
may contain hyphens, and newly created offline orders use UUIDs. These examples are illustrative
and must not be used as validation rules. Always preserve the complete order_id
exactly as returned: do not convert it to an integer, remove punctuation, or require a
particular format.
WARNING: Webhook definitions are currently omitted from the official OpenAPI (Swagger)
specification file. Always treat incoming webhooks as signals to trigger a subsequent API
query (POST /v2/get/order/{order_id}) before executing financial or fulfillment
state changes. Note also that part.status.changed carries id_bridge
(deprecated) alongside external_id.
To retrieve complete details for an individual purchase or poll orders in bulk, use the V2 Order
endpoints. All retrieval calls are sent as POST requests with
application/x-www-form-urlencoded form data.
Endpoints
POST https://api.rrr.lt/v2/get/order/{order_id}
(reference)
POST https://api.rrr.lt/v2/get/orders/{date_from}/{date_to}
(reference)
Request Parameters
Requests require authentication credentials submitted within the form body:
| Parameter | Type | Required | Description |
|---|---|---|---|
username | string | Yes | Account username |
password | string | Yes | Account password |
user_token | string | Yes | User API authorization token |
Date Format for Bulk Retrieval: On /v2/get/orders/{date_from}/{date_to},
date parameters in the URL path must be formatted as YYYY-MM-DD (e.g.,
/v2/get/orders/2026-08-01/2026-08-06).
Example PHP / cURL Request
$post = [
'username' => 'your_username',
'password' => 'your_password',
'user_token' => 'your_user_token',
];
$orderId = '9072389';
$ch = curl_init("https://api.rrr.lt/v2/get/order/{$orderId}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
if ($response['status_code'] === 'R200') {
$orderData = $response['list'];
// Process order record
}
CRITICAL — Deprecated V1 Endpoints: Do not use legacy V1 order endpoints
(/get/order/{id} or /get/orders/{from}/{to}). V1 endpoints are
deprecated and do not support multi-currency amounts (returning a single flat price integer
and currency field, which produces incorrect accounting on cross-border orders). Furthermore,
V1 responses lack order_status, payment_method,
invoice_number, company/VAT details, and VIES validation objects.
Response Structure & Key Fields
Both single and bulk V2 endpoints wrap records inside a flat list array under
$r['list']:
{
"list": [
{
"order_id": "9072389",
"order_source": "ovoko",
"client_name": "Ovoko UAB",
"client_address": "Panerių gatvė 43, Vilnius, LT-03202",
"client_address_street": "Panerių gatvė 43",
"client_address_city": "Vilnius",
"client_address_country": "LT",
"client_address_zip_code": "03202",
"client_phone": "+37064762911",
"client_email": "[email protected]",
"company_code": "304401253",
"company_vat_code": "LT100010771516",
"company_title": "Ovoko UAB",
"company_phone": "+37064762911",
"company_address": "Paneriu str. 43, LT-03202 Vilnius",
"item_list": [
{
"id": "209608",
"id_bridge": "P23900830",
"car_id": "58978",
"name": "Engine splash shield/under tray",
"sell_price": {
"seller": { "amount": "3.31", "currency": "EUR" },
"buyer": { "amount": "3.31", "currency": "EUR" }
},
"external_id": "P23900830",
"delivery_type": "courier",
"shipping_provider": "schenker"
}
],
"part_total_price": {
"seller": { "amount": "3.31", "currency": "EUR" },
"buyer": { "amount": "3.31", "currency": "EUR" }
},
"order_date": "2026-08-06 07:06:37",
"payment_type": "RRR",
"seller": null,
"shipping_price": {
"seller": { "amount": "70.74", "currency": "EUR" },
"buyer": { "amount": "70.74", "currency": "EUR" }
},
"total_price": {
"seller": { "amount": "74.05", "currency": "EUR" },
"buyer": { "amount": "74.05", "currency": "EUR" }
},
"payment_method": "credit",
"order_status": "PREPARED",
"invoice_number": null,
"invoice_download_url": null,
"vies_vat_check_result": {
"status": "valid",
"name": "UAB \"Ovoko\"",
"vat_number": "LT100010771516",
"vat_country": "LT",
"address": "Panerių g. 43, Vilniaus m., Vilniaus m. sav.",
"source": "vies"
},
"vat_amount": { "amount": "0.00", "type": "%" },
"view_order": "https://yourdomain.rrr.lt/order/view_order/9072389"
}
],
"msg": "OK",
"status_code": "R200"
}
Field Mapping Reference
client_name, client_address,
client_phone, client_email supply purchaser contact details.
company_code, company_vat_code,
company_title, company_address populate when an order is placed on
behalf of a business entity.
id (part
ID), car_id, name, external_id,
delivery_type, shipping_provider, and dual-currency
sell_price.
"PREPARED",
"CANCELLED").
NEW PREPARED SENT CANCELED
Every monetary value in a V2 order response is represented as a structured JSON object
containing two distinct currency representations: seller and buyer.
"total_price": {
"seller": { "amount": "74.05", "currency": "EUR" },
"buyer": { "amount": "320.50", "currency": "PLN" }
}
Accounting Rule: Always Book Against seller
WARNING — Accounting Integrity: Always record financial totals and line items in
your local DMS/ERP using the seller object. Using buyer amounts for internal
accounting or invoice calculation will introduce currency exchange errors on every
international transaction.
The dual-currency object pattern applies to all financial fields:
sell_price (per-item price in item_list)part_total_price (subtotal of all parts in the order)shipping_price (logistics freight charge)total_price (grand total for the order)VAT Handling (vat_amount)
The vat_amount field breaks the dual-currency pattern. It returns a flat
{ "amount": "...", "type": "%" } object:
"vat_amount": {
"amount": "21.00",
"type": "%"
}
"21.00" with type: "%"
indicates a 21% VAT rate. A value of "0.00" indicates a zero-rated or
reverse-charge transaction.
Automated VIES VAT Validation (vies_vat_check_result)
For cross-border business purchases within the EU, Ovoko automatically queries the VIES system
to validate buyer tax credentials. When applicable, vies_vat_check_result provides
verification details:
"vies_vat_check_result": {
"status": "valid",
"name": "UAB \"Ovoko\"",
"vat_number": "LT100010771516",
"vat_country": "LT",
"address": "Panerių g. 43, Vilniaus m., Vilniaus m. sav.",
"source": "vies"
}
If the transaction is a consumer sale or VIES validation is not applicable,
vies_vat_check_result returns null.
POST /crm/importInvoice)Once an order has been created in your internal system (DMS/ERP), you must generate and upload your official sales invoice PDF to Ovoko. This attaches your accounting document to the marketplace transaction record and allows the buyer to download it.
Endpoint
POST https://api.rrr.lt/crm/importInvoice (reference)
Request Format
This endpoint requires multipart/form-data encoding to handle the binary PDF file upload.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
username | string | Yes | Account username |
password | string | Yes | Account password |
user_token | string | Yes | User API authorization token |
order_id | string / integer | Yes* | The Ovoko Order ID (*required for sales invoices) |
refund_id | string / integer | Conditional | The Ovoko Refund ID (*required if uploading a credit note/refund invoice) |
invoice_number | string | Yes | Your internal invoice document number (e.g., INV-2026-00123) |
is_credit_invoice | integer | Yes | 0 for standard debit sales invoices; 1 for credit notes / refund invoices |
file | binary file | Yes | The generated invoice document in PDF format |
NOTE: Uploading an invoice attaches the PDF to the order record on Ovoko and populates
the invoice_number and invoice_download_url fields visible in
subsequent POST /v2/get/order/{order_id} API responses.
Example PHP / cURL Upload
$postData = [
'username' => 'your_username',
'password' => 'your_password',
'user_token' => 'your_user_token',
'order_id' => '9072389',
'invoice_number' => 'INV-2026-08912',
'is_credit_invoice' => 0,
'file' => new CURLFile('/path/to/invoices/INV-2026-08912.pdf', 'application/pdf', 'INV-2026-08912.pdf')
];
$ch = curl_init('https://api.rrr.lt/crm/importInvoice');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
POST /crm/importPostData)After packing the ordered parts, you must submit parcel dimensions and total weight to Ovoko.
Endpoint
POST https://api.rrr.lt/crm/importPostData (reference)
State Transition Effect
Submitting valid parcel post data serves as an explicit fulfillment milestone in Ovoko: executing this call automatically advances the order's order_status to "PREPARED" ("Shipment prepared").
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
username | string | Yes | Account username |
password | string | Yes | Account password |
user_token | string | Yes | User API authorization token |
order_id | string / integer | Yes | Ovoko Order ID |
weight | numeric | Yes | Total package weight in kilograms (e.g., 12.5) |
height | numeric | Yes | Package height in centimeters (e.g., 30) |
length | numeric | Yes | Package length in centimeters (e.g., 40) |
width | numeric | Yes | Package width in centimeters (e.g., 25) |
packing_type | string | Optional | Packaging type descriptor (e.g., box, pallet) |
WARNING: Ensure package weight and dimensions are accurate prior to sending. These measurements are submitted directly to logistics providers to compute freight tariffs and generate carrier routing manifests.
POST /get/print_shipping_label/{order_id})
Once package dimensions are recorded and the order status reaches "PREPARED", you
can download the transport shipping label generated by the assigned logistics carrier.
Endpoint
POST https://api.rrr.lt/get/print_shipping_label/{order_id} (reference)
Parameters
| Parameter | Location | Type | Required | Description |
|---|---|---|---|---|
{order_id} | URI Path | integer | Yes | Ovoko Order ID in path |
username | Body | string | Yes | Account username |
password | Body | string | Yes | Account password |
user_token | Body | string | Yes | User API authorization token |
label_type | Query / Body | string | Optional | Desired label output format: pdf (default) or zpl (for thermal label printers) |
Handling Binary Response
Unlike most Ovoko API endpoints that return JSON envelopes, this endpoint streams raw binary document data (a PDF document or ZPL printer code stream).
$postData = [
'username' => 'your_username',
'password' => 'your_password',
'user_token' => 'your_user_token'
];
$orderId = '9072389';
$ch = curl_init("https://api.rrr.lt/get/print_shipping_label/{$orderId}?label_type=pdf");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
$binaryLabel = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $binaryLabel) {
file_put_contents("/tmp/shipping_label_{$orderId}.pdf", $binaryLabel);
}
WARNING: Do not attempt to pass the output of this endpoint through
json_decode(). Save or pipe the raw binary stream directly to your printer
spooler or filesystem.
The final physical step in the order fulfillment flow is requesting carrier pickup and handing over the parcel.
Requesting Courier Handover
Courier booking is handled manually through the Ovoko Scrapyard Web UI:
Automatic Status Transition to "SENT"
When the courier arrives, collects, and scans the physical package parcel label:
order_status from "PREPARED" to
"SENT".
order.delivered webhook event.Synchronize return requests and track their refund status in your application.
Return management through the public API is read-only. You can retrieve returns, returned items, and refund details. Creating or approving returns, resolving disputes, and initiating refunds are handled through the applicable Ovoko workflow. Credit invoice upload is a separate invoice capability, described in §5.5.
[ Primary: Webhook ] [ Fallback: Polling ]
order.return.created OR POST /get/order_returns
order.return.updated
│ │
└──────────────────┬──────────────────┘
│
▼
Fetch full return details
POST /get/order_return/{id}
│
▼
Update your local return record
Track each refund's status
When integrating your application (such as a DMS or ERP) with Ovoko, use return notifications where enabled, backed by scheduled polling to reconcile changes.
order.return.created and
order.return.updated as signals to fetch the latest return details.
POST /get/order_returns): Retrieve returns using a
date range and page number. Use this for reconciliation or when your application cannot
receive webhooks.
Your integration must update existing records rather than create duplicates. Match returns
using their returned id and refunds using refunds[].id, within the
relevant seller account.
NOTE: The list filters by return creation date. Polling only today's returns can miss changes to older records. Re-fetch known returns with pending refunds and periodically reconcile earlier date ranges.
Use the webhook setup and authorization described in the order guide
(§5.2). Return HTTP 2xx promptly and process the notification
asynchronously.
Return Event Catalog
order.return.created: Signals a new return. Fetch its details using event_data.return_id.order.return.updated: Signals a return update. Fetch the record again to synchronize its status, items, and refunds.
{
"event_id": "18d7b24c-6fad-4f83-83a9-8c3efaeab294",
"event_type": "order.return.created",
"timestamp": "2026-09-17T10:00:00Z",
"event_data": {
"return_id": 123,
"order_id": 9072389
}
}
An update uses the same structure with event_type set to
"order.return.updated". Deduplicate notifications using event_id and
retain polling to reconcile missed updates.
All retrieval calls use POST with application/x-www-form-urlencoded authentication data.
Endpoints
POST https://api.rrr.lt/get/order_return/{id}
(reference)
POST https://api.rrr.lt/get/order_returns
(reference)
POST https://api.rrr.lt/get/order_return_status
(reference)
Request Parameters
| Parameter | Location | Type | Required | Description |
|---|---|---|---|---|
username | Body | string | Yes | Account username |
password | Body | string | Yes | Account password |
user_token | Body | string | Yes | User API authorization token |
{id} | URI path | integer | Single return only | Return identifier returned by the API |
date_from | Query | string | No | Start date for list retrieval: YYYY-MM-DD |
date_to | Query | string | No | End date for list retrieval: YYYY-MM-DD |
page | Query | integer | No | List page number, starting at 1 |
Example PHP / cURL Request
$post = [
'username' => 'your_username',
'password' => 'your_password',
'user_token' => 'your_user_token',
];
$returnId = 123;
$ch = curl_init('https://api.rrr.lt/get/order_return/' . rawurlencode((string) $returnId));
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
$body = curl_exec($ch);
if ($body === false) {
throw new RuntimeException(curl_error($ch));
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode < 200 || $httpCode >= 300) {
throw new RuntimeException('Return retrieval failed: HTTP ' . $httpCode);
}
$response = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
if (($response['status_code'] ?? null) !== 'R200') {
throw new RuntimeException($response['msg'] ?? 'Return retrieval failed');
}
$returnData = $response['list'][0][0] ?? null;
// Update your local return record if a record was returned.
For list retrieval, use a URL such as
https://api.rrr.lt/get/order_returns?date_from=2026-09-01&date_to=2026-09-17&page=1,
with the same authentication form body.
Response Structure & Key Fields
| Endpoint | Record access |
|---|---|
/get/order_return/{id} | $response['list'][0][0] — single return |
/get/order_returns | Iterate $response['list'] — list of returns |
Field Mapping Reference
id: Return identifier. Preserve the value returned by the API; do not construct it from the order ID.status: Return workflow status. Available values can be retrieved using /get/order_return_status.order_return_items: Returned parts, with their order_id, part_id, return reason, amounts, and VAT rate.customer: Customer contact and return-address details, where available.refunds: Separate refund records, each with its own id,
status, amounts, and payment timestamp. This list may be empty or contain
multiple refunds.
Return, order, part, and refund IDs identify different records. Use the return
id to retrieve a return and refunds[].id when referring to a specific
refund.
Returns use currency and seller_currency, with separate amounts for each currency.
{
"currency": "EUR",
"seller_currency": "PLN",
"total_returnable_amount": 55.00,
"total_returnable_amount_in_seller_currency": 233.75
}
currency: Currency for amounts without the _in_seller_currency suffix.seller_currency: Currency for amounts ending in _in_seller_currency. Use these for seller-currency accounting.vat_rate: Item-level VAT percentage; for example, 21 means 21% VAT.
Use the supplied amounts rather than calculating a new exchange rate. A return's
returnable_amount describes the return request; a refund line's
refund_amount describes that refund. Neither field alone confirms payment.
Track each entry in refunds independently, using its id and status.
Refund Status Reference
| Status | Meaning |
|---|---|
NEW | Refund is pending. |
PAID_OUT | Refund is marked as paid out. Reconcile its amount and paid_at. |
REJECTED | Refund is rejected. |
A refund includes total_amount, total_amount_in_seller_currency, and
its individual refund_items. These amounts cover the seller-funded, non-fee refund
lines exposed for your account. A refund line may have part_id: null, for example a
shipping refund.
WARNING: Return status and refund payment status are separate. A return marked
"Returned" does not mean its refund has been paid. Check each refund's
status; paid_at may be null while payment is pending.
When a credit invoice is available, the refund's invoice object contains its number
and download_url. Otherwise, invoice may be null. Invoice
availability does not confirm that a refund has been paid; check the refund's
status separately.
| Endpoint | Purpose | Required (beyond auth) |
|---|---|---|
/crm/importCar | Create car | car_model, car_years, status |
/crm/updateCar | Update car | car_id |
/crm/deleteCar | Delete car | car_id |
/crm/deleteCarPhotos | Remove all car photos | car_id |
/crm/importPart | Create part | category_id, car_id, quality, status |
/crm/updatePart | Update part | part_id |
/crm/deletePart | Delete part | part_id |
/crm/changePartStatus | Change status | part_id, status (0–9) |
/crm/deletePartPhotos | Remove all part photos | part_id |
/crm/importInvoice | Upload invoice (multipart) | invoice_number, is_credit_invoice, file |
/crm/importPostData | Package dimensions | order_id, weight, height, length, width |
| Endpoint | Purpose | Status |
|---|---|---|
/get/car/{id} | Single car | |
/get/cars/{date_from}/{date_to} | Cars by date | |
/v2/get/cars | Cars, paginated + filtered | Preferred |
/get/part/{id} | Single part | |
/get/parts/{date_from}/{date_to} | Parts by date | Deprecated |
/v2/get/parts | Parts, paginated + filtered | Preferred |
/get/order/{id} | Single order | Deprecated |
/get/orders/{date_from}/{date_to} | Orders by date | Deprecated |
/v2/get/order/{id} | Single order, multi-currency | Preferred |
/v2/get/orders/{date_from}/{date_to} | Orders, multi-currency | Preferred |
/v2/get/invoice_list/{date_from}/{date_to} | Invoices | |
/v2/get/invoice-download/{path} | Invoice PDF | |
/get/order_return/{id} | Single return | |
/get/order_returns | Returns, paginated | |
/get/print_shipping_label/{order_id} | Label (binary) | |
/get/logs/{date_from}/{date_to} | Activity log |
All take authentication only.
/get/car_brands, /get/car_models/{brand_id},
/get/car_class, /get/car_status, /get/car_body_type,
/get/color, /get/fuel, /get/gearbox_type,
/get/wheel (steering wheel), /get/wheel_drive
/get/categories, /get/part_status,
/get/part_quality, /get/part_position
/get/wheels_width, /get/wheels_height,
/get/wheels_tread_depth, /get/wheels_spacing,
/get/wheels_fixing_points, /get/wheels_central_diameter
/get/order_return_status
NOTE: The spec labels /get/color as "Get car body type list" — a
copy-paste error. It returns colours.
Three different shapes are in use, and the difference is not signposted:
| Pattern | Endpoints | Access |
|---|---|---|
| Doubly-nested | /get/car/{id}, /get/part/{id}, /get/order_return/{id} |
$r['list'][0][0] |
| Flat list | /get/cars/..., /get/parts/..., /v2/get/order/{id},
/v2/get/orders/..., /get/order_returns, /get/logs, invoice list |
$r['list'][0] |
| Paginated | /v2/get/cars, /v2/get/parts |
$r['data'][0] plus $r['pagination'] |
WARNING: Note in particular that /get/car/{id} is doubly nested while
/v2/get/order/{id} is not, despite both returning a single record. And the V2
list endpoints use data, not list.
/v2/get/cars and /v2/get/parts accept as query parameters:
date_from, date_to, user_ids, model_ids
(cars), car_ids (cars), external_ids, page,
limit (1–100), search, and sort
(?sort[id]=desc&sort[date]=asc, supporting id and
date).
On parts, search matches against name and manufacturer_code.
Important: The spec declares the pagination object as nested
pagination.pagination.page. The right response is pagination.page.