Preia un meniu, formează un coș folosind identificatorii publicați și trimite de pe server o comandă completă pentru ridicare.
1. Obține cheia tenantului
Toți tenanții din producție folosesc https://website.api.pionier.ro. Solicită persoanei de contact Nexus cheia website a tenantului tău. Cere restaurantului să activeze comenzile website și să publice meniul (Retail Admin → Integrări → POS → Website). Stochează cheia în configurația secretă a serverului. Cheia identifică tenantul, iar ID-ul conexiunii selectează punctul său de vânzare.
export NEXUS_WEBSITE_KEY='your-website-key'
2. Descoperă punctele de vânzare activate
curl --fail-with-body "https://website.api.pionier.ro/v1/connections" \
-H "Authorization: Bearer $NEXUS_WEBSITE_KEY"
{
"connections": [{
"id": "website-example-connection",
"location_id": "10",
"location_name": "Central restaurant",
"pos_id": "1",
"pos_name": "Register"
}]
}
Asociază locația selectată de client cu o conexiune din răspuns. Salvează ID-ul conexiunii împreună cu coșul și comanda. Actualizează lista pentru a descoperi conexiuni POS activate ulterior; nu este necesară o cheie nouă. Nu selecta automat primul element când există mai multe conexiuni disponibile.
export NEXUS_CONNECTION_ID='the-id-returned-by-discovery'
Folosește câmpul id returnat drept NEXUS_CONNECTION_ID, nu pos_id sau location_id. Tratează-l ca pe un identificator opac; nu îl construi tu.
O listă goală înseamnă că niciun POS nu este activat. ID-ul conexiunii este obligatoriu chiar dacă răspunsul conține o singură conexiune.
3. Preia meniul
curl --fail-with-body "https://website.api.pionier.ro/v1/connections/$NEXUS_CONNECTION_ID/menu" \
-H "Authorization: Bearer $NEXUS_WEBSITE_KEY"// Run on your server with a runtime that supports fetch.
const response = await fetch(`https://website.api.pionier.ro/v1/connections/${encodeURIComponent(process.env.NEXUS_CONNECTION_ID)}/menu`, {
headers: { Authorization: `Bearer ${process.env.NEXUS_WEBSITE_KEY}` },
signal: AbortSignal.timeout(20000)
});
if (!response.ok) throw new Error(`Menu request failed: ${response.status}`);
const menu = await response.json();
// Render menu.products and keep menu.revision with the cart.<?php
// Server-side PHP with the cURL extension.
$request = curl_init('https://website.api.pionier.ro/v1/connections/' . rawurlencode(getenv('NEXUS_CONNECTION_ID')) . '/menu');
curl_setopt_array($request, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('NEXUS_WEBSITE_KEY')]
]);
$body = curl_exec($request);
$status = curl_getinfo($request, CURLINFO_HTTP_CODE);
curl_close($request);
if ($body === false || $status !== 200) {
throw new RuntimeException('Menu request failed: ' . $status);
}
$menu = json_decode($body, true, 512, JSON_THROW_ON_ERROR);404 menu_not_published înseamnă că restaurantul trebuie să publice meniul. Un meniu primit cu succes poate avea totuși accepting_orders: false; dezactivează finalizarea comenzii în acest caz.
Descarcă meniul demonstrativ ↓ pentru a explora schema. Pizza costă 3.200 bani, ambalajul 100 bani, iar brânza suplimentară 400 bani: 3.700 bani / 37,00 RON.
4. Înregistrează webhook-ul înainte de a trimite comenzi
Publică un receptor HTTPS care verifică semnăturile, salvează fiecare eveniment o singură dată și confirmă rapid primirea. Apoi înregistrează URL-ul folosind cheia tenantului. Păstrează în siguranță secretul de semnare primit; este separat de cheia API website. Consultă ghidul webhook-urilor pentru codul receptorului, reîncercări și înlocuirea secretului.
curl --fail-with-body -X PUT "https://website.api.pionier.ro/v1/webhook" \
-H "Authorization: Bearer $NEXUS_WEBSITE_KEY" \
-H "Content-Type: application/json" \
--data '{"url":"https://shop.example.com/nexus/events","enabled":true}'
Înlocuiește URL-ul demonstrativ cu receptorul tău. Sunt urmărite doar comenzile confirmate cât timp webhook-ul este activ; comenzile existente nu sunt preluate retroactiv. Un răspuns 503 webhooks_not_configured necesită activarea semnării de către Nexus. Până atunci, folosește citirea periodică a stării ca alternativă.
5. Salvează și trimite comanda
Salvează connection_id, un external_order_id și cererea completă în baza de date înainte de trimitere. Fiecare reîncercare trebuie să le refolosească pe toate trei fără modificări. Exemplul următor presupune că procesatorul a confirmat deja plata.
{
"external_order_id": "shop-1001",
"menu_revision": "example-menu-1",
"currency": "RON",
"fulfillment": "pickup",
"customer": {
"name": "Example Customer",
"phone": "0700000000"
},
"payment": {
"method": "paid_online",
"reference": "payment-example-1001"
},
"items": [
{
"product_id": "pizza-margherita",
"quantity": 1,
"modifiers": [
{
"group_id": "pizza-extras",
"option_id": "cheese"
}
],
"notes": "Please slice the pizza"
}
],
"total": 3700,
"notes": "Pickup by Alex"
}Descarcă order-pickup.json ↓. Aceste ID-uri funcționează doar cu meniul demonstrativ. Adaptează fișierul la meniul publicat pentru conexiunea selectată înainte de a-l trimite.
curl --fail-with-body "https://website.api.pionier.ro/v1/connections/$NEXUS_CONNECTION_ID/orders" \
-H "Authorization: Bearer $NEXUS_WEBSITE_KEY" \
-H 'Content-Type: application/json' \
--data-binary @order-pickup.jsonimport { readFile } from "node:fs/promises";
// In production, read the exact persisted request from your durable outbox.
const payload = await readFile("order-pickup.json", "utf8");
const response = await fetch(`https://website.api.pionier.ro/v1/connections/${encodeURIComponent(process.env.NEXUS_CONNECTION_ID)}/orders`, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.NEXUS_WEBSITE_KEY}`,
"Content-Type": "application/json"
},
body: payload,
signal: AbortSignal.timeout(20000)
});
if (response.status === 200 || response.status === 201) {
const receipt = await response.json();
// Persist confirmation; handle webhooks and reconcile current progress with GET.
} else {
// Handle the status using the errors guide. Keep the original payload.
throw new Error(`Submission requires recovery: ${response.status}`);
}
// A network exception also requires recovery; it does not prove rejection.<?php
// In production, load the original JSON from your durable outbox.
$payload = file_get_contents('order-pickup.json');
$request = curl_init('https://website.api.pionier.ro/v1/connections/' . rawurlencode(getenv('NEXUS_CONNECTION_ID')) . '/orders');
curl_setopt_array($request, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('NEXUS_WEBSITE_KEY'),
'Content-Type: application/json'
]
]);
$body = curl_exec($request);
$status = curl_getinfo($request, CURLINFO_HTTP_CODE);
curl_close($request);
if ($body === false || !in_array($status, [200, 201], true)) {
// Keep the saved ID/body. Follow the errors guide before retrying.
throw new RuntimeException('Submission requires recovery: ' . $status);
}
$receipt = json_decode($body, true, 512, JSON_THROW_ON_ERROR);Primirea cu succes întoarce 201 Created:
{
"external_order_id": "shop-1001",
"status": "pending_acceptance",
"total": 3700,
"currency": "RON"
}
6. Citește decizia restaurantului
curl --fail-with-body "https://website.api.pionier.ro/v1/connections/$NEXUS_CONNECTION_ID/orders/shop-1001" \
-H "Authorization: Bearer $NEXUS_WEBSITE_KEY"
Actualizează pagina comenzii din evenimente webhook verificate. Folosește GET de mai sus pentru starea curentă după întreruperi sau actualizări lipsă; citirea periodică este alternativa când webhook-urile nu sunt disponibile. POST-urile repetate întorc confirmarea inițială. Citește starea comenzii și regulile de recuperare înainte de activarea reîncercărilor automate.