Skip to content

Export a user's data

GET
/api/v1/admin/users/{id}/export
Code sample: Shell / cURL
curl --request GET \
--url http://localhost:9090/api/v1/admin/users/1/export \
--header 'Authorization: Bearer <token>'

One JSON document holding what the auth server holds about the user, to answer their request for a copy of their data: the identifiers to search the logs with, and the audit entries that name the user only by subject, email address or its digest; the profile; and the user’s other data as the matching Admin API reads answer it. Nothing secret is in it: no password hash, two-factor secret, recovery code, pending code or token. It leaves out every attribute, the user’s own or a group’s, whose includeInIdToken and includeInAccessToken are both false, since no app receives it; groups and permissions are kept in full. Every list is in id order, oldest first, and is [] when empty, never null. formatVersion goes up only for a change that breaks a reader; a field added to an entry is additive.

The answer is a file to save, named user-<id>-<date>.json in Content-Disposition, the date being exportedAt’s in UTC. It is gzip-compressed (Content-Encoding: gzip) when the request’s Accept-Encoding accepts gzip, and plain JSON otherwise; error answers are never compressed. Like every Admin API answer it is never cached.

The audit events in the document don’t name the other people who acted on the user: an event an administrator made about the user says an administrator made it, without saying who, so the file can be handed to the user as it is. The audit log still names them.

The document holds the user’s audit events, so the route needs a token that reads both users and the audit log: authserver:admin-read, authserver:manage, or authserver:manage-users together with authserver:manage-settings. A token holding authserver:manage-users without authserver:manage-settings is refused INSUFFICIENT_SCOPE.

id
required
integer format: int64

User ID

Accept-Encoding
string

Send gzip to receive the document gzip-compressed.

The user’s document

Media typeapplication/json

What the auth server holds about one user, but for the attributes no app receives. Each entry is the one the matching Admin API read answers, and every list is in id order, oldest first.

object
formatVersion
required

The document’s format, 1.

integer
exportedAt
required
string format: date-time
issuer
required

The auth server’s issuer. A subject identifies the user only together with it.

string
identifiers
required

What the user is known by, to search the logs, and the audit entries that name the user only by subject, email address or its digest.

object
id
required
integer format: int64
subject
required
string
email
required
string
emailDigest
required

The SHA-256 hex digest of the email address, which is how an audit entry about the address records it.

string
user
required
object
id
required
integer format: int64
createdAt
required
string format: date-time
nullable
updatedAt
required
string format: date-time
nullable
enabled
required
boolean
subject
required
string format: uuid
username
required
string
givenName
required
string
middleName
required
string
familyName
required
string
nickname
required
string
website
required
string
gender
required

“female”, “male” or “other”, or empty when unset

string
email
required
string format: email
emailVerified
required
boolean
zoneInfoCountryName
required
string
zoneInfo
required
string
locale
required

The user’s language and region, such as fr-CA, which applications receive as the locale claim, or empty when unset.

string
pageLanguage
required

The language the user chose for Goiabada’s own pages and emails: the tag of one of the auth server’s language catalogs, such as pt-BR, or empty for Automatic, where pages follow the language the application or the browser asks for and emails follow locale.

string
birthDate
required
string format: date-time
nullable
phoneNumberCountryUniqueId
required
string
phoneNumberCountryCallingCode
required
string
phoneNumber
required
string
phoneNumberVerified
required
boolean
addressLine1
required
string
addressLine2
required
string
addressLocality
required
string
addressRegion
required
string
addressPostalCode
required
string
addressCountry
required

ISO 3166-1 alpha-2 country code (e.g. US, BR), or empty string.

string
/^([A-Z]{2})?$/
otpEnabled
required
boolean
otpAuthenticatorDisabled
required

True while the user’s authenticator is disabled because 100 one-time codes in a row were refused. otpEnabled stays true, and every code is refused, the right one included, until two-factor authentication is turned off for the user and they set up a new authenticator. Someone who knew the user’s password, or held one of their sessions, sent those codes, so set a new password (PUT /api/v1/admin/users/{id}/password) before turning two-factor authentication off (PUT /api/v1/admin/users/{id}/otp): otherwise the old password alone signs in.

boolean
attributes
required

The user’s attributes that an app receives: those with includeInIdToken or includeInAccessToken true. One with both false is left out.

Array<object>
object
id
required
integer format: int64
createdAt
required
string format: date-time
nullable
updatedAt
required
string format: date-time
nullable
key
required
string
value
required
string
includeInIdToken
required
boolean
includeInAccessToken
required
boolean
userId
required
integer format: int64
groups
required

The groups the user is a member of, each with the attributes and permissions the user gets through it. A group attribute with includeInIdToken and includeInAccessToken both false is left out.

Array

A group the user is a member of, as GET /api/v1/admin/users/{id}/groups answers it, with the group’s attributes and permissions as the group’s own reads answer them.

object
id
required
integer format: int64
createdAt
required
string format: date-time
nullable
updatedAt
required
string format: date-time
nullable
groupIdentifier
required
string
description
required
string
includeInIdToken
required
boolean
includeInAccessToken
required
boolean
memberCount
required
integer
attributes
required

The group’s attributes that an app receives: those with includeInIdToken or includeInAccessToken true. One with both false is left out.

Array<object>
object
id
required
integer format: int64
createdAt
required
string format: date-time
nullable
updatedAt
required
string format: date-time
nullable
key
required
string
value
required
string
includeInIdToken
required
boolean
includeInAccessToken
required
boolean
groupId
required
integer format: int64
permissions
required
Array<object>
object
id
required
integer format: int64
permissionIdentifier
required
string
description
required
string
resourceId
required
integer format: int64
resource
required
object
id
required
integer format: int64
resourceIdentifier
required
string
description
required
string
isSystemLevelResource
required

True for a resource this server owns and enforces as system level: rename and delete are refused on it with 403. A consumer should disable those controls rather than recompute the rule.

boolean
permissions
required

The permissions granted to the user directly.

Array<object>
object
id
required
integer format: int64
permissionIdentifier
required
string
description
required
string
resourceId
required
integer format: int64
resource
required
object
id
required
integer format: int64
resourceIdentifier
required
string
description
required
string
isSystemLevelResource
required

True for a resource this server owns and enforces as system level: rename and delete are refused on it with 403. A consumer should disable those controls rather than recompute the rule.

boolean
consents
required
Array<object>
object
id
required
integer format: int64
createdAt
required
string format: date-time
nullable
updatedAt
required
string format: date-time
nullable
clientId
required
integer format: int64
userId
required
integer format: int64
scope
required
string
grantedAt
required
string format: date-time
nullable
clientIdentifier
required
string
clientName
required

The name the consent screen shows a user for this client: its display name when an administrator chose to show one, else, for a client that registered itself, the name it registered with, else its identifier.

string
clientNameUnverified
required

Whether clientName is the client’s own claim about itself, the name a self-registered client gave and nobody has replaced, which the consent screen marks as unverified.

boolean
clientDescription
required

The client’s description as stored, on the admin endpoint. The account endpoint, which answers the user, carries it only as the consent screen shows it: when an administrator chose to show it, and never beside an unverified clientName, which is then the description already. Otherwise it is empty there.

string
sessions
required

The user’s live sessions, as GET /api/v1/admin/users/{id}/sessions lists them. isCurrent is false on every one, since the document is the same whoever asks.

Array
object
id
required
integer format: int64
createdAt
required
string format: date-time
nullable
updatedAt
required
string format: date-time
nullable
sessionIdentifier
required
string
started
required
string format: date-time
nullable
lastAccessed
required
string format: date-time
nullable
authMethods
required
string
acrLevel
required
string
authTime
required
string format: date-time
nullable
ipAddress
required
string
deviceName
required
string
deviceType
required
string
deviceOS
required
string
userAgent
required
string
userId
required
integer format: int64
isCurrent
required
boolean
clientIdentifiers
required
Array<string>
clients
required

The same clients as clientIdentifiers, in the same order, each with the name its user is shown for it.

Array<object>

One client a session authorized.

object
clientIdentifier
required
string
name
required

The name the consent screen shows a user for this client: its display name when an administrator chose to show one, else, for a client that registered itself, the name it registered with, else its identifier.

string
nameUnverified
required

Whether name is the client’s own claim about itself, the name a self-registered client gave and nobody has replaced, which the consent screen marks as unverified.

boolean
refreshTokens
required

Every refresh token the auth server holds for the user, from a sign-in to an app or a password grant, rotated-out and revoked ones included, until they expire and are deleted.

Array<object>

A refresh token the auth server holds for the user, with the sign-in it came from. The token itself is never stored, so it is not here.

object
clientIdentifier
required
string
clientName
required

The app’s name, as the consent screen shows it.

string
clientNameUnverified
required

True when clientName is the app’s own claim about itself.

boolean
scope
required
string
type
required

Refresh for a token bound to a session, Offline for one that outlives it.

string
Allowed values: Refresh Offline
issuedAt
required
string format: date-time
nullable
expiresAt
required
string format: date-time
nullable
maxLifetime
required

When an Offline token stops being renewable; null on a Refresh token.

string format: date-time
nullable
sessionIdentifier
required

The session a Refresh token is bound to; empty on an Offline token.

string
jti
required

The token’s id, which the audit events name as refresh_token_jti.

string
revoked
required

True when the token, the sign-in it came from or its rotation family is revoked.

boolean
ipAddress
required

The IP address of the sign-in the token came from; empty for a password-grant token.

string
userAgent
required

The browser of the sign-in the token came from; empty for a password-grant token.

string
authenticatedAt
required

When the user signed in: at the sign-in the token came from, or, for a password-grant token, when the password was checked. A rotated token keeps it, so it can be earlier than issuedAt. Null when no authentication time is stored.

string format: date-time
nullable
legalDocumentAcceptances
required
Array<object>
object
id
required
integer format: int64
acceptedAt
required
string format: date-time
nullable
legalDocumentId
required
integer format: int64
shortName
required
string
version
required

The number of the version accepted.

integer
title
required

The accepted version’s title.

string
publishedAt
required
string format: date-time
nullable
retired
required

Whether the document is retired now.

boolean
url
required

The absolute URL of the version’s public page, /legal//versions/, or null when the document is retired.

string
nullable
profilePicture
required

The user’s profile picture, or null when the user has none.

object
contentType
required

The image’s media type, such as image/png.

string
data
required

The image, in base64.

string format: byte
auditEvents
required

Every audit event about the user or made by them. An event another user made about the user, such as an administrator’s change, does not say who made it.

Array

An audit event in the user export: the entry GET /api/v1/admin/audit-logs answers, plus actedByAdministrator. When another user’s token made the event about the user, as an administrator’s does on the Admin API, actedByAdministrator is true, loggedInUserId is null and details carries no logged_in_user. A cross_user_session_replaced event carries no previous_user_id. An event the user made keeps the users, groups and clients it names, and an event made by a client credentials token keeps the client.

object
id
required
integer format: int64
createdAt
required
string format: date-time
auditEvent
required
string
details
required

The event payload, as a JSON string

string
requestId
required

The request’s id as the application log carries it, so the same value appears in the log’s request_id attribute. Empty when the entry was not written on a request.

string
userId
required

The row id of the user the entry is about, the user_id in its details. Null when it is about no user.

integer format: int64
nullable
loggedInUserId
required

The row id of the user whose access token made the request: the administrator on the Admin API, the user themselves on the Account API. Null when no user’s token made it, as on a sign-in in the browser or a call with a client credentials token.

integer format: int64
nullable
actedByAdministrator
required

True when another user’s token made the event about the user, which the export does not name.

boolean

Example

{
"refreshTokens": [
{
"type": "Refresh"
}
]
}
Content-Disposition
string

attachment; filename="user-<id>-<date>.json", the date in UTC.

Content-Encoding
string

gzip when the request accepted gzip; absent otherwise.

Vary
string

Accept-Encoding.

Invalid request body or parameters

Media typeapplication/json

Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.

object
error_code

Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for codes named after the sentence’s catalog key (e.g. validator.email.required). Never translated, whatever the request’s language.

string
error_description
required

A sentence for people to read: in the request’s language, from the ui_locales query parameter or else the Accept-Language header, when the server has the sentence in that language, and in English otherwise. Route on error_code, not on this text.

string

Example generated

{
"error_code": "example",
"error_description": "example"
}
WWW-Authenticate
string

Bearer challenge when token transport is malformed; ordinary validation errors omit it.

Missing or invalid access token (ACCESS_TOKEN_REQUIRED, INVALID_TOKEN), or a refused DPoP proof (INVALID_DPOP_PROOF)

Media typeapplication/json

Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.

object
error_code

Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for codes named after the sentence’s catalog key (e.g. validator.email.required). Never translated, whatever the request’s language.

string
error_description
required

A sentence for people to read: in the request’s language, from the ui_locales query parameter or else the Accept-Language header, when the server has the sentence in that language, and in English otherwise. Route on error_code, not on this text.

string

Example generated

{
"error_code": "example",
"error_description": "example"
}
WWW-Authenticate
string

A Bearer challenge, then a DPoP challenge naming the accepted proof algorithms, on token refusals, the error in the challenge of the scheme the token was sent with: Bearer realm="goiabada", error="invalid_token", error_description="...", DPoP realm="goiabada", algs="ES256 ...". An operation may also return a handler-level 401 without this header.

The token is valid but does not authorise this request. A caller tells the refusals apart by error_code.

INSUFFICIENT_SCOPE comes from the route’s authorisation middleware, before the handler runs: an Admin operation needs one of the scopes its route names, and an Account operation needs authserver:manage-account.

USER_CONTEXT_REQUIRED comes from the same middleware on the Account operations, which also require the token to have been issued for a user: one obtained through the client credentials grant carries no auth_time claim and is refused here.

FORBIDDEN comes from the handler, on the account endpoints that resolve a resource by id and then check it belongs to the caller, so a valid token for the wrong user reaches this rather than a 404.

CLIENT_NOT_ALLOWED comes from the route on the two Account operations only the admin console’s own client may call, deleteAccount and exportAccount. ACCOUNT_DELETION_DISABLED comes from deleteAccount while an administrator has turned off Let users delete their own account.

MANAGE_SCOPE_REQUIRED comes from the handler, on the Admin operations the administrative policy guards. Only authserver:manage creates an administrator, changes one, or changes what reaches one, so no granular scope will ever be enough: the remedy is a token holding authserver:manage, not requesting the route’s scope as for INSUFFICIENT_SCOPE. An administrator is a user, group or client holding any of the six administrative permissions (manage, admin-read, manage-users, manage-clients, manage-settings, browser-sessions), a user directly or through any of its groups, the admin console’s own client whatever it holds, and a client allowed to request the administrative scopes. A granular scope is refused here when it:

  • grants or revokes an administrative permission, directly or by moving a user into or out of a group that holds one, or deletes such a group;
  • writes to an administrator user (profile, credentials, enabled, sessions, consents, attributes, memberships, permissions, deletion), an administrative group (settings, attributes, members, permissions, deletion), or an administrator client (settings, authentication, flows, redirect URIs, sign-out redirect URIs, back-channel logout, DPoP, web origins, token settings, permissions, introspection resources, logo, deletion);
  • switches whether a client may request the administrative scopes, on or off, on any client;
  • adds the authserver resource to a client’s introspection resources;
  • reads an administrator client’s secret, or reads or sets the secret of a client listed for the authserver resource among its introspection resources;
  • sets or changes a client’s back-channel logout URI;
  • changes the email or the audit-log settings;
  • changes an administrative permission’s description. Granular scopes still read administrators. The refusal is answered after the request’s 400 and 404, writes nothing, carries the insufficient_scope challenge of the scheme the token was sent with, such as WWW-Authenticate: Bearer realm="goiabada", error="insufficient_scope", error_description="...", scope="authserver:manage", and leaves an administrator_change_refused audit record.
Media typeapplication/json

Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.

object
error_code

Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for codes named after the sentence’s catalog key (e.g. validator.email.required). Never translated, whatever the request’s language.

string
error_description
required

A sentence for people to read: in the request’s language, from the ui_locales query parameter or else the Accept-Language header, when the server has the sentence in that language, and in English otherwise. Route on error_code, not on this text.

string

Example generated

{
"error_code": "example",
"error_description": "example"
}
WWW-Authenticate
string

An insufficient_scope challenge in the scheme the token was sent with, Bearer or DPoP, on every refusal but FORBIDDEN and ACCOUNT_DELETION_DISABLED, which omit it.

Resource not found

Media typeapplication/json

Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.

object
error_code

Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for codes named after the sentence’s catalog key (e.g. validator.email.required). Never translated, whatever the request’s language.

string
error_description
required

A sentence for people to read: in the request’s language, from the ui_locales query parameter or else the Accept-Language header, when the server has the sentence in that language, and in English otherwise. Route on error_code, not on this text.

string

Example generated

{
"error_code": "example",
"error_description": "example"
}

The request failed inside the server, most often a storage error. error_code is INTERNAL_SERVER_ERROR: no detail about the failure, only the request id an operator can find the log line by, and retrying is reasonable. Key rotation’s 500 also answers KEY_SET_INCOMPLETE, which names its cause and no retry clears.

Media typeapplication/json

Admin/account API error envelope. Routing by HTTP status code: 4xx is a client-correctable failure (validation, not found, permission denied, rate limited); 5xx is a server-side problem. The body provides a stable error_code and an error_description for people to read. Protocol endpoints (/auth/token, /auth/authorize, /connect/register, /userinfo) use their RFC-defined error envelopes instead of this one.

object
error_code

Stable identifier for the failure. UPPER_SNAKE for legacy codes (e.g. VALIDATION_ERROR), dotted lowercase for codes named after the sentence’s catalog key (e.g. validator.email.required). Never translated, whatever the request’s language.

string
error_description
required

A sentence for people to read: in the request’s language, from the ui_locales query parameter or else the Accept-Language header, when the server has the sentence in that language, and in English otherwise. Route on error_code, not on this text.

string

Example generated

{
"error_code": "example",
"error_description": "example"
}