Custom Metadata
Gate Identity stores every end-user in a shared Ory Kratos instance. The core identity schema contains only email and locale. For any other data you want to associate with a user — plan, company, phone_number, onboarding_complete, etc. — use the metadata_public field.
metadata_public is a free-form JSON object. Gate enforces no structure on it, so your application controls the schema. In a future release you will be able to register a JSON Schema per tenant to get server-side validation on write.
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /v1/gate/identities/{id}/metadata | Read current metadata |
PATCH | /v1/gate/identities/{id}/metadata | Merge updates into metadata |
Both endpoints require a tenant API key with the gate scope.
Reading Metadata
curl https://api.vernesoft.com/v1/gate/identities/f47ac10b-.../metadata \
-H 'Authorization: Bearer vrn_gate_live_sk_9f8a7...'
{
"metadata_public": {
"plan": "pro",
"company": "Acme Inc",
"onboarding_complete": true
}
}
If no metadata has been set yet, metadata_public is returned as an empty object {}.
Writing Metadata
Send a PATCH with a JSON object. The fields you supply are merged into any existing metadata — keys you omit are left unchanged.
curl -X PATCH https://api.vernesoft.com/v1/gate/identities/f47ac10b-.../metadata \
-H 'Authorization: Bearer vrn_gate_live_sk_9f8a7...' \
-H 'Content-Type: application/json' \
-d '{
"plan": "enterprise",
"seats": 50
}'
{
"metadata_public": {
"plan": "enterprise",
"company": "Acme Inc",
"onboarding_complete": true,
"seats": 50
}
}
Deleting a key
Pass the key with a JSON null value to remove it:
curl -X PATCH https://api.vernesoft.com/v1/gate/identities/f47ac10b-.../metadata \
-H 'Authorization: Bearer vrn_gate_live_sk_9f8a7...' \
-H 'Content-Type: application/json' \
-d '{ "seats": null }'
After this call, seats is no longer present in metadata_public.
Access from the Client
metadata_public is visible to the end-user in their Kratos session. You can surface it in your frontend after a successful login by calling your session introspection endpoint.
const res = await fetch('/v1/gate/tokens/introspect', {
method: 'POST',
headers: {
'Authorization': 'Bearer vrn_gate_live_sk_...',
'Content-Type': 'application/json',
},
body: JSON.stringify({ token: gateToken }),
})
const { identity } = await res.json()
const meta = identity.metadata_public // { plan: 'enterprise', ... }
Important Notes
- Ownership isolation — the internal
verne_tenant_idkey is managed by Gate and cannot be overwritten or deleted. It is stripped from all API responses. - No schema enforcement (yet) — any valid JSON value is accepted. Future releases will support per-tenant JSON Schema validation.
- Size limit — keep
metadata_publicunder 64 KB. Large objects will be rejected by Kratos. - Visibility —
metadata_publicis readable by the identity owner. Do not store sensitive data (passwords, payment details, PII beyond what the user already knows about themselves) in this field. For private server-side data, usemetadata_admin(not yet exposed via Gate API).