Download own data
curl --request GET \ --url http://localhost:9090/api/v1/account/export \ --header 'Authorization: Bearer <token>'The authenticated user’s own data, as one JSON document: the same document, headers and
file name as an administrator’s export of that user,
GET /api/v1/admin/users/{id}/export.
Only a token issued to the admin console’s own client may call this. Any other client’s
token is refused with 403 (CLIENT_NOT_ALLOWED), whatever its scopes and however recent
its sign-in, and the WWW-Authenticate header says error="insufficient_scope".
The token’s sign-in must be at most 300 seconds old, by its auth_time, and at
urn:goiabada:level2_optional or above, by its acr: with the user’s authenticator code,
when they have one. A refreshed token keeps the auth_time of the sign-in it came from. An
older or weaker sign-in is refused with 401 (INSUFFICIENT_USER_AUTHENTICATION) and RFC
9470’s step-up challenge, WWW-Authenticate: Bearer realm="goiabada", error="insufficient_user_authentication", error_description="...", acr_values="urn:goiabada:level2_optional", max_age="300", DPoP realm="goiabada", algs="ES256 ...". Sign the user in again, with prompt=login and those acr_values, and
retry with the new token.
Each download counts against the account_export rate limit, 5 per hour for each user; a
request refused by the client or the sign-in check spends nothing.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”Send gzip to receive the document gzip-compressed.
Responses
Section titled “Responses”The user’s document
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
The document’s format, 1.
The auth server’s issuer. A subject identifies the user only together with it.
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
The SHA-256 hex digest of the email address, which is how an audit entry about the address records it.
object
“female”, “male” or “other”, or empty when unset
The user’s language and region, such as fr-CA, which applications receive as the locale claim, or empty when unset.
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.
ISO 3166-1 alpha-2 country code (e.g. US, BR), or empty string.
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.
The user’s attributes that an app receives: those with includeInIdToken or
includeInAccessToken true. One with both false is left out.
object
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.
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
The group’s attributes that an app receives: those with includeInIdToken or
includeInAccessToken true. One with both false is left out.
object
object
object
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.
The permissions granted to the user directly.
object
object
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.
object
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.
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.
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.
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.
object
The same clients as clientIdentifiers, in the same order, each with the name its user is shown for it.
One client a session authorized.
object
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.
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.
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.
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
The app’s name, as the consent screen shows it.
True when clientName is the app’s own claim about itself.
Refresh for a token bound to a session, Offline for one that outlives it.
When an Offline token stops being renewable; null on a Refresh token.
The session a Refresh token is bound to; empty on an Offline token.
The token’s id, which the audit events name as refresh_token_jti.
True when the token, the sign-in it came from or its rotation family is revoked.
The IP address of the sign-in the token came from; empty for a password-grant token.
The browser of the sign-in the token came from; empty for a password-grant token.
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.
object
The number of the version accepted.
The accepted version’s title.
Whether the document is retired now.
The absolute URL of the version’s public page, /legal/
The user’s profile picture, or null when the user has none.
object
The image’s media type, such as image/png.
The image, in base64.
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.
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
The event payload, as a JSON string
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.
The row id of the user the entry is about, the user_id in its details.
Null when it is about no user.
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.
True when another user’s token made the event about the user, which the export does not name.
Example
{ "refreshTokens": [ { "type": "Refresh" } ]}Headers
Section titled “Headers”attachment; filename="user-<id>-<date>.json", the date in UTC.
gzip when the request accepted gzip; absent otherwise.
Accept-Encoding.
Missing or invalid access token (ACCESS_TOKEN_REQUIRED, INVALID_TOKEN), a refused
DPoP proof (INVALID_DPOP_PROOF), or a sign-in older than 300 seconds or below
urn:goiabada:level2_optional (INSUFFICIENT_USER_AUTHENTICATION), whose challenge
names the acr_values and max_age a new sign-in must meet.
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
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.
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.
Example generated
{ "error_code": "example", "error_description": "example"}Headers
Section titled “Headers”A Bearer challenge, then a DPoP challenge naming the accepted proof algorithms, the
error in the challenge of the scheme the token was sent with. For
INSUFFICIENT_USER_AUTHENTICATION it is error="insufficient_user_authentication"
with acr_values="urn:goiabada:level2_optional" and max_age="300".
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
authserverresource to a client’s introspection resources; - reads an administrator client’s secret, or reads or sets the
secret of a client listed for the
authserverresource 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 anadministrator_change_refusedaudit record.
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
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.
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.
Example generated
{ "error_code": "example", "error_description": "example"}Headers
Section titled “Headers”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
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
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.
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.
Example generated
{ "error_code": "example", "error_description": "example"}Rate limit reached. Every limit on the account API is counted by the token’s user and applies whether or not the rate limiter (GOIABADA_AUTHSERVER_RATELIMITER_ENABLED) is on. error_code is TOO_MANY_REQUESTS and a Retry-After header carries the window length in seconds.
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
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.
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.
Example generated
{ "error_code": "example", "error_description": "example"}Headers
Section titled “Headers”Seconds to wait before retrying
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.
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
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.
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.
Example generated
{ "error_code": "example", "error_description": "example"}