Getting Started
Make your first authenticated API call to the Ordeliya API in under 5 minutes.
Quick Start
This guide takes you from zero to a working API integration. By the end, you will have authenticated, listed your products, and created your first order programmatically.
Prerequisites
- An Ordeliya account at app.ordeliya.com
- A store with at least one product in the menu
- A terminal with
curlinstalled (or any HTTP client)
Step 1: Get Your API Key
The fastest way to authenticate is with an API Key. API Keys are long-lived and don't require token refresh.
- Log in to your dashboard at app.ordeliya.com
- Go to Settings → API Keys
- Click Create API Key
- Give it a name (e.g., "My Integration") and select scopes
- Copy the key — it starts with
ord_live_sk_
API Keys are shown only once. Store them securely. If you lose a key, revoke it and create a new one.
Step 2: Verify Connectivity
Test that your key works with the health endpoint (no auth required) and then an authenticated call:
# Public health check (no auth required)
curl https://api.ordeliya.com/health
{
"success": true,
"data": {
"status": "ok",
"db": true,
"redis": true,
"responseTime": 4
}
}
Now test with your API key:
# Authenticated request — list your products
curl https://api.ordeliya.com/products \
-H "Authorization: Bearer ord_live_sk_7f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c"
{
"success": true,
"data": [
{
"id": "prod_8kx2m4n7",
"name": "Margherita Pizza",
"slug": "margherita-pizza",
"basePrice": 8900,
"status": "ACTIVE",
"isAvailable": true,
"imageUrl": "https://cdn.ordeliya.com/stores/store_r4k7/products/margherita.webp",
"categories": [
{ "id": "cat_p1z2a3", "name": "Pizzas" }
]
},
{
"id": "prod_3jn8v5q2",
"name": "Garlic Bread",
"slug": "garlic-bread",
"basePrice": 3900,
"status": "ACTIVE",
"isAvailable": true,
"imageUrl": null,
"categories": [
{ "id": "cat_s1d2e3", "name": "Sides" }
]
}
],
"meta": {
"total": 2,
"page": 1,
"limit": 20,
"totalPages": 1,
"requestId": "req_a1b2c3d4e5f6"
}
}
If you see your products, you're connected.
Step 3: Get an Access Token (Alternative)
If you prefer short-lived JWTs over API Keys (e.g., for browser-based apps):
curl -X POST https://api.ordeliya.com/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "owner@myrestaurant.dk",
"password": "your-secure-password"
}'
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfNGs3bTJuOHYiLCJlbWFpbCI6Im93bmVyQG15cmVzdGF1cmFudC5kayIsInN0b3JlSWQiOiJzdG9yZV9yNGs3IiwiYXVkIjoidGVuYW50IiwiaWF0IjoxNzEwNTEwMTgwLCJleHAiOjE3MTA1MTEwODB9.abc123",
"user": {
"id": "usr_4k7m2n8v",
"email": "owner@myrestaurant.dk",
"name": "Anders Jensen"
},
"stores": [
{
"storeId": "store_r4k7",
"storeName": "Pizza Roma — Copenhagen",
"websiteId": "web_m3x9",
"role": "OWNER"
},
{
"storeId": "store_h8n2",
"storeName": "Pizza Roma — Aarhus",
"websiteId": "web_m3x9",
"role": "OWNER"
}
]
}
}
The access token expires in 15 minutes. A refreshToken is set as an httpOnly cookie automatically.
Use the token in subsequent requests:
curl https://api.ordeliya.com/orders \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
Step 4: Create Your First Order
Create a manual order using the POST /orders endpoint. Include X-Idempotency-Key to prevent duplicates:
curl -X POST https://api.ordeliya.com/orders \
-H "Authorization: Bearer ord_live_sk_7f3a9b2c1d4e5f6a7b8c9d0e1f2a3b4c" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: my-first-order-001" \
-d '{
"fulfillmentType": "PICKUP",
"source": "PHONE",
"customerName": "Maria Nielsen",
"customerPhone": "+4520123456",
"customerEmail": "maria@example.dk",
"items": [
{
"productId": "prod_8kx2m4n7",
"quantity": 2,
"notes": "Extra crispy"
},
{
"productId": "prod_3jn8v5q2",
"quantity": 1
}
],
"notes": "Ring doorbell on arrival",
"scheduledAt": null
}'
{
"success": true,
"data": {
"id": "ord_v7k3m9n2",
"orderId": "2026-0147",
"status": "RECEIVED",
"fulfillmentType": "PICKUP",
"source": "PHONE",
"customer": {
"name": "Maria Nielsen",
"phone": "+4520123456",
"email": "maria@example.dk"
},
"items": [
{
"id": "oi_x1y2z3",
"productId": "prod_8kx2m4n7",
"productName": "Margherita Pizza",
"quantity": 2,
"unitPriceMinor": 8900,
"totalMinor": 17800,
"notes": "Extra crispy"
},
{
"id": "oi_a4b5c6",
"productId": "prod_3jn8v5q2",
"productName": "Garlic Bread",
"quantity": 1,
"unitPriceMinor": 3900,
"totalMinor": 3900,
"notes": null
}
],
"subtotalMinor": 21700,
"taxMinor": 5425,
"deliveryFeeMinor": 0,
"discountMinor": 0,
"totalMinor": 21700,
"currency": "DKK",
"paymentStatus": "PENDING",
"notes": "Ring doorbell on arrival",
"createdAt": "2026-03-15T14:22:31.000Z"
}
}
The order appears immediately in your dashboard under Orders.
Pagination
All list endpoints support cursor-based pagination:
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 20 | Items per page (max: 100) |
sort | string | createdAt | Sort field |
order | string | desc | Sort direction (asc or desc) |
# Get page 3, 50 items per page, oldest first
curl "https://api.ordeliya.com/orders?page=3&limit=50&order=asc" \
-H "Authorization: Bearer ord_live_sk_..."
The response meta includes pagination info:
{
"meta": {
"total": 1247,
"page": 3,
"limit": 50,
"totalPages": 25
}
}
Idempotency
For any POST request that creates a resource, include X-Idempotency-Key:
curl -X POST https://api.ordeliya.com/orders \
-H "Authorization: Bearer ord_live_sk_..." \
-H "X-Idempotency-Key: checkout_session_abc123" \
-H "Content-Type: application/json" \
-d '{ ... }'
How it works:
- First request with key
checkout_session_abc123→ creates the order, returns201 - Second request with the same key → returns the original response without creating a duplicate
- Keys expire after 24 hours
Key format recommendations:
| Pattern | Example |
|---|---|
| Session-based | checkout_{sessionId}_{timestamp} |
| Client-generated | ord_{uuid} |
| POS transaction | pos_{deviceId}_{transactionId} |
Error Handling
The API uses standard HTTP status codes:
| Code | Meaning | When |
|---|---|---|
200 | OK | Successful GET, PATCH |
201 | Created | Successful POST |
204 | No Content | Successful DELETE |
400 | Bad Request | Invalid JSON, missing required fields |
401 | Unauthorized | Missing, expired, or invalid token |
403 | Forbidden | Valid token but insufficient role/permissions |
404 | Not Found | Resource doesn't exist or belongs to another store |
409 | Conflict | Duplicate resource (e.g., duplicate email) |
422 | Unprocessable Entity | Validation errors (correct format, invalid values) |
429 | Too Many Requests | Rate limited — check Retry-After header |
500 | Server Error | Unexpected error — include requestId in bug report |
Error responses always include a requestId for debugging:
{
"success": false,
"error": {
"statusCode": 422,
"message": "Validation failed",
"errors": [
{ "field": "items", "message": "At least one item is required" },
{ "field": "fulfillmentType", "message": "Must be DELIVERY, PICKUP, or CURBSIDE" }
]
},
"meta": {
"requestId": "req_x9y8z7w6v5u4"
}
}
Next Steps
You've made your first API call and created an order. Here's what to explore next:
- Authentication — JWT realms, API Key scopes, roles & permissions
- Orders API — Full order lifecycle, status transitions, timeline
- Webhooks — Real-time event subscriptions with HMAC verification