External API v1

ZenAdmin API

Programmatic access to your company-scoped external APIs, including existing inventory APIs and the newly added partner integration APIs.

Base URL

https://baseUrl/api/external

Content Type

All requests and responses use application/json.

Example Request
curl -X GET "https://baseUrl/api/external/devices?page=0&limit=25" \
  -H "x-api-key: your-api-key-here"

Authentication

All API requests require a valid API key.

MethodHeaderValue
Recommendedx-api-keyyour-api-key
AlternativeAuthorizationBearer your-api-key
Important: API key is shown once when created.
401 Response
{"success":false,"message":"Invalid or expired API key"}

Error Handling

StatusMeaningWhen
200OKRequest succeeded
400Bad RequestValidation error
401UnauthorizedInvalid API key
404Not FoundResource not found
Error Example
{"success":false,"message":"Data validation failed"}

Pagination

List APIs return meta_data with total_items, page_no, items_on_page.

List Devices

GET/api/external/devices
Request
curl -X GET "https://baseUrl/api/external/devices?page=0&limit=25" \
  -H "x-api-key: your-api-key"

Get Device Details

GET/api/external/devices/:id
404 Response
{"success":false,"message":"Device not found"}

Get API Context

GET/api/external/me

Returns company_id, API version, and supported webhook events.

200 Response
{"success":true,"data":{"company_id":"...","api_version":"v1","supported_events":["rfq.created","order.status_changed"]}}

Create Order

POST/api/external/orders
Key points
  • Idempotent by external_request_id
  • Employee resolution fallback: user_id -> work_email -> employee_id
  • Per-key rate limit: 60 req/min (burst 120)
Request Body
{
  "external_request_id":"JIRA-AUTO-123",
  "external_system":"jira",
  "external_ticket_id":"DEV-1234",
  "employee":{"work_email":"alice@company.com"},
  "ship_to_type":"address",
  "address":{"city":"Cupertino","country_id":"","postal_code":"95014"},
  "items":[{"product_configuration_id":"","quantity":1}]
}

Get Order

GET/api/external/orders/:rfq_id

List Orders

GET/api/external/orders?status=&from=&to=&page=&limit=

Cancel Order

POST/api/external/orders/:rfq_id/cancel
Cancellation is rejected when order has reached in_transit or delivered.

Catalog APIs

GET/api/external/catalog/devices?country_id=&search=&page=&limit=
GET/api/external/catalog/devices/:product_configuration_id
GET/api/external/catalog/countries

Employee APIs

GET/api/external/employees?search=&status=&department_id=&page=&limit=
GET/api/external/employees/:id

Webhook APIs

POST/api/external/webhooks/subscriptions
GET/api/external/webhooks/subscriptions
PATCH/api/external/webhooks/subscriptions/:id
DELETE/api/external/webhooks/subscriptions/:id
GET/api/external/webhooks/deliveries?subscription_id=&status=&event=
POST/api/external/webhooks/deliveries/:id/redeliver
Signature Verify (Node.js)
const ts = req.header('X-Zenadmin-Timestamp');
const sig = req.header('X-Zenadmin-Signature').replace('sha256=','');
const signingKey = sha256(plaintextSecret);
const expected = hmacSha256(signingKey, `${ts}.${rawBody}`);