Guides
Code examples
Copyable cURL, JavaScript and PHP examples for requests, POST with idempotency, pagination and retries.
Small, copyable examples for common environments. Replace the placeholder key with your own, and read it from an environment variable or secret store: never paste a real key into source code.
Set these once in your shell:
export NEXTOREX_API_BASE="https://api.nextorex.com/api/public/v1"
export NEXTOREX_API_KEY="nx_live_xxxxxxxxxxxx_YOUR_SECRET_HERE"cURL
GET
curl "$NEXTOREX_API_BASE/erp/customers?limit=10&sort=name" \
-H "Authorization: Bearer $NEXTOREX_API_KEY" \
-H "Accept: application/json"POST with an Idempotency-Key
curl -X POST "$NEXTOREX_API_BASE/erp/customers" \
-H "Authorization: Bearer $NEXTOREX_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: customer-import-row-1042" \
-d '{"name": "Example Traders", "email": "[email protected]", "phone": "+923001234567"}'Public catalog (no key)
curl "$NEXTOREX_API_BASE/catalog?app=crm"JavaScript (Node.js 18 or newer)
const BASE = process.env.NEXTOREX_API_BASE
const KEY = process.env.NEXTOREX_API_KEY
async function nextorex(path, { method = 'GET', body, idempotencyKey } = {}) {
const headers = { Authorization: `Bearer ${KEY}`, Accept: 'application/json' }
if (body) headers['Content-Type'] = 'application/json'
if (idempotencyKey) headers['Idempotency-Key'] = idempotencyKey
const res = await fetch(`${BASE}${path}`, { method, headers, body: body ? JSON.stringify(body) : undefined })
const json = await res.json().catch(() => null)
if (!res.ok) {
const e = json?.error ?? {}
throw Object.assign(new Error(e.message ?? `HTTP ${res.status}`), { status: res.status, code: e.code, requestId: e.request_id, retryAfter: res.headers.get('Retry-After') })
}
return json
}
// GET
const me = await nextorex('/me')
console.log(me.data.key.scopes)
// POST with an Idempotency-Key: safe to retry with the same key
import { randomUUID } from 'node:crypto'
const key = `lead-${randomUUID()}`
const lead = await nextorex('/crm/leads', {
method: 'POST',
idempotencyKey: key,
body: { first_name: 'Ayesha', last_name: 'Khan', email: '[email protected]', phone: '+923001234567', source: 'Website' },
})
console.log(lead.data.id)
// Pagination: follow next_cursor until has_more is false
async function* allLeads(filter = '') {
let cursor = null
do {
const qs = `limit=100${filter}${cursor ? `&cursor=${encodeURIComponent(cursor)}` : ''}`
const page = await nextorex(`/crm/leads?${qs}`)
yield* page.data
cursor = page.pagination.has_more ? page.pagination.next_cursor : null
} while (cursor)
}
for await (const l of allLeads('&filter[priority]=high')) console.log(l.id, l.email)Generate the idempotency key once per operation and keep it with your own record, so that a retry after a crash reuses the same key.
PHP
<?php
$base = getenv('NEXTOREX_API_BASE');
$key = getenv('NEXTOREX_API_KEY');
function nextorex(string $method, string $path, ?array $body = null, ?string $idempotencyKey = null): array
{
global $base, $key;
$headers = ['Authorization: Bearer ' . $key, 'Accept: application/json'];
if ($body !== null) {
$headers[] = 'Content-Type: application/json';
}
if ($idempotencyKey !== null) {
$headers[] = 'Idempotency-Key: ' . $idempotencyKey;
}
$ch = curl_init($base . $path);
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_POSTFIELDS => $body !== null ? json_encode($body) : null,
]);
$raw = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
$json = json_decode((string) $raw, true) ?? [];
if ($status >= 400) {
$e = $json['error'] ?? [];
throw new RuntimeException(($e['code'] ?? 'http_' . $status) . ' (request ' . ($e['request_id'] ?? 'unknown') . ')');
}
return $json;
}
// GET
$customers = nextorex('GET', '/erp/customers?limit=10');
// POST with an Idempotency-Key
$created = nextorex('POST', '/erp/customers', ['name' => 'Example Traders'], 'customer-import-row-1042');
// Pagination
$cursor = null;
do {
$query = '/erp/customers?limit=100' . ($cursor ? '&cursor=' . urlencode($cursor) : '');
$page = nextorex('GET', $query);
foreach ($page['data'] as $customer) {
echo $customer['id'], ' ', $customer['name'], PHP_EOL;
}
$cursor = $page['pagination']['has_more'] ? $page['pagination']['next_cursor'] : null;
} while ($cursor);Webhook verification
Ready-to-use verification functions for Node.js and PHP are on the Webhooks page.
Retrying safely
async function withRetry(fn, attempts = 5) {
for (let i = 0; i < attempts; i++) {
try {
return await fn()
} catch (e) {
const retryable = e.status === 429 || e.status >= 500 || e.status === undefined || e.code === 'idempotency_request_in_progress'
if (!retryable || i === attempts - 1) throw e
const wait = e.retryAfter ? Number(e.retryAfter) * 1000 : 2 ** i * 500
await new Promise((r) => setTimeout(r, wait + Math.random() * 250))
}
}
}Retry only network failures, 429 and 5xx (and idempotency_request_in_progress), always with the same Idempotency-Key. Do not retry other 4xx errors unchanged.