Adding Orders to BOCP
The full connector integration flow: publish products to the connector, read the published product list, send orders using those product codes, and receive real-time webhook notifications when invoices and AWBs are issued.
Integration flow
Once the connector exists (see Setup), the integration follows four steps:
- Publish products to the connector — done in BOCP by your team; it decides which products the connector may see.
- Read the published products — pull the catalog to get product codes, prices, and stock.
- Send orders — POST orders using those product codes (and PUT to update them).
- Receive notifications — BOCP pushes status, invoice, and AWB events back to your URL.
Setup
Each integration requires its own connector. A connector is a named slot in the BOCP eCommerce module that holds the type, credentials, and settings for one external platform.
1. Verify you have a free connector slot
Connector slots are part of your BOCP license. The REST API package includes one eCommerce connector; additional connectors are licensed separately. Check your active slots in eCommerce → Connectors before proceeding.
2. Add a new connector in BOCP
In the BOCP back-end go to eCommerce → Connectors → Add new connector. Fill in:
- Name — a label for this connector, e.g. "My Webshop" or "Partner Dropship". Used only for identification inside BOCP.
- Type — choose one of the two connector types (see table below).
Save the connector. BOCP automatically generates a dedicated username and password (API key pair) for it.
3. Connector types
| Type | Invoice goes to | When to use |
|---|---|---|
| BOCP Rest API (eCommerce) | The client supplied in the order payload | Your own webshop — the end customer is invoiced directly. |
| Dropship | The preconfigured dropshipper contact in BOCP | A partner who sells on your behalf — you are invoiced, not their end customer. |
4. Collect your credentials
After saving, the connector detail page shows:
connector_id— the numeric ID in the URL; used in every API request.- Username & password — the generated API key pair, scoped exclusively to this connector. One connector = one key pair; the credentials cannot access any other connector or endpoint outside the order flow.
- Base URL — your account endpoint, e.g.
https://secure.bocp.eu/app/rest/v1/{company_id}/.
product item you send must use a code that exists in the BOCP product catalog. You obtain these codes in Step 2 by reading the product list — orders with unknown codes are rejected with 400.
You also provide a notification URL on your server and enter it in the connector settings — BOCP will POST event notifications there whenever the order status changes, an invoice is issued, or an AWB is generated.
5. Read the connector configuration (optional but recommended)
Before wiring up the flow, pull the connector's configuration so your integration knows what to expect — which automations BOCP will run on the orders you send (sale issue, invoicing, proforma, AWB), how products sync in both directions, and the event → status mapping used for notifications:
GET https://secure.bocp.eu/app/rest/v1/{company_id}/connector/{connector_id}/config/
Authorization: Basic <base64(username:password)>
The response groups the settings under connector, products (auto-import mode, update options, push feed URL), order_processing (confirmation method, working point, on-import action), invoicing, proforma, awb, and status_sync. Option fields include the full list of possible values, and settings that fall back to an account-wide default carry a source key (connector or global). The call is read-only. See the endpoint reference for the full field list.
Step 1 — Publish products to the connector
A connector can only see products that have been published to it. This is done inside BOCP (not through the API) by your team:
- Go to Product Catalogue, select one or more products, and choose Publish — pick this connector as the destination.
- Publishing simply flags the product for this connector's feed. There is no push — the partner pulls the current list on demand (Step 2).
- Unpublished products are never exposed. Publishing more products later makes them appear in the feed automatically; no code change on your side.
No external category mapping is required — the BOCP category structure travels inside the feed.
Step 2 — Read the published products
Pull the catalog from your connector to get the product code, price, and stock of every published item. Poll it to keep your local catalog in sync.
/product/list/ endpoint, so you can reuse the same parser. Prices and stock reflect the working point configured on the connector.
GET https://secure.bocp.eu/app/rest/v1/{company_id}/connector/{connector_id}/products/
Authorization: Basic <base64(username:password)>
Filters
Filters are appended as key:value path segments (see Conventions), not query strings. The most useful ones:
| Filter | Purpose |
|---|---|
page:n | Page number. Results are paginated; keep requesting the next page while has_more_pages is true. |
format:json|xml|csv | Response format. Defaults to json. |
code:SKU | Return a single product by its code or barcode. |
modifiedafter:YYYY-MM-DD HH:MM:SS | Only products changed after this timestamp — use it for incremental sync. |
include:images,properties | Opt-in extra data: product images and characteristics. |
magazia_id:n | Override the working point used for prices/stock (defaults to the connector's). |
GET https://secure.bocp.eu/app/rest/v1/{company_id}/connector/{connector_id}/products/include:images/page:1/
Response
Standard envelope; data is the array of products for the current page. Trimmed example:
{
"is_error": false,
"page": 1,
"has_more_pages": true,
"data": [
{
"product_id": 4521,
"cod_varianta": "TS-001",
"cod_produs": "ABC123456",
"barcode": "0789876543210",
"product_name": "Product Name",
"category_name": "T-Shirts",
"stoc_global": 37,
"unitate_masura": "buc",
"pret_vanzare": 100.00,
"pret_vanzare_cu_tva": 119.00,
"cota_tva_vanzare": 19,
"selling_currency_txt":"RON",
"website_published": 1,
"producator": "Acme",
"last_changed_ts": "2024-01-01 10:00:00"
}
]
}
Use cod_produs as the code when you build order items. Poll with modifiedafter to keep your local catalog and stock in sync.
Step 3 — Send a new order
When a customer places an order on your platform, POST it to BOCP. The {order_id} in the URL is your own order identifier and must exactly match order_unique_id in the body.
POST https://secure.bocp.eu/app/rest/v1/{company_id}/connector/{connector_id}/order/ABC123456/
Authorization: Basic <base64(username:password)>
Content-Type: application/json
{
"order_unique_id": "ABC123456",
"order_reference": "ABC123456",
"order_date": "2024-01-01",
"order_updated_at": "2024-01-01 10:00:00",
"order_status": "new",
"order_cancelled": 0,
"order_mentions": "Please deliver in the morning",
"order_currency_code": "RON",
"shipping_method": "courier",
"cod_amount": 0,
"cod_currency": "RON",
"client": {
"name": "John Doe",
"representative": "John Doe",
"email": "john@example.com",
"phone": "0722222222",
"vat_id": "",
"registration_number": "",
"client_unique_id": 123456,
"invoice_address": {
"city": "Bucharest",
"county": "Bucharest",
"country": "Romania",
"zip": "123456",
"street": "Street Name",
"number": "1",
"building": "",
"stair": "",
"floor": "",
"apartment": "",
"GLN": ""
},
"delivery_address": {
"city": "Bucharest",
"county": "Bucharest",
"country": "Romania",
"zip": "123456",
"street": "Street Name",
"number": "1",
"building": "",
"stair": "",
"floor": "",
"apartment": "",
"shipping_contact_name": "John Doe",
"shipping_contact_phone": "0722222222",
"GLN": ""
}
},
"items": [
{
"type": "product",
"code": "ABC123456",
"ean": "0789876543210",
"item_name": "Product Name",
"item_quantity": 2,
"item_price": 100.00,
"item_vat_percent": 19,
"item_price_with_vat": 119.00,
"line_value_with_vat": 238.00,
"discounted_price_with_vat": 98.00,
"line_discount_value_with_vat": 4.00
},
{
"type": "discount",
"code": "DISCOUNT",
"item_name": "Promo Code: BONUS10",
"item_quantity": 1,
"item_price": -10.00,
"item_vat_percent": 19,
"item_price_with_vat": -11.90,
"line_value_with_vat": -11.90
},
{
"type": "service",
"code": "SHIPPING",
"item_name": "Shipping via courier",
"item_quantity": 1,
"item_price": 24.00,
"item_vat_percent": 19,
"item_price_with_vat": 28.56,
"line_value_with_vat": 28.56
},
{
"type": "service",
"code": "SERVICE",
"item_name": "Special gift wrap",
"item_quantity": 1,
"item_price": 50.00,
"item_vat_percent": 19,
"item_price_with_vat": 59.50,
"line_value_with_vat": 59.50
}
],
"payments": [
{
"payment_method": "card",
"payment_status": "confirmed",
"payment_date": "2024-01-01 12:11:42",
"payment_amount": 274.16,
"payment_currency": "RON",
"payment_reference": "TXN-ABSJ-2",
"payment_comments": "Paid online"
}
]
}
Item types
type | When to use | Notes |
|---|---|---|
product |
A stocked product | code must exist in the BOCP product catalog. A 400 is returned if not found. |
discount |
Promo code, voucher, order-level discount | Use a negative item_price and item_price_with_vat. Use code DISCOUNT. |
service |
Shipping cost, gift wrap, handling fee | Use code SHIPPING for the shipping line; SERVICE for any other service. |
Key field notes
| Field | Notes |
|---|---|
order_unique_id |
Must match the {order_id} URL segment. Use your platform's native order ID. |
order_currency_code |
ISO code (e.g. RON, EUR). Must be configured in the BOCP account. All item prices must be in this currency. |
shipping_method |
One of: courier, post, personal_pickup, other. |
cod_amount |
Cash-on-delivery amount collected by the courier from the customer. Send 0 if none. Required for correct AWB generation when COD applies. |
client.client_unique_id |
Recommended. Your platform's customer ID. BOCP uses it to recognise returning customers and avoid duplicates. |
client.invoice_address.zip |
May be left blank — BOCP will attempt to resolve it from city + county. |
line_value_with_vat |
Must equal item_quantity × item_price_with_vat. |
discounted_price_with_vat |
Optional. When provided alongside line_discount_value_with_vat and less than item_price_with_vat, BOCP applies it as the effective unit price. |
payments |
Send only payments forwarded through your platform. Omit or send an empty array if no payment yet — resend the full order when payment is confirmed. Only "payment_status": "confirmed" entries count toward paid_amount. |
Successful response
BOCP returns HTTP 200 with the standard envelope. The data object contains:
{
"is_error": false,
"data": {
"BOCP_order_id": 4521,
"notices": [],
"errors": []
}
}
Save BOCP_order_id to correlate your order IDs with BOCP internal IDs. Non-fatal issues appear in notices; fatal ones appear in errors with HTTP 400.
Step 4 — Update an order
Send a PUT to the same URL to update an existing order. Only fields present in the body are changed. A minimal status-only update:
PUT https://secure.bocp.eu/app/rest/v1/{company_id}/connector/{connector_id}/order/ABC123456/
Content-Type: application/json
{
"order_unique_id": "ABC123456",
"order_status": "processing"
}
To cancel an order:
{
"order_unique_id": "ABC123456",
"order_cancelled": 1
}
items array in a PUT request it completely replaces all existing lines — there is no merge. Omit items entirely when you only want to update status or payments.
Step 3 — Receive webhook notifications
Configure an HTTPS endpoint on your server as the notification URL. BOCP POSTs a JSON body; read it with:
$data = json_decode(file_get_contents('php://input'));
Respond based on the outcome:
| Your HTTP response | Effect |
|---|---|
200 | Notification accepted and closed. |
4xx | Permanent error. Notification closed without retry. |
| Any other code | Transient error. BOCP retries periodically. |
Use the notification_type field to distinguish events.
Status change
Sent whenever the order status changes in BOCP (e.g. picked, packed, dispatched, delivered).
{
"order_unique_id": "ABC123456",
"notification_type": "status",
"status_text": "Livrata"
}
Invoice issued
Sent when BOCP issues the fiscal invoice. Both an HTML view URL and a PDF download URL are included. For Dropship connectors the invoice goes to the preconfigured dropshipper contact; for eCommerce connectors it goes to the client in the order payload.
{
"order_unique_id": "ABC123456",
"notification_type": "invoice",
"invoice_number": "5243",
"invoice_date": "2024-09-12",
"invoice_series": "SLON",
"invoice_total": 252.00,
"invoice_currency": "RON",
"invoice_total_RON": 252.00,
"invoice_url_html": "https://secure.bocp.eu/...",
"invoice_url_pdf": "https://secure.bocp.eu/..."
}
AWB issued
Sent when a courier AWB is generated. Use awb_url_pdf to retrieve the shipping label and awb_number for tracking.
{
"order_unique_id": "ABC123456",
"notification_type": "awb",
"awb_number": "1ONBLN291059727",
"awb_packet_count": 1,
"weight": 1.5,
"awb_service_type": "Standard",
"shipping_payer": "expeditor",
"cash_on_delivery": 0.00,
"cash_on_delivery_currency": "RON",
"delivery_country": "Romania",
"delivery_country_code": "RO",
"declared_value": 252.00,
"awb_type": "sameday",
"awb_subtype": "",
"awb_url_pdf": "https://secure.bocp.eu/..."
}
Product push (catalog changes)
The same notification URL also receives product-catalog pushes, so your integration doesn't
need to poll GET .../products/ on a schedule — BOCP pushes the CURRENT full state
of a product whenever it changes: on first publish, on any tracked field edit, and on stock or
price changes. This is the same mechanism used for every other connector type BOCP pushes to
(Shopify, GoMag, ...) — BOCPRAPI is treated as a regular push destination, not a passive feed.
GET .../products/, so one parser handles both. Which fields you receive updates
for is controlled by the "Câmpuri actualizate" selection in the connector settings, same as
for any other push destination.
notification_type | Sent when |
|---|---|
product_published | A product is newly published to your connector, or explicitly republished. |
product_update | A tracked field, the stock, or the price changed on an already-published product. |
product_unpublished | A product was disconnected or deleted from your connector — stop offering it. |
{
"notification_type": "product_update",
"cod_produs": "ABC123456",
"barcode": "0789876543210",
"product_name": "Product Name",
"product_website_title": "Product Name",
"product_description": "...",
"category_name": "Category",
"producator": "Brand",
"stoc_global": 50,
"stock_reserved": 8,
"stock_available": 42,
"pret_vanzare": 100.00,
"pret_vanzare_cu_tva": 119.00,
"cota_tva_vanzare": 19,
"selling_currency_txt": "RON",
"deleted": 0,
"last_changed_ts": "2026-08-17 10:00:00"
}
product_unpublished is a short packet with just the identifier, since there is
nothing else to send:
{"notification_type": "product_unpublished", "cod_produs": "ABC123456"}
Single packet per product for now — batching multiple products into one request may follow later.