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

MethodPathDescription
GET/v1/gate/identities/{id}/metadataRead current metadata
PATCH/v1/gate/identities/{id}/metadataMerge 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_id key 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_public under 64 KB. Large objects will be rejected by Kratos.
  • Visibilitymetadata_public is 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, use metadata_admin (not yet exposed via Gate API).