warden

API reference

Sync entitlements

Create or update up to 500 entitlement records in one request, idempotent on external_id.

POST/api/v1/integration/entitlements

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_run1 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

FieldType
recordsarrayRequired. 1 to 500 records. The body has no other field.

A record

FieldType
external_idstringRequired. Up to 200 characters.
statusstringRequired. Up to 200 characters. Your own coarse word, such as active, lapsed, revoked or withdrawn. Never interpreted and never shown outside your organization.
normalized_statestringRequired. active, inactive or unknown.
tierstring or nullUp to 200 characters.
capabilitiesarray of stringFrom a closed list: physical_sales.
effective_fromstring or nullISO 8601.
expires_atstring or nullISO 8601.
credentialobject or nullCreates the public page.
identitiesarrayAt most 50. The full set your system vouches for. [] withdraws every identity you supplied. Omit to leave them as they are.

credential

FieldType
holder_namestringRequired. Up to 200 characters. Public. Not an email address.
titlestring or nullUp to 80 characters.
registration_idstring or nullUp to 64 characters.
registered_atstring or nullISO 8601.
publish_termsbooleanFalse by default. Stored, and the public page draws nothing from it.
retiredbooleanFalse by default.

An identity

FieldType
sourcestringRequired. Up to 80 characters. Warden lowercases it.
handlestring or nullUp to 200 characters. Read from url where it can be, for etsy and ebay.
urlstring or nullUp to 600 characters. http or https.
publicbooleanFalse by default.
assurancestringregistered, 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 }]
    }]
  }'

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": []
}
FieldType
recordsarrayThe records that were written, in the order you sent them. A refused record is absent.
records[].public_idstring or nullNull for a record with no credential. Never changes while Warden holds the record.
records[].verify_urlstring or nullThe public page, or null with no credential.
records[].last_synced_atstringWhen Warden last heard about this record. ISO 8601 in UTC, with an offset.
rejectedarrayWhat was refused.
rejected[].indexinteger or nullThe record's position in your request.
rejected[].external_idstring or nullNull when the record had none.
rejected[].refusedstringrecord: 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[].identityintegerThe identity's position in the record's identities, when refused is identity.
rejected[].becausestringA 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

StatusCodeWhen
400invalid_requestThe body is not {"records": [...]}, is empty, or has more than 500 records, or dry_run is a value Warden does not read.
401invalid_key
429rate_limited