Creates or updates up to 500 records, keyed on external_id within your key's provider. A record
missing from the request changes nothing. Send records explains each field
in full.
Query
| Parameter | |
|---|
dry_run | 1 to check the request and store nothing. true is read the same way. 0 or false is a real request, and any other value is refused. See Dry run. |
Body
| Field | Type | |
|---|
records | array | Required. 1 to 500 records. The body has no other field. |
A record
| Field | Type | |
|---|
external_id | string | Required. Up to 200 characters. |
status | string | Required. Up to 200 characters. Your own coarse word, such as active, lapsed, revoked or withdrawn. Never interpreted and never shown outside your organization. |
normalized_state | string | Required. active, inactive or unknown. |
tier | string or null | Up to 200 characters. |
capabilities | array of string | From a closed list: physical_sales. |
effective_from | string or null | ISO 8601. |
expires_at | string or null | ISO 8601. |
credential | object or null | Creates the public page. |
identities | array | At most 50. The full set your system vouches for. [] withdraws every identity you supplied. Omit to leave them as they are. |
credential
| Field | Type | |
|---|
holder_name | string | Required. Up to 200 characters. Public. Not an email address. |
title | string or null | Up to 80 characters. |
registration_id | string or null | Up to 64 characters. |
registered_at | string or null | ISO 8601. |
publish_terms | boolean | False by default. Stored, and the public page draws nothing from it. |
retired | boolean | False by default. |
An identity
| Field | Type | |
|---|
source | string | Required. Up to 80 characters. Warden lowercases it. |
handle | string or null | Up to 200 characters. Read from url where it can be, for etsy and ebay. |
url | string or null | Up to 600 characters. http or https. |
public | boolean | False by default. |
assurance | string | registered, the default, or issuer_hosted. |
An identity needs a handle or a url. A bad identity is refused alone and its record is still
written. See One bad identity.
Request
curl -sS "https://3dwarden.com/api/v1/integration/entitlements" \
-H "Authorization: Bearer $WARDEN_KEY" \
-H "Content-Type: application/json" \
-d '{
"records": [{
"external_id": "member-1001",
"status": "active",
"normalized_state": "active",
"capabilities": ["physical_sales"],
"credential": { "holder_name": "Example Print Shop", "registration_id": "EX-1A67D8F2" },
"identities": [{ "source": "website", "url": "https://shop.example.com", "public": true }]
}]
}'
const res = await fetch('https://3dwarden.com/api/v1/integration/entitlements', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.WARDEN_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ records }),
})
if (!res.ok) throw new Error(`${res.status} ${(await res.json()).code}`)
const { records: written, rejected } = await res.json()
import os, requests
res = requests.post(
"https://3dwarden.com/api/v1/integration/entitlements",
headers={"Authorization": f"Bearer {os.environ['WARDEN_KEY']}"},
json={"records": records},
timeout=60,
)
res.raise_for_status()
written, rejected = res.json()["records"], res.json()["rejected"]
Response, 200
{
"records": [
{
"external_id": "member-1001",
"public_id": "q3Zr8mW1x0aB4cD5eF6gHi",
"normalized_state": "active",
"capabilities": ["physical_sales"],
"last_synced_at": "2026-09-21T18:04:11.123456+00:00",
"retired": false,
"verify_url": "https://3dwarden.com/verify/q3Zr8mW1x0aB4cD5eF6gHi"
}
],
"rejected": []
}
| Field | Type | |
|---|
records | array | The records that were written, in the order you sent them. A refused record is absent. |
records[].public_id | string or null | Null for a record with no credential. Never changes while Warden holds the record. |
records[].verify_url | string or null | The public page, or null with no credential. |
records[].last_synced_at | string | When Warden last heard about this record. ISO 8601 in UTC, with an offset. |
rejected | array | What was refused. |
rejected[].index | integer or null | The record's position in your request. |
rejected[].external_id | string or null | Null when the record had none. |
rejected[].refused | string | record: nothing of it was stored. identity: the record was written and one identity was not. identities: the record was written and its stored identities were left alone. |
rejected[].identity | integer | The identity's position in the record's identities, when refused is identity. |
rejected[].because | string | A sentence for a person. |
With dry_run=1 the response is the one in Dry run. On a plan without the API,
a new record comes back in rejected. See Plans.
Errors
| Status | Code | When |
|---|
| 400 | invalid_request | The body is not {"records": [...]}, is empty, or has more than 500 records, or dry_run is a value Warden does not read. |
| 401 | invalid_key | |
| 429 | rate_limited | |