curl --request POST \
--url https://api.aireserve.com/v1/customers/{customerId}/keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Acme — EMEA production",
"org_id": "emea"
}
'import requests
url = "https://api.aireserve.com/v1/customers/{customerId}/keys"
payload = {
"name": "Acme — EMEA production",
"org_id": "emea"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: 'Acme — EMEA production', org_id: 'emea'})
};
fetch('https://api.aireserve.com/v1/customers/{customerId}/keys', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"id": "9c3f1a2b-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"name": "Acme — EMEA production",
"customer_id": "cust_8f3a2b",
"org_id": "emea",
"key_prefix": "aireserve_api_a1b",
"key_suffix": "f0e9d8",
"status": "active",
"created_at": "2026-10-06T09:30:00.000Z",
"last_used_at": null,
"revoked_at": null,
"key": "aireserve_api_a1b…f0e9d8"
}{
"error": {
"message": "<string>",
"type": "<string>",
"param": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"param": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"param": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"param": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"param": "<string>",
"code": "<string>"
}
}Create a customer key
Mint an API key for one of your end customers. Every request made with the key is billed to your organization and reported under this customer — in Analytics, in GET /v1/customers/usage, and in exports — with no per-request tagging. Pass org_id to mint a sub key for one of the customer’s own organizations or sub-accounts; its usage is reported under both the customer and that organization. The plaintext key is returned once, in this response only.
curl --request POST \
--url https://api.aireserve.com/v1/customers/{customerId}/keys \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "Acme — EMEA production",
"org_id": "emea"
}
'import requests
url = "https://api.aireserve.com/v1/customers/{customerId}/keys"
payload = {
"name": "Acme — EMEA production",
"org_id": "emea"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: 'Acme — EMEA production', org_id: 'emea'})
};
fetch('https://api.aireserve.com/v1/customers/{customerId}/keys', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"id": "9c3f1a2b-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
"name": "Acme — EMEA production",
"customer_id": "cust_8f3a2b",
"org_id": "emea",
"key_prefix": "aireserve_api_a1b",
"key_suffix": "f0e9d8",
"status": "active",
"created_at": "2026-10-06T09:30:00.000Z",
"last_used_at": null,
"revoked_at": null,
"key": "aireserve_api_a1b…f0e9d8"
}{
"error": {
"message": "<string>",
"type": "<string>",
"param": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"param": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"param": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"param": "<string>",
"code": "<string>"
}
}{
"error": {
"message": "<string>",
"type": "<string>",
"param": "<string>",
"code": "<string>"
}
}Authorizations
Your AI Reserve API key (aireserve_api_…) from the API Keys page in the portal (https://portal.aireserve.com/keys).
Path Parameters
Your end-customer id, URL-encoded — the same opaque id you would otherwise send as x-aireserve-customer (1–128 printable characters).
1 - 128Body
Display name for the key. Defaults to the customer id (and org id for a sub key).
1 - 255The customer's organization / sub-account. When set the key is a sub key: usage is reported under the customer AND this organization.
1 - 128Response
Key created. Store key now — it is never shown again.
Key id — the {keyId} for DELETE.
^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$Your end-customer id, exactly as given in the path.
The customer's organization for a sub key; null for a customer-level key.
First characters of the key, for telling keys apart in a list.
Last characters of the key.
active serves requests; paused was stopped by a spending guardrail or an admin and can be resumed in the portal; revoked is permanent.
active, paused, revoked ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$The plaintext API key. Shown exactly once — store it now; only a hash is kept.