# Export KINTRA_API for your environment first; the base URL is on the introduction page.
KEY="YOUR_TENANT_KEY_ID"
SECRET="YOUR_SIGNING_SECRET"
# The signature covers the path and query exactly as sent, so both are split
# off the base URL and reused for the request line below.
API_PATH="/${KINTRA_API#*://*/}"
API_HOST="${KINTRA_API%"$API_PATH"}"
METHOD="POST"
PATH_AND_QUERY="$API_PATH/gateway/customers"
# One compact line, signed and sent unchanged. The server signs a
# re-serialization of the body it parsed, so reformatting this fails with a 401.
BODY='{"email":"YOUR_EMAIL"}'
TIMESTAMP="$(date +%s)"
SIGNATURE="$(printf '%s' "$TIMESTAMP$METHOD$PATH_AND_QUERY$BODY" \
| openssl dgst -sha256 -hmac "$SECRET" | awk '{print $NF}')"
curl -sS -w '\n%{http_code}' -X "$METHOD" "$API_HOST$PATH_AND_QUERY" \
-H "X-Tenant-Key: $KEY" \
-H "X-Tenant-Timestamp: $TIMESTAMP" \
-H "X-Tenant-Signature: $SIGNATURE" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: YOUR_IDEMPOTENCY_KEY" \
--data-binary "$BODY"
const options = {
method: 'POST',
headers: {
'X-Tenant-Signature': '<x-tenant-signature>',
'X-Tenant-Timestamp': '<x-tenant-timestamp>',
'X-Idempotency-Key': '<x-idempotency-key>',
'x-tenant-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: '<string>',
attributes: {},
cohort: {club_ids: ['<string>'], country_id: '<string>', metadata: {}},
first_name: '<string>',
last_name: '<string>'
})
};
fetch('https://api.kintra.io/api/v1/gateway/customers', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.kintra.io/api/v1/gateway/customers"
payload = {
"email": "<string>",
"attributes": {},
"cohort": {
"club_ids": ["<string>"],
"country_id": "<string>",
"metadata": {}
},
"first_name": "<string>",
"last_name": "<string>"
}
headers = {
"X-Tenant-Signature": "<x-tenant-signature>",
"X-Tenant-Timestamp": "<x-tenant-timestamp>",
"X-Idempotency-Key": "<x-idempotency-key>",
"x-tenant-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"success": true,
"data": {
"auth_provider": "<string>",
"auth_provider_id": "<string>",
"email": "<string>",
"id": "<string>",
"status": "<string>",
"username": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"first_name": "<string>",
"internal_wallets": [
{
"address": "<string>",
"id": "<string>",
"user_id": "<string>",
"wallet_kind": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z",
"label": "<string>",
"updated_at": "2023-11-07T05:31:56Z"
}
],
"last_name": "<string>",
"updated_at": "2023-11-07T05:31:56Z"
},
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}{
"success": true,
"data": {
"auth_provider": "<string>",
"auth_provider_id": "<string>",
"email": "<string>",
"id": "<string>",
"status": "<string>",
"username": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"first_name": "<string>",
"internal_wallets": [
{
"address": "<string>",
"id": "<string>",
"user_id": "<string>",
"wallet_kind": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z",
"label": "<string>",
"updated_at": "2023-11-07T05:31:56Z"
}
],
"last_name": "<string>",
"updated_at": "2023-11-07T05:31:56Z"
},
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}{
"success": true,
"data": null,
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}{
"success": true,
"data": null,
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}{
"success": true,
"data": null,
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}{
"success": true,
"data": null,
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}Create a customer
Registers a customer under your tenant. email is required; first_name, last_name, attributes and a cohort holding country_id, club_ids and metadata are optional. Call it once per person, at signup or when importing an account you already hold. The response data carries the created customer, including its id, username, status and onboarding_status; keep the id, because every other customer route takes it. An email address already registered under the tenant returns 409. X-Idempotency-Key is required: a missing key returns 400 IDEMPOTENCY_KEY_REQUIRED, and a replay returns the stored response instead of creating a second record. Reusing a key with a different request returns 422 IDEMPOTENCY_KEY_CONFLICT, and replaying a key whose first request is still in flight returns 409 with the same code. A first request that never recorded a response keeps returning 409 until the key ages out, so send a fresh key rather than retrying that one.
# Export KINTRA_API for your environment first; the base URL is on the introduction page.
KEY="YOUR_TENANT_KEY_ID"
SECRET="YOUR_SIGNING_SECRET"
# The signature covers the path and query exactly as sent, so both are split
# off the base URL and reused for the request line below.
API_PATH="/${KINTRA_API#*://*/}"
API_HOST="${KINTRA_API%"$API_PATH"}"
METHOD="POST"
PATH_AND_QUERY="$API_PATH/gateway/customers"
# One compact line, signed and sent unchanged. The server signs a
# re-serialization of the body it parsed, so reformatting this fails with a 401.
BODY='{"email":"YOUR_EMAIL"}'
TIMESTAMP="$(date +%s)"
SIGNATURE="$(printf '%s' "$TIMESTAMP$METHOD$PATH_AND_QUERY$BODY" \
| openssl dgst -sha256 -hmac "$SECRET" | awk '{print $NF}')"
curl -sS -w '\n%{http_code}' -X "$METHOD" "$API_HOST$PATH_AND_QUERY" \
-H "X-Tenant-Key: $KEY" \
-H "X-Tenant-Timestamp: $TIMESTAMP" \
-H "X-Tenant-Signature: $SIGNATURE" \
-H "Content-Type: application/json" \
-H "X-Idempotency-Key: YOUR_IDEMPOTENCY_KEY" \
--data-binary "$BODY"
const options = {
method: 'POST',
headers: {
'X-Tenant-Signature': '<x-tenant-signature>',
'X-Tenant-Timestamp': '<x-tenant-timestamp>',
'X-Idempotency-Key': '<x-idempotency-key>',
'x-tenant-key': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: '<string>',
attributes: {},
cohort: {club_ids: ['<string>'], country_id: '<string>', metadata: {}},
first_name: '<string>',
last_name: '<string>'
})
};
fetch('https://api.kintra.io/api/v1/gateway/customers', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.kintra.io/api/v1/gateway/customers"
payload = {
"email": "<string>",
"attributes": {},
"cohort": {
"club_ids": ["<string>"],
"country_id": "<string>",
"metadata": {}
},
"first_name": "<string>",
"last_name": "<string>"
}
headers = {
"X-Tenant-Signature": "<x-tenant-signature>",
"X-Tenant-Timestamp": "<x-tenant-timestamp>",
"X-Idempotency-Key": "<x-idempotency-key>",
"x-tenant-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"success": true,
"data": {
"auth_provider": "<string>",
"auth_provider_id": "<string>",
"email": "<string>",
"id": "<string>",
"status": "<string>",
"username": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"first_name": "<string>",
"internal_wallets": [
{
"address": "<string>",
"id": "<string>",
"user_id": "<string>",
"wallet_kind": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z",
"label": "<string>",
"updated_at": "2023-11-07T05:31:56Z"
}
],
"last_name": "<string>",
"updated_at": "2023-11-07T05:31:56Z"
},
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}{
"success": true,
"data": {
"auth_provider": "<string>",
"auth_provider_id": "<string>",
"email": "<string>",
"id": "<string>",
"status": "<string>",
"username": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"first_name": "<string>",
"internal_wallets": [
{
"address": "<string>",
"id": "<string>",
"user_id": "<string>",
"wallet_kind": "<string>",
"created_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z",
"label": "<string>",
"updated_at": "2023-11-07T05:31:56Z"
}
],
"last_name": "<string>",
"updated_at": "2023-11-07T05:31:56Z"
},
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}{
"success": true,
"data": null,
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}{
"success": true,
"data": null,
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}{
"success": true,
"data": null,
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}{
"success": true,
"data": null,
"errors": [
{
"message": "<string>",
"path": "<string>"
}
],
"message": "<string>"
}Authorizations
Tenant API key
Headers
Hex HMAC-SHA256 of the timestamp, the uppercase method, the url as sent and the request body, keyed by the signing secret.
Unix seconds. Checked before the signature.
Unique key for this write. A replay returns the stored response; the same key with a different body conflicts.
Body
Optional initial attribute values, keyed by definition id. Mirrors the PUT attributes body.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Optional human first name. Captured on the tenant Add User form.
Optional human last name. Captured on the tenant Add User form.

