Integration Guide

Applies to: the RRR/Ovoko API at https://api.rrr.lt   Companion to: the endpoint reference in this documentation   Support: [email protected]

How to Read This

Integrating for the first time? Read §1–§3, then follow §4 or §5 depending on what you're building. Most integrations need both.

Already integrated and looking something up? §6 and §7 stand alone; §7 is the full endpoint reference.

Contents

  1. What This API Is
  2. Core Request Rules
  3. Getting Your First Successful Call
  4. Guide: Listing Parts for Sale
  5. Guide: Handling an Order
  6. Guide: Handling Returns and Refunds
  7. Endpoint Reference

1. What This API Is

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.

Request Categories

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.

2. Core Request Rules

These apply to every endpoint. They are unusual enough that skipping this section will cost you an afternoon.

2.1 Everything Is POST, Including Reads

There are no GET endpoints. Retrieving a car is a POST. This includes all of CRM Export and CRM Info.

2.2 Form Data, Never JSON

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.

2.3 Three Credentials on Every Single Request

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.

2.4 API HTTP Status Codes and Error Handling

There are 2 layers in handling errors:

  1. Infrastructure and/or Ovoko services related issues:
    • These are actually handled via HTTP status codes and address issues/status of Ovoko services health ($httpCode)
  2. Application-level/validation errors:
    • These come in the $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
}

Status Code Reference

Possible output values of $response['status_code'] (also listed in Status codes, errors):

Code Explanation
R001User name not found
R002Bad password
R003User is inactive
R004No cars found
R005No sold items
R006Bad date format - from
R007Bad date format - to
R008Too many connections
R009Empty user name
R010Empty user password
R011Empty user token
R012Wrong user token
R013Wrong IP address
R200OK
R202OK with a warning
R400Bad data
R404Not found
R500System error

2.5 Arrays Use Bracket-Suffixed Repeated Keys

To send multiple values, repeat the key with []:

photos[]=https://example.com/img1.jpg
photos[]=https://example.com/img2.jpg

2.6 Numbers Come Back as Strings

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.

2.7 Two Date Traps in Responses

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.

3. Getting Your First Successful Call

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.

Generating a Client

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.

4. Guide: Listing Parts for Sale

The end-to-end path from nothing to a part visible on the marketplace.

Step 0 — Map Your Fields First

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.

Step 1 — Import the Car

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.
  • Existing Integrations only (deprecated): 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.

Step 2 — Import the Part

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
  • at least one photo

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"}

Step 3 — Photos

Photos are supplied as URLs that Ovoko fetches — raw image upload is not supported.

Rules

  • The URL must end in a real extension: .jpg, .jpeg, or .png
  • Thumbnails use the first element in the photos[] array
  • Use photos[] repeated for the full gallery
  • The value of photo 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.

Step 4 — Identifier and Code Fields

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.

Step 5 — Ongoing Maintenance

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

  • status = SOLD (status code 2) and there is an order attached to the part. (except if part was returned)
  • status = WRITTEN_OFF (status code 4) + order cancellation reason = PART_OUT_OF_STOCK

NOTE: /crm/changePartStatus accepts status values 0–9, a wider range than /get/part_status may return. Fetch the list rather than hardcoding.

Tyres and Rims

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.

Right-Hand Drive

The field for a right-hand-drive part is named english — set it to 1. The naming is historical.

5. Guide: Handling an Order

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)

5.1 Order Synchronization Strategy: Webhooks vs Polling

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.

  • Primary Strategy — Webhook Notifications (Event-Driven): Ovoko sends real-time HTTP POST notifications to your server whenever an order event occurs (such as order.created or order.cancelled). This approach guarantees immediate order ingestion and real-time inventory adjustments across all your connected sales channels.
  • Fallback Strategy — Periodic List Polling (POST /v2/get/orders/{date_from}/{date_to}): For systems unable to expose a public HTTPS endpoint, operating behind strict network firewalls, or requiring a periodic reconciliation job, order list polling must be implemented. Integrations call 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.

5.2 Webhook Setup and Order Events

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

  1. Create an Endpoint: Set up a publicly accessible HTTPS POST endpoint on your server capable of receiving JSON payloads.
  2. Configure Custom Header Security: Implement custom header authorization to verify payload authenticity. Define a secret header token (e.g., X-Ovoko-Webhook-Token: your_secret_token) in your backend.
  3. Register in Scrapyard UI: Register your callback URL and custom authorization headers in your Scrapyard account under Settings > Integrations > API.
  4. Return HTTP 2xx Promptly: Your endpoint must quickly return a successful HTTP 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

  • order.created: Fired when a buyer places a new purchase order on the marketplace. This is the primary trigger to fetch full order details using 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"
  }
}
  • order.cancelled: Fired when an order is cancelled prior to dispatch.
{
  "event_id": "101aa6a1-ed22-42f0-84ca-1f8a028a2d28",
  "event_type": "order.cancelled",
  "timestamp": "2026-08-06T08:12:00+02:00",
  "event_data": {
    "order_id": "9072389"
  }
}
  • order.delivered: Fired when the logistics carrier marks the package status as 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"
  }
}
  • order.prepared: Fired when an order advances to the 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"
  }
}
  • order.sent: Fired when an order advances to the 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.

5.3 Retrieving Order Details

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

  • Single Order Retrieval: POST https://api.rrr.lt/v2/get/order/{order_id} (reference)
  • Bulk Order Retrieval (Polling): 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
usernamestringYesAccount username
passwordstringYesAccount password
user_tokenstringYesUser 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

  • Customer Identification: client_name, client_address, client_phone, client_email supply purchaser contact details.
  • Corporate & Tax Data: company_code, company_vat_code, company_title, company_address populate when an order is placed on behalf of a business entity.
  • item_list Array: Contains individual purchased parts including id (part ID), car_id, name, external_id, delivery_type, shipping_provider, and dual-currency sell_price.
  • order_status: Reflects fulfillment status (e.g., "PREPARED", "CANCELLED").
    • Possible values: NEW PREPARED SENT CANCELED
  • invoice_download_url: Direct download link to generated debit invoice files when available.

5.4 The Dual-Currency Price Model

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

  • seller: Represents the net monetary amount credited to your account, expressed in your account's base settlement currency (e.g., EUR or PLN).
  • buyer: Represents the total amount paid by the customer in their local store currency.

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:

  1. sell_price (per-item price in item_list)
  2. part_total_price (subtotal of all parts in the order)
  3. shipping_price (logistics freight charge)
  4. 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": "%"
}
  • amount: Represents the tax rate percentage applied to the sale, not a calculated currency sum. For example, "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.

5.5 Uploading Your Invoice (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
usernamestringYesAccount username
passwordstringYesAccount password
user_tokenstringYesUser API authorization token
order_idstring / integerYes* The Ovoko Order ID (*required for sales invoices)
refund_idstring / integerConditional The Ovoko Refund ID (*required if uploading a credit note/refund invoice)
invoice_numberstringYes Your internal invoice document number (e.g., INV-2026-00123)
is_credit_invoiceintegerYes 0 for standard debit sales invoices; 1 for credit notes / refund invoices
filebinary fileYes 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);

5.6 Submitting Package Dimensions & Status Advancement (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
usernamestringYesAccount username
passwordstringYesAccount password
user_tokenstringYesUser API authorization token
order_idstring / integerYesOvoko Order ID
weightnumericYesTotal package weight in kilograms (e.g., 12.5)
heightnumericYesPackage height in centimeters (e.g., 30)
lengthnumericYesPackage length in centimeters (e.g., 40)
widthnumericYesPackage width in centimeters (e.g., 25)
packing_typestringOptionalPackaging 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.

5.7 Generating Shipping Labels (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 PathintegerYesOvoko Order ID in path
usernameBodystringYesAccount username
passwordBodystringYesAccount password
user_tokenBodystringYesUser API authorization token
label_typeQuery / BodystringOptional 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.

5.8 Courier Request & Dispatch

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:

  1. Navigate to Orders → Awaiting dispatch.
  2. Select the prepared order(s).
  3. Click Request courier.

Automatic Status Transition to "SENT"

When the courier arrives, collects, and scans the physical package parcel label:

  • If the setting "Use Automatic Order Status Change" is enabled in your Scrapyard account settings, Ovoko receives real-time tracking scan updates from the logistics provider and automatically shifts the order_status from "PREPARED" to "SENT".
  • Once delivered to the buyer, Ovoko emits an order.delivered webhook event.

6. Guide: Handling Returns and Refunds

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

6.1 Return Synchronization Strategy: Webhooks vs Polling

When integrating your application (such as a DMS or ERP) with Ovoko, use return notifications where enabled, backed by scheduled polling to reconcile changes.

  • Webhook Notifications (Event-Driven): Use order.return.created and order.return.updated as signals to fetch the latest return details.
  • Scheduled List Polling (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.

6.2 Return Events

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.

6.3 Retrieving Return Details

All retrieval calls use POST with application/x-www-form-urlencoded authentication data.

Endpoints

  • Single Return Retrieval: POST https://api.rrr.lt/get/order_return/{id} (reference)
  • Bulk Return Retrieval (Polling): POST https://api.rrr.lt/get/order_returns (reference)
  • Return Status Reference: POST https://api.rrr.lt/get/order_return_status (reference)

Request Parameters

Parameter Location Type Required Description
usernameBodystringYesAccount username
passwordBodystringYesAccount password
user_tokenBodystringYesUser API authorization token
{id}URI pathintegerSingle return onlyReturn identifier returned by the API
date_fromQuerystringNoStart date for list retrieval: YYYY-MM-DD
date_toQuerystringNoEnd date for list retrieval: YYYY-MM-DD
pageQueryintegerNoList 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_returnsIterate $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.

6.4 Return and Refund Currency Model

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.

6.5 Tracking Refunds

Track each entry in refunds independently, using its id and status.

Refund Status Reference

Status Meaning
NEWRefund is pending.
PAID_OUTRefund is marked as paid out. Reconcile its amount and paid_at.
REJECTEDRefund 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.

6.6 Credit Invoice Availability

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.

7. Endpoint Reference

7.1 CRM Import

Endpoint Purpose Required (beyond auth)
/crm/importCarCreate carcar_model, car_years, status
/crm/updateCarUpdate carcar_id
/crm/deleteCarDelete carcar_id
/crm/deleteCarPhotosRemove all car photoscar_id
/crm/importPartCreate partcategory_id, car_id, quality, status
/crm/updatePartUpdate partpart_id
/crm/deletePartDelete partpart_id
/crm/changePartStatusChange statuspart_id, status (0–9)
/crm/deletePartPhotosRemove all part photospart_id
/crm/importInvoiceUpload invoice (multipart)invoice_number, is_credit_invoice, file
/crm/importPostDataPackage dimensionsorder_id, weight, height, length, width

7.2 CRM Export

Endpoint Purpose Status
/get/car/{id}Single car
/get/cars/{date_from}/{date_to}Cars by date
/v2/get/carsCars, paginated + filteredPreferred
/get/part/{id}Single part
/get/parts/{date_from}/{date_to}Parts by dateDeprecated
/v2/get/partsParts, paginated + filteredPreferred
/get/order/{id}Single orderDeprecated
/get/orders/{date_from}/{date_to}Orders by dateDeprecated
/v2/get/order/{id}Single order, multi-currencyPreferred
/v2/get/orders/{date_from}/{date_to}Orders, multi-currencyPreferred
/v2/get/invoice_list/{date_from}/{date_to}Invoices
/v2/get/invoice-download/{path}Invoice PDF
/get/order_return/{id}Single return
/get/order_returnsReturns, paginated
/get/print_shipping_label/{order_id}Label (binary)
/get/logs/{date_from}/{date_to}Activity log

7.3 CRM Info

All take authentication only.

  • Vehicle: /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
  • Part: /get/categories, /get/part_status, /get/part_quality, /get/part_position
  • Tyres and rims: /get/wheels_width, /get/wheels_height, /get/wheels_tread_depth, /get/wheels_spacing, /get/wheels_fixing_points, /get/wheels_central_diameter
  • Returns: /get/order_return_status

NOTE: The spec labels /get/color as "Get car body type list" — a copy-paste error. It returns colours.

7.4 Response Envelope Shapes — A Real Trap

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.

7.5 V2 List Filtering

/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.