Salt la conținutul principal

Contract API V1

Recomandăm API-ul server-to-server. JavaScript este doar o metodă analitică opțională de rezervă și funcționează numai după acordarea consimțământului pentru analiză.

Contract API V1 Link către secțiunea Contract API V1

Recomandăm API-ul server-to-server. JavaScript este doar o metodă analitică opțională de rezervă și funcționează numai după acordarea consimțământului pentru analiză.

Comenzile, veniturile și indicatorii derivați sunt afișați numai când măsurarea conversiilor este activă. Sunt destinați exclusiv analizei și nu modifică facturarea CPC.

schema_version

1.0

payload_contract

order_v1

Content-Type

application/json

request_limit

64 KiB

Cum conectați măsurarea Link către secțiunea Cum conectați măsurarea

Recomandăm API-ul server-to-server. JavaScript este doar o metodă analitică opțională de rezervă și funcționează numai după acordarea consimțământului pentru analiză.

  1. 1 Salvați parametrul zclid din URL-ul de destinație împreună cu coșul sau comanda timp de 30 de zile.
  2. 2 Pe server, creați o amprentă HMAC-SHA-256 stabilă a ID-ului intern al comenzii, folosind o cheie separată. Nu trimiteți ID-ul în format neprelucrat și nici date cu caracter personal.
  3. 3 După crearea comenzii, trimiteți JSON-ul către API și semnați corpul exact al solicitării cu cheia secretă de integrare.
  4. 4 Pentru plată, anulare și rambursări cumulative, reutilizați aceleași zclid și order_id_hash. Păstrați neschimbate totalurile și liniile finale.

Cheia secretă de integrare este afișată o singură dată. Salvați-o în managerul de secrete de pe serverul magazinului.

Recomandat: API server-to-server Link către secțiunea Recomandat: API server-to-server

Serverul magazinului trimite comenzile verificate, modificările de stare și rambursările direct către Zoneo. Nu introduceți niciodată cheia secretă în browser.

POST https://zoneo.ro/api/v1/conversions
Sandbox https://zoneo.ro/api/v1/conversions/sandbox

Pe server, creați o amprentă HMAC-SHA-256 stabilă a ID-ului intern al comenzii, folosind o cheie separată. Nu trimiteți ID-ul în format neprelucrat și nici date cu caracter personal.

order_id_hash · PHP

$orderIdHash = hash_hmac(
    'sha256',
    "zoneo-order-v1\n".$internalOrderId,
    $_ENV['ZONEO_ORDER_HASH_KEY'],
);

Exemplu de solicitare Link către secțiunea Exemplu de solicitare

După crearea comenzii, trimiteți JSON-ul către API și semnați corpul exact al solicitării cu cheia secretă de integrare.

order_v1 · JSON

{
    "schema_version": "1.0",
    "zclid": "018fb72a-7d8e-7c3c-a4da-f37ce07ad739",
    "order_id_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "currency": "RON",
    "occurred_at": "2026-08-31T12:34:56Z",
    "status": "placed",
    "refund_amount_minor": 0,
    "totals": {
        "items_gross_minor": 14000,
        "discount_minor": 1500,
        "shipping_gross_minor": 390,
        "fees_gross_minor": 100,
        "tax_minor": 2165,
        "order_total_gross_minor": 12990
    },
    "items": [
        {
            "merchant_item_id": "ITEM_ID_FROM_FEED",
            "item_group_id": "MODEL-10",
            "variant_id": "size:42",
            "name": "PRODUCT_NAME",
            "gtin": "8581234567890",
            "quantity": 2,
            "unit_price_gross_minor": 7000,
            "line_total_gross_minor": 14000
        }
    ],
    "order_locale": "ro",
    "expected_delivery_date": "2026-09-03"
}
order_v1 · JSON
JSON Câmpuri obligatorii V1
schema_version = "1.0"
zclid UUID
order_id_hash HMAC-SHA-256 · [a-f0-9]{64}
currency ISO 4217 · RON
occurred_at ISO 8601 · UTC
status placed | paid | cancelled | partially_refunded | refunded
refund_amount_minor integer ≥ 0 · Σ · monotonic
totals object · integer · gross
items array[1..100]
order_locale BCP 47
expected_delivery_date YYYY-MM-DD
order_v1 · items[]
items[] Câmpuri obligatorii V1
merchant_item_id feed.ITEM_ID · stable
quantity integer · 1..1000
unit_price_gross_minor integer ≥ 0
line_total_gross_minor unit_price_gross_minor × quantity
item_group_id string
variant_id string
name string · PRODUCT_NAME · PII = 0
gtin [0-9]{8,14}

totals · RON · integer

totals.items_gross_minor = sum(items[].line_total_gross_minor)

totals.order_total_gross_minor = totals.items_gross_minor - totals.discount_minor + totals.shipping_gross_minor + totals.fees_gross_minor

line_total_gross_minor = unit_price_gross_minor × quantity

Semnătură canonică Link către secțiunea Semnătură canonică

Dacă nu ați salvat cheia secretă inițială, utilizați opțiunea „Regenerați cheia secretă” și salvați imediat noua cheie în siguranță.

HTTP · HMAC-SHA-256
HTTP V1
Content-Type application/json
X-Zoneo-Integration-ID zci_...
X-Zoneo-Timestamp Unix · UTC
X-Zoneo-Nonce CSPRNG · unique · len ≥ 16
Idempotency-Key order:{hash}:{status}
X-Zoneo-Signature v1=HMAC_SHA256_HEX

HMAC-SHA-256 · canonical request

UPPERCASE_HTTP_METHOD
/exact/request/path
unix_timestamp
nonce
idempotency_key
sha256_hex_of_exact_raw_body

body_hash = SHA256(raw_body)
signature = HMAC_SHA256(api_secret, canonical_request)
X-Zoneo-Signature = "v1=" + lowercase_hex(signature)

S2S · PHP

<?php

$path = '/api/v1/conversions';
$body = json_encode($payload, JSON_THROW_ON_ERROR | JSON_UNESCAPED_SLASHES);
$timestamp = time();
$nonce = bin2hex(random_bytes(16));
$idempotencyKey = 'order:'.$orderIdHash.':'.$payload['status'];
$canonical = implode("\n", [
    'POST',
    $path,
    (string) $timestamp,
    $nonce,
    $idempotencyKey,
    hash('sha256', $body),
]);
$signature = hash_hmac('sha256', $canonical, $_ENV['ZONEO_API_SECRET']);

$headers = [
    'Content-Type: application/json',
    'X-Zoneo-Integration-ID: '.$_ENV['ZONEO_INTEGRATION_ID'],
    'X-Zoneo-Timestamp: '.$timestamp,
    'X-Zoneo-Nonce: '.$nonce,
    'Idempotency-Key: '.$idempotencyKey,
    'X-Zoneo-Signature: v1='.$signature,
];

$curl = curl_init('https://zoneo.ro/api/v1/conversions');
curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_POSTFIELDS => $body,
    CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
curl_close($curl);

Plasată → Rambursată Link către secțiunea Plasată → Rambursată

Pentru plată, anulare și rambursări cumulative, reutilizați aceleași zclid și order_id_hash. Păstrați neschimbate totalurile și liniile finale.

Plasată · placed Plătită · paid Anulată · cancelled Rambursată parțial · partially_refunded Rambursată · refunded

order_v1 · lifecycle

placed -> paid | cancelled | partially_refunded | refunded
paid -> partially_refunded | refunded
partially_refunded -> refunded
cancelled, refunded -> terminal

0 <= refund_amount_minor <= totals.order_total_gross_minor
new_refund_amount_minor >= previous_refund_amount_minor

Idempotency-Key · retry

nonce₁ != nonce₂
retry = nonce₂ + Idempotency-Key₁ + SHA256(JSON₁)
Idempotency-Key₁ + SHA256(JSON₁) -> HTTP 200
Idempotency-Key₁ + SHA256(JSON₂) -> HTTP 409 idempotency_conflict

Sandbox V1 Link către secțiunea Sandbox V1

Lipiți un JSON V1 pentru a valida câmpurile, totalurile și asocierea cu feedul fără a crea o comandă sau a afecta facturarea.

POST https://zoneo.ro/api/v1/conversions/sandbox
persisted = false billing_impact = false

Măsurare opțională prin JavaScript Link către secțiunea Măsurare opțională prin JavaScript

Biblioteca păstrează zclid după consimțământ și trimite doar evenimentul inițial placed din pagina de mulțumire. Trimiteți stările ulterioare în siguranță prin S2S.

Consimțământul este dezactivat implicit. Funcția consent trebuie să returneze true numai după acordarea valabilă a consimțământului utilizatorului pentru analiză.

Încărcare și inițializare

<script src="https://zoneo.ro/integrations/zoneo-conversion-v1.js"></script>
<script>
const zoneo = window.ZoneoConversions.init({
  integrationId: 'zci_...',
  apiBase: 'https://zoneo.ro/api/v1/conversions',
  consent: () => analyticsConsent === true
})

zoneo.track({
  order_id_hash: 'SERVER_HMAC_SHA256',
  currency: 'RON',
  occurred_at: new Date().toISOString(),
  status: 'placed',
  totals: {
    items_gross_minor: 12990,
    discount_minor: 0,
    shipping_gross_minor: 0,
    fees_gross_minor: 0,
    tax_minor: 2165,
    order_total_gross_minor: 12990
  },
  items: [{
    merchant_item_id: 'ITEM_ID_FROM_FEED',
    quantity: 1,
    unit_price_gross_minor: 12990,
    line_total_gross_minor: 12990
  }]
})
</script>

Starea integrării Link către secțiunea Starea integrării

Evenimente acceptate și respinse în ultimele 7 zile.

201 · created = true
200 · idempotent = true | deduplicated = true
4xx · error.code

HTTP 201 · JSON

{
    "data": {
        "conversion_reference": "6bfca33e-3ac7-48dc-a733-c1f313853269",
        "status": "placed",
        "source": "s2s",
        "verification": "hmac_current",
        "schema_version": "1.0",
        "payload_contract": "order_v1",
        "totals": {
            "items_gross_minor": 14000,
            "discount_minor": 1500,
            "shipping_gross_minor": 390,
            "fees_gross_minor": 100,
            "tax_minor": 2165,
            "order_total_gross_minor": 12990
        },
        "refund_amount_minor": 0,
        "net_revenue_minor": 12990,
        "items": {
            "count": 1,
            "quantity_total": 2,
            "matched_count": 1,
            "match_status": "complete"
        },
        "totals_reconciled": true,
        "warnings": [],
        "currency": "RON",
        "created": true,
        "idempotent": false,
        "deduplicated": false,
        "provisional": false,
        "billing_impact": false
    }
}

HTTP 4xx · JSON

{
    "error": {
        "code": "order_total_mismatch",
        "field": "totals.order_total_gross_minor",
        "details": {
            "expected_minor": 12990,
            "received_minor": 13000
        }
    }
}
invalid_signature stale_timestamp replayed_nonce pii_not_allowed items_total_mismatch order_total_mismatch currency_mismatch click_not_eligible store_or_market_mismatch not_last_zoneo_click attribution_window_expired invalid_state_transition order_definition_conflict refund_amount_decreased order_attribution_conflict

Protecția datelor personale Link către secțiunea Protecția datelor personale

Cele mai recente comenzi primite de Zoneo doar pentru analiză. ID-urile brute și datele personale nu sunt afișate niciodată.

Pe server, creați o amprentă HMAC-SHA-256 stabilă a ID-ului intern al comenzii, folosind o cheie separată. Nu trimiteți ID-ul în format neprelucrat și nici date cu caracter personal.

Comenzile, veniturile și indicatorii derivați sunt afișați numai când măsurarea conversiilor este activă. Sunt destinați exclusiv analizei și nu modifică facturarea CPC.

Cum conectați măsurarea

Recomandăm API-ul server-to-server. JavaScript este doar o metodă analitică opțională de rezervă și funcționează numai după acordarea consimțământului pentru analiză.