curl --request POST \
--url https://api-sandbox.endl.io/giftcards/orders \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-Api-Key-Id: <api-key>' \
--data '
{
"partner_order_ref": "ORD-10294",
"amount_minor": "100000",
"currency": "INR",
"payment_ref": "pi_3QXk2s",
"items": [
{
"canonical_sku": "BIGBASKET--IN--INR",
"denomination_minor": "50000",
"qty": 2
}
]
}
'import requests
url = "https://api-sandbox.endl.io/giftcards/orders"
payload = {
"partner_order_ref": "ORD-10294",
"amount_minor": "100000",
"currency": "INR",
"payment_ref": "pi_3QXk2s",
"items": [
{
"canonical_sku": "BIGBASKET--IN--INR",
"denomination_minor": "50000",
"qty": 2
}
]
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"X-Api-Key-Id": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
'X-Api-Key-Id': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
partner_order_ref: 'ORD-10294',
amount_minor: '100000',
currency: 'INR',
payment_ref: 'pi_3QXk2s',
items: [{canonical_sku: 'BIGBASKET--IN--INR', denomination_minor: '50000', qty: 2}]
})
};
fetch('https://api-sandbox.endl.io/giftcards/orders', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-sandbox.endl.io/giftcards/orders",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'partner_order_ref' => 'ORD-10294',
'amount_minor' => '100000',
'currency' => 'INR',
'payment_ref' => 'pi_3QXk2s',
'items' => [
[
'canonical_sku' => 'BIGBASKET--IN--INR',
'denomination_minor' => '50000',
'qty' => 2
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>",
"X-Api-Key-Id: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-sandbox.endl.io/giftcards/orders"
payload := strings.NewReader("{\n \"partner_order_ref\": \"ORD-10294\",\n \"amount_minor\": \"100000\",\n \"currency\": \"INR\",\n \"payment_ref\": \"pi_3QXk2s\",\n \"items\": [\n {\n \"canonical_sku\": \"BIGBASKET--IN--INR\",\n \"denomination_minor\": \"50000\",\n \"qty\": 2\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-Api-Key-Id", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-sandbox.endl.io/giftcards/orders")
.header("Idempotency-Key", "<idempotency-key>")
.header("X-Api-Key-Id", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"partner_order_ref\": \"ORD-10294\",\n \"amount_minor\": \"100000\",\n \"currency\": \"INR\",\n \"payment_ref\": \"pi_3QXk2s\",\n \"items\": [\n {\n \"canonical_sku\": \"BIGBASKET--IN--INR\",\n \"denomination_minor\": \"50000\",\n \"qty\": 2\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.endl.io/giftcards/orders")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-Api-Key-Id"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"partner_order_ref\": \"ORD-10294\",\n \"amount_minor\": \"100000\",\n \"currency\": \"INR\",\n \"payment_ref\": \"pi_3QXk2s\",\n \"items\": [\n {\n \"canonical_sku\": \"BIGBASKET--IN--INR\",\n \"denomination_minor\": \"50000\",\n \"qty\": 2\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"order_id": "9f1c8a44-2b7e-4d31-9a6f-5c0e7b2d81a3",
"state": "PENDING"
}{
"code": "VALIDATION_ERROR",
"message": "items must be a non-empty array"
}{
"code": "AUTH_INVALID_KEY",
"message": "credential could not be verified"
}{
"code": "SCOPE_FORBIDDEN",
"message": "key lacks the required scope"
}{
"code": "IDEMPOTENCY_KEY_REUSED",
"message": "idempotency key was used with a different body"
}{
"code": "VALIDATION_ERROR",
"message": "request body too large"
}{
"code": "RATE_LIMITED",
"message": "rate limit exceeded"
}{
"code": "INTERNAL_ERROR",
"message": "unexpected error"
}Create an order
Places a fulfilment instruction. Returns 202 Accepted with an order id.
The order is not complete when this returns, and the response never contains vouchers. A 201 would imply it was finished.
There is no confirmation step and no cancellation endpoint — an accepted order either fulfils or produces a refund obligation. Validate before you send.
amount_minor must equal Σ(denomination_minor × qty) over the items. That is checked asynchronously: a mismatch is accepted here, then moves to FAILED with state_reason: AMOUNT_MISMATCH and raises a refund obligation. Compute the total yourself before sending.
curl --request POST \
--url https://api-sandbox.endl.io/giftcards/orders \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--header 'X-Api-Key-Id: <api-key>' \
--data '
{
"partner_order_ref": "ORD-10294",
"amount_minor": "100000",
"currency": "INR",
"payment_ref": "pi_3QXk2s",
"items": [
{
"canonical_sku": "BIGBASKET--IN--INR",
"denomination_minor": "50000",
"qty": 2
}
]
}
'import requests
url = "https://api-sandbox.endl.io/giftcards/orders"
payload = {
"partner_order_ref": "ORD-10294",
"amount_minor": "100000",
"currency": "INR",
"payment_ref": "pi_3QXk2s",
"items": [
{
"canonical_sku": "BIGBASKET--IN--INR",
"denomination_minor": "50000",
"qty": 2
}
]
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"X-Api-Key-Id": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
'X-Api-Key-Id': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
partner_order_ref: 'ORD-10294',
amount_minor: '100000',
currency: 'INR',
payment_ref: 'pi_3QXk2s',
items: [{canonical_sku: 'BIGBASKET--IN--INR', denomination_minor: '50000', qty: 2}]
})
};
fetch('https://api-sandbox.endl.io/giftcards/orders', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-sandbox.endl.io/giftcards/orders",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'partner_order_ref' => 'ORD-10294',
'amount_minor' => '100000',
'currency' => 'INR',
'payment_ref' => 'pi_3QXk2s',
'items' => [
[
'canonical_sku' => 'BIGBASKET--IN--INR',
'denomination_minor' => '50000',
'qty' => 2
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>",
"X-Api-Key-Id: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-sandbox.endl.io/giftcards/orders"
payload := strings.NewReader("{\n \"partner_order_ref\": \"ORD-10294\",\n \"amount_minor\": \"100000\",\n \"currency\": \"INR\",\n \"payment_ref\": \"pi_3QXk2s\",\n \"items\": [\n {\n \"canonical_sku\": \"BIGBASKET--IN--INR\",\n \"denomination_minor\": \"50000\",\n \"qty\": 2\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("X-Api-Key-Id", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-sandbox.endl.io/giftcards/orders")
.header("Idempotency-Key", "<idempotency-key>")
.header("X-Api-Key-Id", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"partner_order_ref\": \"ORD-10294\",\n \"amount_minor\": \"100000\",\n \"currency\": \"INR\",\n \"payment_ref\": \"pi_3QXk2s\",\n \"items\": [\n {\n \"canonical_sku\": \"BIGBASKET--IN--INR\",\n \"denomination_minor\": \"50000\",\n \"qty\": 2\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-sandbox.endl.io/giftcards/orders")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["X-Api-Key-Id"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"partner_order_ref\": \"ORD-10294\",\n \"amount_minor\": \"100000\",\n \"currency\": \"INR\",\n \"payment_ref\": \"pi_3QXk2s\",\n \"items\": [\n {\n \"canonical_sku\": \"BIGBASKET--IN--INR\",\n \"denomination_minor\": \"50000\",\n \"qty\": 2\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"order_id": "9f1c8a44-2b7e-4d31-9a6f-5c0e7b2d81a3",
"state": "PENDING"
}{
"code": "VALIDATION_ERROR",
"message": "items must be a non-empty array"
}{
"code": "AUTH_INVALID_KEY",
"message": "credential could not be verified"
}{
"code": "SCOPE_FORBIDDEN",
"message": "key lacks the required scope"
}{
"code": "IDEMPOTENCY_KEY_REUSED",
"message": "idempotency key was used with a different body"
}{
"code": "VALIDATION_ERROR",
"message": "request body too large"
}{
"code": "RATE_LIMITED",
"message": "rate limit exceeded"
}{
"code": "INTERNAL_ERROR",
"message": "unexpected error"
}Idempotency
| You send | Endl answers | Effect |
|---|---|---|
| Same key, identical body | 202 with the original order_id | Nothing new is created. Safe to repeat indefinitely. |
| Same key, different body | 409 IDEMPOTENCY_KEY_REUSED | Nothing is created. |
New key, same partner_order_ref | 409 PARTNER_ORDER_REF_DUPLICATE | Nothing is created; the existing id is returned. |
409. Serialise once, then hash and send the same string.Authorizations
Your key id, verbatim. Public — it identifies the credential. The secret is never transmitted.
Headers
Required on POST /orders. A stable string — a UUID is the simplest scheme — that makes the call safe to retry. Absent means VALIDATION_ERROR.
1Unix seconds. Optional, carried for symmetry — send the same value as the t= inside X-Signature, which is the one actually validated.
Body
Your own reference. Trimmed; 1–200 characters after trimming. Unique across your orders — a repeat is a 409.
Total in minor units. Must equal Σ(denomination_minor × qty). A number must be a safe integer; a string must match ^[0-9]+$.
^[A-Z]{3}$. Applies to the whole order — lower case is rejected, and a mixed-currency order is refused.
Your payment reference, 1–200 characters. Recorded but never interpreted or verified.
1–50 entries. An empty array is a VALIDATION_ERROR.
1 - 50 elementsShow child attributes
Show child attributes
Response
Accepted. The order will be worked on.