Create end user
Registers a new end user within your tenant and provisions a Privy-managed wallet for them on the configured chain. Returns immediately (no on-chain transactions). You supply a stable external_id (your own user identifier) and a user_jwt (a partner-minted JWT for that user). This endpoint is Entra token only (Entra token, no user token).
If the external_id already exists and the existing user is not deleted, the server returns 201 with the existing user object — creation is idempotent on external_id.
Headers
Entra M2M access token. Format: Bearer <token>. See Entra authentication.
Must be application/json.
Body
Your stable identifier for this user. 1–128 characters; allowed characters: alphanumeric, -,
_, .. Must be unique within your tenant. Example: alice-bunq-id.
A partner-minted JWT for this user, signed with your RSA-2048 private key. The sub claim must
equal external_id. The iss claim must match your registered JWKS issuer URL. See
User authentication for the full signing spec and key requirements.
Example request
const baseUrl = process.env.YIELDFORCE_API_BASE_URL ?? 'https://yieldforce.io/api';
const res = await fetch(`${baseUrl}/v1/partner/end_users`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${entraToken}`,
},
body: JSON.stringify({
external_id: 'alice-bunq-id',
user_jwt: 'eyJhbGciOiJSUzI1NiIs...',
}),
});
const data = await res.json();Response
201 End user created (or already exists)
{
"id": "usr_01HZ4KXQM5E8WRTYN3P7VBJD6F",
"external_id": "alice-bunq-id",
"tenant_id": "tnt_01HZ4KXQM5ABCDEF12345678",
"tenant_slug": "bunq",
"user_source": "partner",
"wallet_address": "0xabc123...def456",
"created_at": "2026-05-20T10:00:00.000Z"
}The user_jwt you supply here is also the X-User-Token for user-scoped endpoints
The JWT you pass in the body during creation is the same credential format used in the X-User-Token header for all user-scoped endpoints (portfolios, deposit, withdraw, etc.). You may generate a fresh JWT at request time — the key requirement is that sub always matches the external_id in the URL.
Errors
400 validation_error — external_id contains invalid characters, exceeds 128 chars, or user_jwt is missing. Check the detail field for the specific validation failure.
400 external_id_jwt_sub_mismatch — The external_id in the request body does not match the sub claim in user_jwt. Ensure both values are identical.
401 token_missing — No Authorization: Bearer header on the request.
401 invalid_entra_token — Token is expired, malformed, or has an unexpected audience.
422 jwt_invalid — The user_jwt could not be verified. Ensure the JWT is signed with your registered RSA private key and that iss, aud, and sub claims are correct.