{"openapi":"3.0.3","info":{"title":"@faablecloud/auth","description":"Auth Platform made by Faable. Manage Users and Roles","version":"1.19.0","license":{"name":"private","url":"https://faable.com/docs/platform/privacy-policy"},"termsOfService":"https://faable.com/docs/platform/terms-of-service"},"components":{"securitySchemes":{"apikey":{"type":"apiKey","in":"query","name":"api_key"},"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"},"faableauth":{"type":"oauth2","flows":{"authorizationCode":{"authorizationUrl":"http://localhost:4500/authorize","tokenUrl":"http://localhost:4500/oauth/token","scopes":{"base":"openid profile email offline_access"}}}}},"schemas":{"AuthAccount":{"type":"object","required":["id","name","domain","slug","callback_hostnames","token_signature","token_signing_alg","enabled_locales","notification_settings","createdAt"],"properties":{"id":{"type":"string","description":"AuthAccount ID"},"name":{"type":"string"},"domain":{"type":"string"},"slug":{"type":"string"},"logo_src":{"type":"string","nullable":true},"icon_src":{"type":"string","nullable":true},"callback_hostnames":{"type":"array","items":{"type":"string"}},"token_signature":{"type":"string","description":"Shared HMAC secret. Used when token_signing_alg is an HS* algorithm; ignored for RS*/ES*/PS*."},"token_signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign tokens issued by this Account. Today only RS256 is implemented."},"default_connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"enabled_locales":{"type":"array","items":{"type":"string"}},"team":{"type":"string","nullable":true},"notification_settings":{"type":"object","required":["welcome_email_enabled","verify_email_auto_send"],"properties":{"welcome_email_enabled":{"type":"boolean","description":"Send the built-in welcome email on user.created","default":false},"verify_email_auto_send":{"type":"boolean","description":"Send a verification email automatically when a user is created with `email_verified=false` and an email address. The link in the email lands on `GET /verify-email?ticket=...` and flips `email_verified=true` with `email_verified_method=verification_flow`. When `false`, verification emails must be requested explicitly via `POST /user/:id/verify-email/start`.","default":false}},"additionalProperties":false},"email_change_verification_mode":{"anyOf":[{"type":"string","enum":["new_only"]},{"type":"string","enum":["old_and_new"]}],"description":"Policy for the user email-change flow. `new_only` (default) sends a single confirmation link to the new email. `old_and_new` requires the user to also click a link sent to the previous email before the swap takes effect — stricter, useful for tenants with higher-risk users."},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Controls what happens to `user.email` on subsequent OAuth/federated logins when the user previously changed their email manually through this auth server (i.e. `user.email_change_locked_at` is set).\n\n- `preserve_manual` (default): the manually-set email wins. The federated provider's email is ignored on re-sync; `email` and `email_verified` are not touched. The identity link stays valid via `provider_user_id`, so the user can still log in with Google/etc.\n- `always_sync`: the federated provider's email is always written back, overwriting any manual change. Useful for tenants whose source of truth for identity is the IdP (corporate SSO, etc.)."},"createdAt":{"type":"string","description":"AuthAccount creation date"},"updatedAt":{"type":"string","description":"AuthAccount updated date"}},"description":"AuthAccount"},"TokenSigningAlg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign tokens issued by this Account. Today only RS256 is implemented."},"AccountNotificationSettings":{"type":"object","required":["welcome_email_enabled","verify_email_auto_send"],"properties":{"welcome_email_enabled":{"type":"boolean","description":"Send the built-in welcome email on user.created","default":false},"verify_email_auto_send":{"type":"boolean","description":"Send a verification email automatically when a user is created with `email_verified=false` and an email address. The link in the email lands on `GET /verify-email?ticket=...` and flips `email_verified=true` with `email_verified_method=verification_flow`. When `false`, verification emails must be requested explicitly via `POST /user/:id/verify-email/start`.","default":false}},"additionalProperties":false},"EmailChangeVerificationMode":{"anyOf":[{"type":"string","enum":["new_only"]},{"type":"string","enum":["old_and_new"]}],"description":"Policy for the user email-change flow. `new_only` (default) sends a single confirmation link to the new email. `old_and_new` requires the user to also click a link sent to the previous email before the swap takes effect — stricter, useful for tenants with higher-risk users."},"Connection":{"type":"object","required":["id","connection_name","connection_type","authorize_url","token_url","userinfo_url","client_id","client_secret","issuer","jwks_url","response_type","enabled","enabled_clients","scope","authorize_params","is_using_default_credentials","account","createdAt"],"properties":{"id":{"type":"string","description":"Connection ID"},"connection_name":{"type":"string"},"connection_type":{"enum":["database","custom","github","figma","google_oauth2","oidc","passwordless_email"]},"authorize_url":{"type":"string","default":null},"token_url":{"type":"string","default":null},"userinfo_url":{"type":"string","default":null},"client_id":{"type":"string","default":null},"client_secret":{"type":"string","default":null},"issuer":{"type":"string","default":null},"jwks_url":{"type":"string","default":null},"response_type":{"type":"string","default":null},"enabled":{"type":"boolean"},"enabled_clients":{"type":"array","items":{"type":"string"},"default":null,"nullable":true},"scope":{"type":"array","items":{"type":"string"},"default":[]},"authorize_params":{"type":"object","description":"Authorize params","default":{},"additionalProperties":{"type":"string"}},"claims_mapping":{"type":"object","additionalProperties":{"type":"string"}},"is_using_default_credentials":{"type":"boolean","readOnly":true,"description":"Derived: true when the connection_type has shared Faable defaults AND the tenant has not set its own client_id/client_secret. Read-only — set by the server on every read."},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Per-connection override of `Account.email_oauth_sync_policy`. When set on a Connection, takes precedence over the Account-level setting for logins through this IdP. When unset (default), the Account-level policy applies. Use this to allow `always_sync` for a trusted IdP (e.g. corporate SSO) while keeping `preserve_manual` for others within the same tenant."},"password_policy":{"type":"object","required":["level"],"properties":{"level":{"anyOf":[{"type":"string","enum":["none"]},{"type":"string","enum":["low"]},{"type":"string","enum":["fair"]},{"type":"string","enum":["good"]},{"type":"string","enum":["excellent"]}]},"min_length":{"type":"integer","minimum":1,"maximum":128},"require_lowercase":{"type":"boolean"},"require_uppercase":{"type":"boolean"},"require_number":{"type":"boolean"},"require_special":{"type":"boolean"}},"description":"Password policy enforced when writing a password through this database connection (password reset and admin set-password). `level` is an Auth0-style preset (none/low/fair/good/excellent); the dashboard expands it into the explicit rule fields when saving. The rule fields override the preset baseline. When unset on the connection, the server applies the `good` default. Does not affect login."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ConnectionMetadata","default":{}},"createdAt":{"type":"string","description":"Connection creation date"},"updatedAt":{"type":"string","description":"Connection updated date"}},"description":"Connection"},"ConnectionMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ConnectionMetadata","default":{}},"ConnectionCreate":{"type":"object","required":["connection_name","connection_type"],"properties":{"connection_name":{"type":"string"},"connection_type":{"enum":["database","custom","github","figma","google_oauth2","oidc","passwordless_email"]},"authorize_url":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"issuer":{"type":"string"},"jwks_url":{"type":"string"},"scope":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"claims_mapping":{"type":"object","additionalProperties":{"type":"string"}},"authorize_params":{"type":"object","description":"Authorize params","default":{},"additionalProperties":{"type":"string"}},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Controls what happens to `user.email` on subsequent OAuth/federated logins when the user previously changed their email manually through this auth server (i.e. `user.email_change_locked_at` is set).\n\n- `preserve_manual` (default): the manually-set email wins. The federated provider's email is ignored on re-sync; `email` and `email_verified` are not touched. The identity link stays valid via `provider_user_id`, so the user can still log in with Google/etc.\n- `always_sync`: the federated provider's email is always written back, overwriting any manual change. Useful for tenants whose source of truth for identity is the IdP (corporate SSO, etc.)."},"password_policy":{"type":"object","required":["level"],"properties":{"level":{"anyOf":[{"type":"string","enum":["none"]},{"type":"string","enum":["low"]},{"type":"string","enum":["fair"]},{"type":"string","enum":["good"]},{"type":"string","enum":["excellent"]}]},"min_length":{"type":"integer","minimum":1,"maximum":128},"require_lowercase":{"type":"boolean"},"require_uppercase":{"type":"boolean"},"require_number":{"type":"boolean"},"require_special":{"type":"boolean"}},"description":"Password policy enforced when writing a password through this database connection (password reset and admin set-password). `level` is an Auth0-style preset (none/low/fair/good/excellent); the dashboard expands it into the explicit rule fields when saving. The rule fields override the preset baseline. When unset on the connection, the server applies the `good` default. Does not affect login."},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"ConnectionCreate","additionalProperties":false},"ConnectionMetadataCreate":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"},"ConnectionUpdate":{"type":"object","properties":{"connection_name":{"type":"string"},"enabled":{"type":"boolean"},"enabled_clients":{"type":"array","items":{"type":"string"}},"scope":{"type":"array","items":{"type":"string"}},"client_id":{"type":"string"},"client_secret":{"type":"string"},"issuer":{"type":"string"},"authorize_url":{"type":"string"},"token_url":{"type":"string"},"userinfo_url":{"type":"string"},"jwks_url":{"type":"string"},"response_type":{"type":"string"},"authorize_params":{"type":"object","description":"Authorize params","default":{},"additionalProperties":{"type":"string"}},"claims_mapping":{"type":"object","additionalProperties":{"type":"string"}},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]},{"type":"null"}]},"password_policy":{"anyOf":[{"type":"object","required":["level"],"properties":{"level":{"anyOf":[{"type":"string","enum":["none"]},{"type":"string","enum":["low"]},{"type":"string","enum":["fair"]},{"type":"string","enum":["good"]},{"type":"string","enum":["excellent"]}]},"min_length":{"type":"integer","minimum":1,"maximum":128},"require_lowercase":{"type":"boolean"},"require_uppercase":{"type":"boolean"},"require_number":{"type":"boolean"},"require_special":{"type":"boolean"}},"description":"Password policy enforced when writing a password through this database connection (password reset and admin set-password). `level` is an Auth0-style preset (none/low/fair/good/excellent); the dashboard expands it into the explicit rule fields when saving. The rule fields override the preset baseline. When unset on the connection, the server applies the `good` default. Does not affect login."},{"type":"null"}]}},"description":"Partial update for a Connection. Only the supplied fields are modified. `connection_type` is intentionally excluded — changing it would orphan every identity already linked to this connection.","additionalProperties":false},"Client":{"type":"object","required":["id","name","description","client_id","client_secret","callbacks","logout_urls","refresh_token","account","createdAt"],"properties":{"id":{"type":"string","description":"Client ID"},"name":{"type":"string"},"description":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"callbacks":{"type":"array","items":{"type":"string"}},"logout_urls":{"type":"array","items":{"type":"string"}},"refresh_token":{"type":"object","required":["expiration_mode","infinite_token_lifetime","token_lifetime"],"properties":{"expiration_mode":{"enum":["expire","not-expire"]},"infinite_token_lifetime":{"type":"boolean"},"token_lifetime":{"type":"number"}}},"client_uri":{"type":"string","nullable":true},"logo_uri":{"type":"string","nullable":true},"tos_uri":{"type":"string","nullable":true},"policy_uri":{"type":"string","nullable":true},"contacts":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"application_type":{"type":"string"},"software_id":{"type":"string","nullable":true},"software_version":{"type":"string","nullable":true},"frontchannel_logout_uri":{"type":"string","nullable":true},"frontchannel_logout_session_required":{"type":"boolean"},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ClientMetadata","default":{}},"createdAt":{"type":"string","description":"Client creation date"},"updatedAt":{"type":"string","description":"Client updated date"}},"description":"Client"},"ClientMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ClientMetadata","default":{}},"ClientCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"callbacks":{"type":"array","items":{"type":"string"}},"logout_urls":{"type":"array","items":{"type":"string"}},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"ClientCreate","additionalProperties":false},"ClientMetadataCreate":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"},"ClientUpdate":{"type":"object","properties":{"name":{"type":"string","description":"Human-readable client name shown in consent screens."},"description":{"type":"string","description":"Free-form description for internal admin use."},"callbacks":{"type":"array","items":{"type":"string"},"description":"Whitelist of allowed OAuth `redirect_uri` values."},"logout_urls":{"type":"array","items":{"type":"string"},"description":"Whitelist of allowed `post_logout_redirect_uri` values."},"refresh_token":{"type":"object","required":["expiration_mode","infinite_token_lifetime","token_lifetime"],"properties":{"expiration_mode":{"enum":["expire","not-expire"]},"infinite_token_lifetime":{"type":"boolean"},"token_lifetime":{"type":"number"}}},"client_uri":{"type":"string","nullable":true},"logo_uri":{"type":"string","nullable":true},"tos_uri":{"type":"string","nullable":true},"policy_uri":{"type":"string","nullable":true},"contacts":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"application_type":{"type":"string"},"software_id":{"type":"string","nullable":true},"software_version":{"type":"string","nullable":true},"frontchannel_logout_uri":{"type":"string","nullable":true},"frontchannel_logout_session_required":{"type":"boolean"}},"description":"Partial update for a Client. Only the supplied fields are modified. `client_id` and `client_secret` are not editable through this endpoint to prevent accidental rotation; use a dedicated endpoint when secret rotation is added.","additionalProperties":false},"User":{"type":"object","required":["id","email_verified","phone_verified","logins_count","user_metadata","app_metadata","account","createdAt"],"properties":{"id":{"type":"string","description":"User ID"},"name":{"type":"string","description":"User name","nullable":true},"username":{"type":"string","description":"unique username for this user","nullable":true},"given_name":{"type":"string","description":"Given name","nullable":true},"family_name":{"type":"string","description":"Family name","nullable":true},"middle_name":{"type":"string","description":"Middle name (OIDC §5.1)","nullable":true},"nickname":{"type":"string","description":"Casual name. Distinct from given_name (e.g. \"Mike\" vs \"Michael\"). OIDC §5.1","nullable":true},"email":{"type":"string","description":"User email","nullable":true},"email_verified":{"type":"boolean","description":"true if email is verified","default":false},"email_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `email_verified` was last set. `manual` — admin flipped the flag via `POST /user/:id`. `verification_flow` — user clicked the verification link. `passwordless_otp` — user completed passwordless OTP login. `team_invite` — user clicked a team invitation link. `email_change` — user confirmed a self-service email change. `federated` — verified by the external IdP on OAuth callback. `null` — the field was cleared (admin un-verified the email)."},"email_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `email_verified` was last flipped to true.","nullable":true},"email_change_locked_at":{"type":"string","description":"ISO 8601 timestamp of the user's last verified email change. When set, OAuth callbacks will not overwrite `email`/`email_verified` from the federated provider — the manually-chosen email wins.","nullable":true},"email_bounced_at":{"type":"string","description":"ISO 8601 timestamp of the last Postmark hard bounce / spam complaint for this address. When set, the email is treated as undeliverable and no further emails are sent to the user until the address changes.","nullable":true},"phone":{"type":"string","description":"contact phone number","nullable":true},"phone_verified":{"type":"boolean","description":"phone is verified"},"phone_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `phone_verified` was last set. Same enum as `email_verified_method`."},"phone_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `phone_verified` was last flipped to true.","nullable":true},"country_iso":{"type":"string","description":"country iso code","nullable":true},"birth_date":{"type":"string","description":"user birth_date","nullable":true},"gender":{"type":"string","description":"User gender (free-form, OIDC §5.1)","nullable":true},"zoneinfo":{"type":"string","description":"IANA time-zone name (e.g. \"Europe/Madrid\"). OIDC §5.1 — used for the `zoneinfo` claim.","nullable":true},"locale":{"type":"string","description":"user main language","nullable":true},"region":{"type":"string","description":"customer region","nullable":true},"website":{"type":"string","description":"URL of the User's personal Web page or blog (OIDC §5.1)","nullable":true},"address":{"type":"object","properties":{"formatted":{"type":"string","description":"Full mailing address, formatted for display (may contain newlines)","nullable":true},"street_address":{"type":"string","nullable":true},"locality":{"type":"string","description":"City or locality","nullable":true},"region":{"type":"string","description":"State, province, or region","nullable":true},"postal_code":{"type":"string","nullable":true},"country":{"type":"string","description":"Country name","nullable":true}},"additionalProperties":false,"nullable":true},"picture":{"type":"string","description":"User picture url","nullable":true},"logins_count":{"type":"number","description":"Total number of logins this user has performed."},"last_ip":{"type":"string","description":"Last IP address from which this user logged in","nullable":true},"last_login":{"type":"string","description":"Last date and time this user logged in (ISO_8601 format)","nullable":true},"user_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"User Metadata","default":{}},"app_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"App Metadata","default":{}},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"UserMetadata","default":{}},"createdAt":{"type":"string","description":"User creation date"},"updatedAt":{"type":"string","description":"User updated date"}},"description":"User"},"UserAddress":{"type":"object","properties":{"formatted":{"type":"string","description":"Full mailing address, formatted for display (may contain newlines)","nullable":true},"street_address":{"type":"string","nullable":true},"locality":{"type":"string","description":"City or locality","nullable":true},"region":{"type":"string","description":"State, province, or region","nullable":true},"postal_code":{"type":"string","nullable":true},"country":{"type":"string","description":"Country name","nullable":true}},"additionalProperties":false,"nullable":true},"UserUserMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"User Metadata","default":{}},"UserAppMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"App Metadata","default":{}},"UserMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"UserMetadata","default":{}},"UserCreate":{"type":"object","properties":{"name":{"type":"string","description":"The user's full name."},"given_name":{"type":"string","description":"The user's given name."},"family_name":{"type":"string","description":"The user's family name."},"email":{"type":"string","description":"The user's email."},"phone":{"type":"string","description":"contact phone number"},"birth_date":{"type":"string","description":"The user's birth date"},"locale":{"type":"string","description":"The user's default locale lang."},"picture":{"type":"string","description":"A URI pointing to the user's picture."},"user_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"User Metadata"},"app_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"App Metadata"}},"description":"UserCreate","additionalProperties":false},"UserUserCreate":{"type":"object","properties":{},"additionalProperties":true,"description":"User Metadata"},"UserAppCreate":{"type":"object","properties":{},"additionalProperties":true,"description":"App Metadata"},"UserUpdate":{"type":"object","properties":{"name":{"type":"string","description":"name"},"given_name":{"type":"string","description":"given name"},"family_name":{"type":"string","description":"family name"},"email":{"type":"string","description":"Contact email. Changing the email to a new value automatically resets `email_verified` to false (and clears `email_verified_method` / `email_verified_at`) unless the same patch sets `email_verified` explicitly. The override is the documented way to import a pre-verified user from another IdP."},"email_verified":{"type":"boolean","description":"Flip the email verification flag. Setting `true` marks the email as verified by the admin (`email_verified_method=manual`). Setting `false` clears the verification metadata."},"phone":{"type":"string","description":"Contact phone number. Changing it to a new value automatically resets `phone_verified` to false (and clears `phone_verified_method` / `phone_verified_at`) unless the same patch sets `phone_verified` explicitly."},"phone_verified":{"type":"boolean","description":"Flip the phone verification flag. Setting `true` marks the phone as verified by the admin (`phone_verified_method=manual`)."},"country_iso":{"type":"string","description":"user country as iso string"},"birth_date":{"type":"string","description":"user birth_date"},"locale":{"type":"string","description":"user main language","nullable":true},"picture":{"type":"string","description":"User picture url"},"user_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"User defined metadata"},"app_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"App defined metadata"}},"description":"UserUpdate","additionalProperties":false},"UserUserMetadataUpdate":{"type":"object","properties":{},"additionalProperties":true,"description":"User defined metadata"},"UserAppMetadataUpdate":{"type":"object","properties":{},"additionalProperties":true,"description":"App defined metadata"},"Identity":{"type":"object","required":["id","connection","user","identity_id","profile_data","account","createdAt"],"properties":{"id":{"type":"string","description":"Identity ID"},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"identity_id":{"type":"string"},"access_token":{"type":"string"},"access_token_secret":{"type":"string"},"refresh_token":{"type":"string"},"access_token_expires_at":{"type":"string","description":"ISO 8601 timestamp when the stored provider `access_token` expires. Stamped from the provider `expires_in` on (re-)authorization and refresh. Absent when the provider issues non-expiring tokens."},"profile_data":{},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"IdentityMetadata","default":{}},"createdAt":{"type":"string","description":"Identity creation date"},"updatedAt":{"type":"string","description":"Identity updated date"}},"description":"Identity"},"IdentityMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"IdentityMetadata","default":{}},"IdentityCreate":{"type":"object","required":["account","user","identity_id","connection","profile_data"],"properties":{"account":{"type":"string"},"user":{"type":"string"},"identity_id":{"type":"string"},"connection":{"type":"string"},"access_token":{"type":"string"},"access_token_secret":{"type":"string"},"refresh_token":{"type":"string"},"profile_data":{}}},"Credential":{"type":"object","required":["id","connection","user","account","createdAt"],"properties":{"id":{"type":"string","description":"Credential ID"},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"email":{"type":"string","description":"Email login identifier (unique within the connection)."},"username":{"type":"string","description":"Username login identifier (unique within the connection)."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CredentialMetadata","default":{}},"createdAt":{"type":"string","description":"Credential creation date"},"updatedAt":{"type":"string","description":"Credential updated date"}},"description":"Credential"},"CredentialMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CredentialMetadata","default":{}},"CredentialsCreate":{"type":"object","required":["user","connection"],"properties":{"user":{"type":"string"},"connection":{"type":"string"},"email":{"type":"string"},"username":{"type":"string"}}},"CredentialsUpdate":{"type":"object","properties":{"email":{"type":"string"},"username":{"type":"string"}},"additionalProperties":false},"Role":{"type":"object","required":["id","name","description","account","createdAt"],"properties":{"id":{"type":"string","description":"Role ID"},"name":{"type":"string","description":"Short, human-readable identifier for the role (e.g. `admin`, `editor`, `billing-manager`). Surfaced in the dashboard role pickers.","example":"admin"},"description":{"type":"string","description":"Free-form explanation of what users in this role are expected to do or have access to. Shown alongside the role in the dashboard."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"RoleMetadata","default":{}},"createdAt":{"type":"string","description":"Role creation date"},"updatedAt":{"type":"string","description":"Role updated date"}},"description":"Role"},"RoleMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"RoleMetadata","default":{}},"RoleCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Short, human-readable identifier for the role (e.g. `admin`, `editor`).","example":"admin"},"description":{"type":"string","description":"Free-form explanation of what users in this role are expected to do or have access to."},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"RoleCreate","additionalProperties":false},"RoleMetadataCreate":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"},"RoleUpdate":{"type":"object","properties":{"name":{"type":"string","description":"New human-readable identifier for the role."},"description":{"type":"string","description":"New free-form description of what users in this role do."}},"description":"Partial update for a Role. Only the supplied fields are modified.","additionalProperties":false},"RoleMember":{"type":"object","required":["id","role","user","account","createdAt"],"properties":{"id":{"type":"string","description":"RoleMember ID"},"role":{"anyOf":[{"$ref":"#/components/schemas/Role"},{"type":"string"},{}],"description":"Role granted to the user. Returned as an id by default; pass `?expand=role` to inline the full Role object."},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User the role is granted to. Returned as an id by default; pass `?expand=user` to inline the full User object."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"RoleMemberMetadata","default":{}},"createdAt":{"type":"string","description":"RoleMember creation date"},"updatedAt":{"type":"string","description":"RoleMember updated date"}},"description":"RoleMember"},"RoleMemberMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"RoleMemberMetadata","default":{}},"RoleMemberCreate":{"type":"object","required":["users"],"properties":{"users":{"type":"array","items":{"type":"string"},"description":"List of User ids to grant the role to. Existing role memberships are preserved; passing a user that already holds the role is a no-op.","example":["user_6555fd293acc2f0fac0e3452"]}},"additionalProperties":false,"description":"Payload for granting a role to one or more users in a single call. Posted to `POST /role/:role_id/users`."},"Team":{"type":"object","required":["id","name","slug","description","logo_url","account","createdAt"],"properties":{"id":{"type":"string","description":"Team ID"},"name":{"type":"string","description":"Human-readable name of the team. Shown in the dashboard and in team-picker UI.","example":"Acme Engineering"},"slug":{"type":"string","description":"URL-safe identifier auto-derived from `name`. Unique within the tenant; used in routes that address a team by slug.","example":"acme-engineering"},"description":{"type":"string","description":"Optional free-form description of the team.","nullable":true},"logo_url":{"type":"string","description":"Optional URL of an image used as the team avatar/logo.","nullable":true},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMetadata","default":{}},"createdAt":{"type":"string","description":"Team creation date"},"updatedAt":{"type":"string","description":"Team updated date"}},"description":"Team"},"TeamMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMetadata","default":{}},"TeamCreate":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Human-readable name of the team.","example":"Acme Engineering"},"description":{"type":"string","description":"Optional free-form description of the team."},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"TeamCreate","additionalProperties":false},"TeamMetadataCreate":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"},"TeamUpdate":{"type":"object","properties":{"name":{"type":"string","description":"New human-readable name for the team."},"description":{"type":"string","description":"New free-form description for the team."},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Arbitrary key/value pairs attached to the team. Replaces the previous metadata entirely."}},"description":"Partial update for a Team. Only the supplied fields are modified. `slug` is auto-derived from `name` and is not user-editable.","additionalProperties":false},"TeamUpdateMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Arbitrary key/value pairs attached to the team. Replaces the previous metadata entirely."},"TeamMember":{"type":"object","required":["id","user","team","roles","account","createdAt"],"properties":{"id":{"type":"string","description":"TeamMember ID"},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User that belongs to the team. Returned as an id by default; pass `?expand=user` to inline the full User object."},"team":{"anyOf":[{"$ref":"#/components/schemas/Team"},{"type":"string"},{}],"description":"Team the user belongs to. Returned as an id by default; pass `?expand=team` to inline the full Team object."},"roles":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/Role"},{"type":"string"},{}]},"description":"Roles granted to the user *within this team*. Distinct from account-wide RoleMember grants — these only apply in the scope of the team. Each entry is an id by default; pass `?expand=roles` to inline."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMemberMetadata","default":{}},"createdAt":{"type":"string","description":"TeamMember creation date"},"updatedAt":{"type":"string","description":"TeamMember updated date"}},"description":"TeamMember"},"TeamMemberMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMemberMetadata","default":{}},"TeamMemberCreate":{"type":"object","required":["users"],"properties":{"users":{"type":"array","items":{"type":"string"},"description":"List of User ids to add as members of the team. Users already in the team are skipped.","example":["user_6555fd293acc2f0fac0e3452"]},"roles":{"type":"array","items":{"type":"string"},"description":"Role ids to grant to the added members within the scope of this team.","default":[],"example":["role_6555fd293acc2f0fac0e3452"]}},"additionalProperties":false,"description":"Payload for adding one or more users to a team in a single call. Posted to `POST /team/:team_id/member`."},"Permission":{"type":"object","required":["value"],"properties":{"value":{"type":"string","description":"Permission identifier as it appears in the `permissions` claim of an access_token (e.g. `read:users`). Use `<verb>:<resource>` by convention.","example":"read:users"},"description":{"type":"string","description":"Human-readable explanation shown in the consent prompt."}},"description":"A permission exposed by an API: a single value that may end up in the `permissions` claim of an access_token, plus a human-readable description shown in the consent prompt."},"PermissionCreate":{"type":"object","required":["value"],"properties":{"value":{"type":"string","description":"Permission identifier as it will appear in the `permissions` claim (e.g. `read:users`). Convention: `<verb>:<resource>`.","example":"read:users"},"description":{"type":"string","description":"Human-readable explanation shown in the consent prompt."}},"additionalProperties":false,"description":"Payload for declaring a single permission inside an Api."},"ApiSigningAlg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign access_tokens issued for this API. Currently only RS256 (the account keystore default) is implemented."},"ApiTokenDialect":{"anyOf":[{"type":"string","enum":["access_token"]},{"type":"string","enum":["access_token_authz"]}],"description":"Shape of access_tokens issued for this API. `access_token` emits the standard OAuth2 token. `access_token_authz` additionally embeds a `permissions` claim listing the permissions granted to the subject for this API."},"Api":{"type":"object","required":["id","name","slug","identifier","permissions","signing_alg","token_dialect","token_lifetime","enforce_policies","allow_offline_access","skip_consent","include_teams_in_access_token","include_roles_in_access_token","include_teams_in_id_token","include_roles_in_id_token","account","createdAt"],"properties":{"id":{"type":"string","description":"Api ID"},"name":{"type":"string","description":"Human-readable name for the API. Shown in the dashboard and consent prompts.","example":"My Backend API"},"slug":{"type":"string","description":"URL-safe identifier auto-derived from `name`. Unique within the tenant."},"identifier":{"type":"string","description":"Audience URL that clients pass as `audience=` when requesting a token for this API. Becomes the `aud` claim in the issued access_token. Immutable after creation and unique within the tenant.","example":"https://api.faable.com"},"description":{"type":"string","description":"Optional human-readable description of the API."},"permissions":{"type":"array","items":{"$ref":"#/components/schemas/Permission"},"description":"Set of permissions (scopes) this API exposes. When a token is issued with `audience=identifier`, the requested `scope` is intersected with this list to populate the `permissions` claim."},"signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign access_tokens issued for this API. Currently only RS256 (the account keystore default) is implemented."},"token_dialect":{"anyOf":[{"type":"string","enum":["access_token"]},{"type":"string","enum":["access_token_authz"]}],"description":"Shape of access_tokens issued for this API. `access_token` emits the standard OAuth2 token. `access_token_authz` additionally embeds a `permissions` claim listing the permissions granted to the subject for this API."},"token_lifetime":{"type":"integer","description":"Access_token lifetime in seconds. Default 86400 (24h). Applied at token issuance time (overrides the generic default).","minimum":60,"maximum":2592000},"enforce_policies":{"type":"boolean","description":"When true, only scopes that match a permission in `permissions` are forwarded into the access_token. When false, requested scopes are echoed back verbatim with no filtering."},"allow_offline_access":{"type":"boolean","description":"When true, the API is eligible to be the target of a `refresh_token` (i.e. clients can request `offline_access` against it)."},"skip_consent":{"type":"boolean","description":"When true, the consent prompt is skipped for first-party clients (clients owned by the same tenant as the API)."},"include_teams_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `teams` claim listing the slugs of the teams the subject is a member of within the tenant."},"include_roles_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `roles` claim listing the names of the roles the subject holds across their team memberships within the tenant."},"include_teams_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `teams` claim with the subject team slugs. The id_token only sees the flag when the client requested `audience=` so this API is resolved at issuance time."},"include_roles_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `roles` claim with the subject role names. Same audience caveat as `include_teams_in_id_token`."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ApiMetadata","default":{}},"createdAt":{"type":"string","description":"Api creation date"},"updatedAt":{"type":"string","description":"Api updated date"}},"description":"Api"},"ApiMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ApiMetadata","default":{}},"ApiCreate":{"type":"object","required":["name","identifier"],"properties":{"name":{"type":"string","description":"Human-readable name for the API.","example":"My Backend API"},"identifier":{"type":"string","description":"Audience URL clients pass as `audience=` when requesting a token for this API. Must be unique within the tenant and is immutable after creation.","example":"https://api.faable.com"},"description":{"type":"string","description":"Optional human-readable description of the API."},"permissions":{"type":"array","items":{"$ref":"#/components/schemas/PermissionCreate"},"description":"Set of permissions (scopes) this API exposes. Tokens issued with `audience=identifier` will only carry these in their `permissions` claim.","default":[]},"signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign access_tokens issued for this API. Currently only RS256 (the account keystore default) is implemented."},"token_dialect":{"anyOf":[{"type":"string","enum":["access_token"]},{"type":"string","enum":["access_token_authz"]}],"description":"Shape of access_tokens issued for this API. `access_token` emits the standard OAuth2 token. `access_token_authz` additionally embeds a `permissions` claim listing the permissions granted to the subject for this API."},"token_lifetime":{"type":"integer","description":"Access_token lifetime in seconds. Defaults to 86400 (24h) if omitted.","minimum":60,"maximum":2592000},"enforce_policies":{"type":"boolean","description":"When true, requested scopes are filtered against `permissions` at token issuance."},"allow_offline_access":{"type":"boolean","description":"When true, clients can request `offline_access` and receive a refresh_token for this API."},"skip_consent":{"type":"boolean","description":"When true, skip the consent prompt for first-party clients."},"include_teams_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `teams` claim with the subject team slugs."},"include_roles_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `roles` claim with the subject role names."},"include_teams_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `teams` claim with the subject team slugs."},"include_roles_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `roles` claim with the subject role names."}},"additionalProperties":false,"description":"Payload for creating an Api (a.k.a. Resource Server / Audience). The `identifier` becomes the `aud` claim in tokens issued for this API and cannot be changed after creation."},"ApiUpdate":{"type":"object","properties":{"name":{"type":"string","description":"Human-readable name for the API."},"description":{"type":"string","description":"Optional human-readable description of the API."},"permissions":{"type":"array","items":{"$ref":"#/components/schemas/PermissionCreate"},"description":"Replaces the full permissions list. Tokens issued AFTER the update will use the new list; tokens already in circulation are unchanged."},"signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign access_tokens issued for this API. Currently only RS256 (the account keystore default) is implemented."},"token_dialect":{"anyOf":[{"type":"string","enum":["access_token"]},{"type":"string","enum":["access_token_authz"]}],"description":"Shape of access_tokens issued for this API. `access_token` emits the standard OAuth2 token. `access_token_authz` additionally embeds a `permissions` claim listing the permissions granted to the subject for this API."},"token_lifetime":{"type":"integer","description":"Access_token lifetime in seconds.","minimum":60,"maximum":2592000},"enforce_policies":{"type":"boolean","description":"When true, requested scopes are filtered against `permissions` at token issuance."},"allow_offline_access":{"type":"boolean","description":"When true, clients can request `offline_access` and receive a refresh_token for this API."},"skip_consent":{"type":"boolean","description":"When true, skip the consent prompt for first-party clients."},"include_teams_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `teams` claim with the subject team slugs."},"include_roles_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `roles` claim with the subject role names."},"include_teams_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `teams` claim with the subject team slugs."},"include_roles_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `roles` claim with the subject role names."}},"additionalProperties":false,"description":"Partial update for an Api. `identifier` is immutable and not present here; recreate the API if you need to change it."},"Action":{"type":"object","required":["id","name","trigger","code","enabled","account","createdAt"],"properties":{"id":{"type":"string","description":"Action ID"},"name":{"type":"string","description":"Action Name","maxLength":200},"trigger":{"enum":["continue","post-login"],"description":"Trigger event name","default":"post-login"},"code":{"type":"string","description":"JavaScript Code to execute"},"enabled":{"type":"boolean","description":"Is this action active?","default":true},"order":{"type":"number","description":"Execution order","default":0},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ActionMetadata","default":{}},"createdAt":{"type":"string","description":"Action creation date"},"updatedAt":{"type":"string","description":"Action updated date"}},"description":"Action"},"ActionMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ActionMetadata","default":{}},"ActionCreate":{"type":"object","required":["name","trigger"],"properties":{"name":{"type":"string","description":"Action Name","maxLength":200},"trigger":{"type":"string","description":"Trigger event name (e.g., post-login)"},"code":{"type":"string","description":"JavaScript Code to execute"},"enabled":{"type":"boolean","description":"Is this action active?","default":true},"order":{"type":"number","description":"Execution order","default":0}}},"NotificationSubscription":{"anyOf":[{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionEmail ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["email"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionEmailMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionEmail creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionEmail updated date"}},"description":"NotificationSubscriptionEmail"},{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionWebhook ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["webhook"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionWebhookMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionWebhook creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionWebhook updated date"}},"description":"NotificationSubscriptionWebhook"}],"description":"NotificationSubscription"},"NotificationSubscriptionEmail":{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionEmail ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["email"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionEmailMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionEmail creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionEmail updated date"}},"description":"NotificationSubscriptionEmail"},"NotificationSubscriptionEmailConfig":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}},"additionalProperties":false},"NotificationSubscriptionEmailMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionEmailMetadata","default":{}},"NotificationSubscriptionWebhook":{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionWebhook ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["webhook"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionWebhookMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionWebhook creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionWebhook updated date"}},"description":"NotificationSubscriptionWebhook"},"NotificationSubscriptionWebhookConfig":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}},"additionalProperties":false},"NotificationSubscriptionWebhookMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionWebhookMetadata","default":{}},"NotificationSubscriptionCreate":{"anyOf":[{"type":"object","required":["events","channel","config"],"properties":{"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["email"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}},"additionalProperties":false},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"NotificationSubscriptionEmailCreate","additionalProperties":false},{"type":"object","required":["events","channel","config"],"properties":{"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["webhook"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}},"additionalProperties":false},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"NotificationSubscriptionWebhookCreate","additionalProperties":false}],"description":"NotificationSubscriptionCreate"},"NotificationSubscriptionEmailCreate":{"type":"object","required":["events","channel","config"],"properties":{"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["email"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}},"additionalProperties":false},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"NotificationSubscriptionEmailCreate","additionalProperties":false},"NotificationSubscriptionEmailConfigCreate":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}},"additionalProperties":false},"NotificationSubscriptionEmailMetadataCreate":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"},"NotificationSubscriptionWebhookCreate":{"type":"object","required":["events","channel","config"],"properties":{"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["webhook"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}},"additionalProperties":false},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"NotificationSubscriptionWebhookCreate","additionalProperties":false},"NotificationSubscriptionWebhookConfigCreate":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}},"additionalProperties":false},"NotificationSubscriptionWebhookMetadataCreate":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"},"NotificationSubscriptionUpdate":{"anyOf":[{"type":"object","properties":{"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["email"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}}},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Metadata update"}}},{"type":"object","properties":{"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["webhook"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}}},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Metadata update"}}}],"description":"NotificationSubscriptionUpdate"},"NotificationSubscriptionEmailMetadataUpdate":{"type":"object","properties":{},"additionalProperties":true,"description":"Metadata update"},"NotificationSubscriptionWebhookMetadataUpdate":{"type":"object","properties":{},"additionalProperties":true,"description":"Metadata update"},"Log":{"type":"object","required":["id","type","status","account","createdAt"],"properties":{"id":{"type":"string","description":"Log ID"},"type":{"type":"string","description":"Log type, e.g. email.user.created"},"status":{"anyOf":[{"type":"string","enum":["success"]},{"type":"string","enum":["failed"]},{"type":"string","enum":["skipped"]},{"type":"string","enum":["info"]}],"description":"Log status"},"message":{"type":"string","description":"Optional log message"},"data":{"description":"Type-specific structured payload"},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"client":{"anyOf":[{"$ref":"#/components/schemas/Client"},{"type":"string"},{}]},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"team":{"anyOf":[{"$ref":"#/components/schemas/Team"},{"type":"string"},{}]},"identity":{"anyOf":[{"$ref":"#/components/schemas/Identity"},{"type":"string"},{}]},"ticket":{"type":"string"},"expires_at":{"type":"string","format":"date-time","description":"When this log row will be auto-deleted by the Mongo TTL monitor. Absent on rows recorded without `ttl_seconds`."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"LogMetadata","default":{}},"createdAt":{"type":"string","description":"Log creation date"},"updatedAt":{"type":"string","description":"Log updated date"}},"description":"Log"},"LogMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"LogMetadata","default":{}},"Customdomain":{"type":"object","required":["id","domain","token","status","attempts","account","createdAt"],"properties":{"id":{"type":"string","description":"Customdomain ID"},"domain":{"type":"string"},"token":{"type":"string"},"status":{"enum":["PENDING","VERIFYING","ACTIVE","FAILED","DEGRADED"]},"attempts":{"type":"number"},"nextCheck":{"type":"string","format":"date-time"},"lastCheck":{"type":"string","format":"date-time"},"errorLog":{"type":"string","description":"User feedback error from last check"},"verifiedAt":{"type":"string","format":"date-time"},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CustomdomainMetadata","default":{}},"createdAt":{"type":"string","description":"Customdomain creation date"},"updatedAt":{"type":"string","description":"Customdomain updated date"}},"description":"Customdomain"},"CustomdomainMetadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CustomdomainMetadata","default":{}},"CustomdomainCreate":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"CustomdomainCreate","additionalProperties":false},"CustomdomainMetadataCreate":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"},"ClientRegistrationRequest":{"type":"object","required":["redirect_uris"],"properties":{"redirect_uris":{"type":"array","items":{"type":"string","format":"uri"},"description":"Array of redirection URI values used by the client (RFC 7591 §2). REQUIRED for any client that uses an authorization grant.","minItems":1},"client_name":{"type":"string","description":"Human-readable name of the client (RFC 7591 §2)"},"client_uri":{"type":"string","description":"URL of the home page of the client"},"logo_uri":{"type":"string"},"tos_uri":{"type":"string"},"policy_uri":{"type":"string"},"contacts":{"type":"array","items":{"type":"string"},"description":"Array of email addresses responsible for the client"},"grant_types":{"type":"array","items":{"type":"string"},"description":"Grant types the client will use. Defaults to [\"authorization_code\"]. Must be a subset of what the server supports."},"response_types":{"type":"array","items":{"type":"string"},"description":"Response types the client will use. Defaults to [\"code\"]."},"token_endpoint_auth_method":{"type":"string","description":"How the client authenticates at the token endpoint. Defaults to \"client_secret_basic\"."},"application_type":{"anyOf":[{"type":"string","enum":["web"]},{"type":"string","enum":["native"]}],"description":"OIDC §2 — application type. Defaults to \"web\"."},"post_logout_redirect_uris":{"type":"array","items":{"type":"string"},"description":"OIDC RP-Initiated Logout — URIs the OP MAY redirect to after end-session."},"scope":{"type":"string","description":"Space-separated list of scope values the client may use."},"software_id":{"type":"string"},"software_version":{"type":"string"},"frontchannel_logout_uri":{"type":"string","description":"OIDC Front-Channel Logout 1.0 — URL the OP loads inside an iframe at end-session to let the RP clear its session."},"frontchannel_logout_session_required":{"type":"boolean","description":"OIDC Front-Channel Logout 1.0 — when true, the OP MUST include `iss` and `sid` parameters when calling the frontchannel_logout_uri."}},"additionalProperties":true},"ClientRegistrationResponse":{"type":"object","required":["client_id","client_secret","client_id_issued_at","client_secret_expires_at","redirect_uris","grant_types","response_types","token_endpoint_auth_method","application_type"],"properties":{"client_id":{"type":"string"},"client_secret":{"type":"string"},"client_id_issued_at":{"type":"number","description":"Unix timestamp (seconds) at which the client_id was issued"},"client_secret_expires_at":{"type":"number","description":"0 if the client_secret does not expire"},"redirect_uris":{"type":"array","items":{"type":"string"}},"client_name":{"type":"string"},"client_uri":{"type":"string"},"logo_uri":{"type":"string"},"tos_uri":{"type":"string"},"policy_uri":{"type":"string"},"contacts":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"application_type":{"type":"string"},"post_logout_redirect_uris":{"type":"array","items":{"type":"string"}},"scope":{"type":"string"},"software_id":{"type":"string"},"software_version":{"type":"string"},"frontchannel_logout_uri":{"type":"string"},"frontchannel_logout_session_required":{"type":"boolean"}},"additionalProperties":true},"AuthAccountCreate":{"type":"object","required":["name","team"],"properties":{"name":{"type":"string"},"team":{"type":"string"},"logo_src":{"type":"string"},"icon_src":{"type":"string"},"callback_hostnames":{"type":"array","items":{"type":"string"}},"default_connection":{"type":"string"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"AuthAccountCreate","additionalProperties":false},"AuthAccountMetadataCreate":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"},"AuthAccountUpdate":{"type":"object","properties":{"logo_src":{"type":"string","nullable":true},"icon_src":{"type":"string","nullable":true},"callback_hostnames":{"type":"array","items":{"type":"string"}},"default_connection":{"type":"string","nullable":true},"enabled_locales":{"type":"array","items":{"type":"string"}},"notification_settings":{"type":"object","properties":{"welcome_email_enabled":{"type":"boolean","description":"Send the built-in welcome email on user.created","default":false},"verify_email_auto_send":{"type":"boolean","description":"Send a verification email automatically when a user is created with `email_verified=false` and an email address. The link in the email lands on `GET /verify-email?ticket=...` and flips `email_verified=true` with `email_verified_method=verification_flow`. When `false`, verification emails must be requested explicitly via `POST /user/:id/verify-email/start`.","default":false}}}},"description":"AuthAccountUpdate","additionalProperties":false},"OAuthTokenParams":{"type":"object","properties":{"grant_type":{"anyOf":[{"type":"string","enum":["authorization_code"]},{"type":"string","enum":["client_credentials"]},{"type":"string","enum":["refresh_token"]},{"type":"string","enum":["password"]},{"type":"string","enum":["http://auth0.com/oauth/grant-type/passwordless/otp"]},{"type":"string","enum":["urn:ietf:params:oauth:grant-type:token-exchange"]},{"type":"string","enum":["urn:ietf:params:oauth:grant-type:device_code"]}],"description":"Grant Type. https://oauth.net/2/grant-types/"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"scope":{"type":"string"},"code":{"type":"string"},"code_verifier":{"type":"string"},"username":{"type":"string"},"otp":{"type":"string"},"refresh_token":{"type":"string"},"subject_token":{"type":"string"},"subject_token_type":{"type":"string"},"device_code":{"type":"string","description":"The device code returned by the authorization server."},"audience":{"type":"string","description":"Auth0-compatible alias for `resource` (RFC 8707). When both are provided they must match."},"resource":{"type":"string","description":"RFC 8707 Resource Indicator. Absolute URI of the target Api, no fragment. Matched against `Api.identifier` in the tenant."}},"additionalProperties":true},"OAuthGrantType":{"anyOf":[{"type":"string","enum":["authorization_code"]},{"type":"string","enum":["client_credentials"]},{"type":"string","enum":["refresh_token"]},{"type":"string","enum":["password"]},{"type":"string","enum":["http://auth0.com/oauth/grant-type/passwordless/otp"]},{"type":"string","enum":["urn:ietf:params:oauth:grant-type:token-exchange"]},{"type":"string","enum":["urn:ietf:params:oauth:grant-type:device_code"]}],"description":"Grant Type. https://oauth.net/2/grant-types/"},"UsernamepasswordLoginBody":{"type":"object","required":["username","password","client_id"],"properties":{"username":{"type":"string"},"password":{"type":"string"},"state":{"type":"string","description":"An opaque value the applications adds to the initial request that the authorization server includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks."},"response_type":{"type":"string"},"redirect_to":{"type":"string","description":"Same-origin path to return the user to after authentication, instead of the OAuth client redirect. Used by first-party interactive flows (e.g. device-code confirm). Non same-origin values are ignored."},"client_id":{"type":"string"},"connection":{"type":"string","description":"Deprecated. Use connection_id"},"connection_id":{"type":"string","description":"Which oauth connection to use. Leave empty to use default connection"},"scope":{"type":"string"},"redirect_uri":{"type":"string","description":"The URL to which Faable will redirect the browser after authorization has been granted by the user."},"nonce":{"type":"string","description":"OIDC §3.1.2.1 — string value used to associate a Client session with an ID Token, to mitigate replay attacks. If passed at /authorize, the same value MUST appear in the issued id_token."},"max_age":{"type":"number","description":"OIDC §3.1.2.1 — maximum allowable elapsed time in seconds since the last End-User authentication. If exceeded, the OP re-authenticates and `auth_time` is REQUIRED in the resulting id_token.","minimum":0},"prompt":{"type":"string"},"audience":{"type":"string","description":"Auth0-compatible alias for `resource` (RFC 8707). When both are sent they must match. Identifier of the Api the client wants to access; persisted in the auth state so the token issued at /oauth/token targets the matching Api resource."},"resource":{"type":"string","description":"RFC 8707 Resource Indicator. MUST be an absolute URI without fragment. When matched against a registered Api in the tenant the issued access_token gets `aud = <api.identifier>`."}},"description":"UsernamepasswordLoginBody","additionalProperties":false},"LoginCallbackBody":{"type":"object","required":["wa","wresult","wctx"],"properties":{"wa":{"type":"string","description":"is always wsignin1.0"},"wresult":{"type":"string","description":"JWT"},"wctx":{"type":"string","description":"Serialized JSON with context"}}}}},"paths":{"/webhooks/postmark":{"post":{"responses":{"200":{"description":"Default Response"}}}},"/account/current":{"get":{"operationId":"account/current","summary":"Get current Account","tags":["account"],"description":"Returns the Account resolved from request context (header, hostname, or team id). Use `expand` to populate nested references.","parameters":[{"schema":{"type":"array","items":{"type":"string","maxLength":1000}},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `expand=user&expand=team`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"AuthAccount","content":{"application/json":{"schema":{"type":"object","required":["id","name","domain","slug","callback_hostnames","token_signature","token_signing_alg","enabled_locales","notification_settings","createdAt"],"properties":{"id":{"type":"string","description":"AuthAccount ID"},"name":{"type":"string"},"domain":{"type":"string"},"slug":{"type":"string"},"logo_src":{"type":"string","nullable":true},"icon_src":{"type":"string","nullable":true},"callback_hostnames":{"type":"array","items":{"type":"string"}},"token_signature":{"type":"string","description":"Shared HMAC secret. Used when token_signing_alg is an HS* algorithm; ignored for RS*/ES*/PS*."},"token_signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign tokens issued by this Account. Today only RS256 is implemented."},"default_connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"enabled_locales":{"type":"array","items":{"type":"string"}},"team":{"type":"string","nullable":true},"notification_settings":{"type":"object","required":["welcome_email_enabled","verify_email_auto_send"],"properties":{"welcome_email_enabled":{"type":"boolean","description":"Send the built-in welcome email on user.created","default":false},"verify_email_auto_send":{"type":"boolean","description":"Send a verification email automatically when a user is created with `email_verified=false` and an email address. The link in the email lands on `GET /verify-email?ticket=...` and flips `email_verified=true` with `email_verified_method=verification_flow`. When `false`, verification emails must be requested explicitly via `POST /user/:id/verify-email/start`.","default":false}},"additionalProperties":false},"email_change_verification_mode":{"anyOf":[{"type":"string","enum":["new_only"]},{"type":"string","enum":["old_and_new"]}],"description":"Policy for the user email-change flow. `new_only` (default) sends a single confirmation link to the new email. `old_and_new` requires the user to also click a link sent to the previous email before the swap takes effect — stricter, useful for tenants with higher-risk users."},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Controls what happens to `user.email` on subsequent OAuth/federated logins when the user previously changed their email manually through this auth server (i.e. `user.email_change_locked_at` is set).\n\n- `preserve_manual` (default): the manually-set email wins. The federated provider's email is ignored on re-sync; `email` and `email_verified` are not touched. The identity link stays valid via `provider_user_id`, so the user can still log in with Google/etc.\n- `always_sync`: the federated provider's email is always written back, overwriting any manual change. Useful for tenants whose source of truth for identity is the IdP (corporate SSO, etc.)."},"createdAt":{"type":"string","description":"AuthAccount creation date"},"updatedAt":{"type":"string","description":"AuthAccount updated date"}},"description":"AuthAccount"}}}}}}},"/account":{"post":{"operationId":"account/create","summary":"Create an Account","tags":["account"],"description":"Creates a new Auth Account. The slug is derived from the name and used to build the default `*.auth.faable.link` domain.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","team"],"properties":{"name":{"type":"string"},"team":{"type":"string"},"logo_src":{"type":"string"},"icon_src":{"type":"string"},"callback_hostnames":{"type":"array","items":{"type":"string"}},"default_connection":{"type":"string"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"AuthAccountCreate","additionalProperties":false}}},"description":"AuthAccountCreate"},"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"AuthAccount","content":{"application/json":{"schema":{"type":"object","required":["id","name","domain","slug","callback_hostnames","token_signature","token_signing_alg","enabled_locales","notification_settings","createdAt"],"properties":{"id":{"type":"string","description":"AuthAccount ID"},"name":{"type":"string"},"domain":{"type":"string"},"slug":{"type":"string"},"logo_src":{"type":"string","nullable":true},"icon_src":{"type":"string","nullable":true},"callback_hostnames":{"type":"array","items":{"type":"string"}},"token_signature":{"type":"string","description":"Shared HMAC secret. Used when token_signing_alg is an HS* algorithm; ignored for RS*/ES*/PS*."},"token_signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign tokens issued by this Account. Today only RS256 is implemented."},"default_connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"enabled_locales":{"type":"array","items":{"type":"string"}},"team":{"type":"string","nullable":true},"notification_settings":{"type":"object","required":["welcome_email_enabled","verify_email_auto_send"],"properties":{"welcome_email_enabled":{"type":"boolean","description":"Send the built-in welcome email on user.created","default":false},"verify_email_auto_send":{"type":"boolean","description":"Send a verification email automatically when a user is created with `email_verified=false` and an email address. The link in the email lands on `GET /verify-email?ticket=...` and flips `email_verified=true` with `email_verified_method=verification_flow`. When `false`, verification emails must be requested explicitly via `POST /user/:id/verify-email/start`.","default":false}},"additionalProperties":false},"email_change_verification_mode":{"anyOf":[{"type":"string","enum":["new_only"]},{"type":"string","enum":["old_and_new"]}],"description":"Policy for the user email-change flow. `new_only` (default) sends a single confirmation link to the new email. `old_and_new` requires the user to also click a link sent to the previous email before the swap takes effect — stricter, useful for tenants with higher-risk users."},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Controls what happens to `user.email` on subsequent OAuth/federated logins when the user previously changed their email manually through this auth server (i.e. `user.email_change_locked_at` is set).\n\n- `preserve_manual` (default): the manually-set email wins. The federated provider's email is ignored on re-sync; `email` and `email_verified` are not touched. The identity link stays valid via `provider_user_id`, so the user can still log in with Google/etc.\n- `always_sync`: the federated provider's email is always written back, overwriting any manual change. Useful for tenants whose source of truth for identity is the IdP (corporate SSO, etc.)."},"createdAt":{"type":"string","description":"AuthAccount creation date"},"updatedAt":{"type":"string","description":"AuthAccount updated date"}},"description":"AuthAccount"}}}}}},"get":{"operationId":"account/list","summary":"List Accounts","tags":["account"],"description":"List Accounts owned by the requesting project/team. Supports cursor pagination and `expand`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Start from this cursor"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Start from this cursor"},{"schema":{"type":"number"},"in":"query","name":"pageSize","required":false,"description":"Size of the results array"},{"schema":{"type":"array","items":{"type":"string","maxLength":1000}},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `expand=user&expand=team`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"PaginatedResponse","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"type":"string","description":"next cursor","nullable":true},"results":{"type":"array","items":{"$ref":"#/components/schemas/AuthAccount"},"description":"List of results"}},"description":"PaginatedResponse","additionalProperties":false}}}}}}},"/account/{account_id}":{"get":{"operationId":"account/get","summary":"Get an Account","tags":["account"],"description":"Fetch a single Account by its id. Use `expand` to populate id-only fields (e.g. `default_connection`) inline.","parameters":[{"schema":{"type":"array","items":{"type":"string","maxLength":1000}},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `expand=user&expand=team`)."},{"schema":{"type":"string"},"in":"path","name":"account_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"AuthAccount","content":{"application/json":{"schema":{"type":"object","required":["id","name","domain","slug","callback_hostnames","token_signature","token_signing_alg","enabled_locales","notification_settings","createdAt"],"properties":{"id":{"type":"string","description":"AuthAccount ID"},"name":{"type":"string"},"domain":{"type":"string"},"slug":{"type":"string"},"logo_src":{"type":"string","nullable":true},"icon_src":{"type":"string","nullable":true},"callback_hostnames":{"type":"array","items":{"type":"string"}},"token_signature":{"type":"string","description":"Shared HMAC secret. Used when token_signing_alg is an HS* algorithm; ignored for RS*/ES*/PS*."},"token_signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign tokens issued by this Account. Today only RS256 is implemented."},"default_connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"enabled_locales":{"type":"array","items":{"type":"string"}},"team":{"type":"string","nullable":true},"notification_settings":{"type":"object","required":["welcome_email_enabled","verify_email_auto_send"],"properties":{"welcome_email_enabled":{"type":"boolean","description":"Send the built-in welcome email on user.created","default":false},"verify_email_auto_send":{"type":"boolean","description":"Send a verification email automatically when a user is created with `email_verified=false` and an email address. The link in the email lands on `GET /verify-email?ticket=...` and flips `email_verified=true` with `email_verified_method=verification_flow`. When `false`, verification emails must be requested explicitly via `POST /user/:id/verify-email/start`.","default":false}},"additionalProperties":false},"email_change_verification_mode":{"anyOf":[{"type":"string","enum":["new_only"]},{"type":"string","enum":["old_and_new"]}],"description":"Policy for the user email-change flow. `new_only` (default) sends a single confirmation link to the new email. `old_and_new` requires the user to also click a link sent to the previous email before the swap takes effect — stricter, useful for tenants with higher-risk users."},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Controls what happens to `user.email` on subsequent OAuth/federated logins when the user previously changed their email manually through this auth server (i.e. `user.email_change_locked_at` is set).\n\n- `preserve_manual` (default): the manually-set email wins. The federated provider's email is ignored on re-sync; `email` and `email_verified` are not touched. The identity link stays valid via `provider_user_id`, so the user can still log in with Google/etc.\n- `always_sync`: the federated provider's email is always written back, overwriting any manual change. Useful for tenants whose source of truth for identity is the IdP (corporate SSO, etc.)."},"createdAt":{"type":"string","description":"AuthAccount creation date"},"updatedAt":{"type":"string","description":"AuthAccount updated date"}},"description":"AuthAccount"}}}}}},"post":{"operationId":"account/update","summary":"Update an Account","tags":["account"],"description":"Update the Account configuration such as branding (logo and icon URLs).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"logo_src":{"type":"string","nullable":true},"icon_src":{"type":"string","nullable":true},"callback_hostnames":{"type":"array","items":{"type":"string"}},"default_connection":{"type":"string","nullable":true},"enabled_locales":{"type":"array","items":{"type":"string"}},"notification_settings":{"type":"object","properties":{"welcome_email_enabled":{"type":"boolean","description":"Send the built-in welcome email on user.created","default":false},"verify_email_auto_send":{"type":"boolean","description":"Send a verification email automatically when a user is created with `email_verified=false` and an email address. The link in the email lands on `GET /verify-email?ticket=...` and flips `email_verified=true` with `email_verified_method=verification_flow`. When `false`, verification emails must be requested explicitly via `POST /user/:id/verify-email/start`.","default":false}}}},"description":"AuthAccountUpdate","additionalProperties":false}}},"description":"AuthAccountUpdate"},"parameters":[{"schema":{"type":"string"},"in":"path","name":"account_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"AuthAccount","content":{"application/json":{"schema":{"type":"object","required":["id","name","domain","slug","callback_hostnames","token_signature","token_signing_alg","enabled_locales","notification_settings","createdAt"],"properties":{"id":{"type":"string","description":"AuthAccount ID"},"name":{"type":"string"},"domain":{"type":"string"},"slug":{"type":"string"},"logo_src":{"type":"string","nullable":true},"icon_src":{"type":"string","nullable":true},"callback_hostnames":{"type":"array","items":{"type":"string"}},"token_signature":{"type":"string","description":"Shared HMAC secret. Used when token_signing_alg is an HS* algorithm; ignored for RS*/ES*/PS*."},"token_signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign tokens issued by this Account. Today only RS256 is implemented."},"default_connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"enabled_locales":{"type":"array","items":{"type":"string"}},"team":{"type":"string","nullable":true},"notification_settings":{"type":"object","required":["welcome_email_enabled","verify_email_auto_send"],"properties":{"welcome_email_enabled":{"type":"boolean","description":"Send the built-in welcome email on user.created","default":false},"verify_email_auto_send":{"type":"boolean","description":"Send a verification email automatically when a user is created with `email_verified=false` and an email address. The link in the email lands on `GET /verify-email?ticket=...` and flips `email_verified=true` with `email_verified_method=verification_flow`. When `false`, verification emails must be requested explicitly via `POST /user/:id/verify-email/start`.","default":false}},"additionalProperties":false},"email_change_verification_mode":{"anyOf":[{"type":"string","enum":["new_only"]},{"type":"string","enum":["old_and_new"]}],"description":"Policy for the user email-change flow. `new_only` (default) sends a single confirmation link to the new email. `old_and_new` requires the user to also click a link sent to the previous email before the swap takes effect — stricter, useful for tenants with higher-risk users."},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Controls what happens to `user.email` on subsequent OAuth/federated logins when the user previously changed their email manually through this auth server (i.e. `user.email_change_locked_at` is set).\n\n- `preserve_manual` (default): the manually-set email wins. The federated provider's email is ignored on re-sync; `email` and `email_verified` are not touched. The identity link stays valid via `provider_user_id`, so the user can still log in with Google/etc.\n- `always_sync`: the federated provider's email is always written back, overwriting any manual change. Useful for tenants whose source of truth for identity is the IdP (corporate SSO, etc.)."},"createdAt":{"type":"string","description":"AuthAccount creation date"},"updatedAt":{"type":"string","description":"AuthAccount updated date"}},"description":"AuthAccount"}}}}}},"delete":{"operationId":"account/delete","summary":"Delete an Account","tags":["account"],"description":"Permanently removes an Account and its associated data. This action cannot be undone.","parameters":[{"schema":{"type":"string"},"in":"path","name":"account_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{}}},"/account/host/{host}":{"get":{"operationId":"account/getByHost","summary":"Find Account by host","tags":["account"],"description":"Looks up the Account that owns the given hostname, checking both the built-in `*.auth.faable.link` slug and any verified custom domains.","parameters":[{"schema":{"type":"string"},"in":"path","name":"host","required":true}],"responses":{"200":{"description":"AuthAccount","content":{"application/json":{"schema":{"type":"object","required":["id","name","domain","slug","callback_hostnames","token_signature","token_signing_alg","enabled_locales","notification_settings","createdAt"],"properties":{"id":{"type":"string","description":"AuthAccount ID"},"name":{"type":"string"},"domain":{"type":"string"},"slug":{"type":"string"},"logo_src":{"type":"string","nullable":true},"icon_src":{"type":"string","nullable":true},"callback_hostnames":{"type":"array","items":{"type":"string"}},"token_signature":{"type":"string","description":"Shared HMAC secret. Used when token_signing_alg is an HS* algorithm; ignored for RS*/ES*/PS*."},"token_signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign tokens issued by this Account. Today only RS256 is implemented."},"default_connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"enabled_locales":{"type":"array","items":{"type":"string"}},"team":{"type":"string","nullable":true},"notification_settings":{"type":"object","required":["welcome_email_enabled","verify_email_auto_send"],"properties":{"welcome_email_enabled":{"type":"boolean","description":"Send the built-in welcome email on user.created","default":false},"verify_email_auto_send":{"type":"boolean","description":"Send a verification email automatically when a user is created with `email_verified=false` and an email address. The link in the email lands on `GET /verify-email?ticket=...` and flips `email_verified=true` with `email_verified_method=verification_flow`. When `false`, verification emails must be requested explicitly via `POST /user/:id/verify-email/start`.","default":false}},"additionalProperties":false},"email_change_verification_mode":{"anyOf":[{"type":"string","enum":["new_only"]},{"type":"string","enum":["old_and_new"]}],"description":"Policy for the user email-change flow. `new_only` (default) sends a single confirmation link to the new email. `old_and_new` requires the user to also click a link sent to the previous email before the swap takes effect — stricter, useful for tenants with higher-risk users."},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Controls what happens to `user.email` on subsequent OAuth/federated logins when the user previously changed their email manually through this auth server (i.e. `user.email_change_locked_at` is set).\n\n- `preserve_manual` (default): the manually-set email wins. The federated provider's email is ignored on re-sync; `email` and `email_verified` are not touched. The identity link stays valid via `provider_user_id`, so the user can still log in with Google/etc.\n- `always_sync`: the federated provider's email is always written back, overwriting any manual change. Useful for tenants whose source of truth for identity is the IdP (corporate SSO, etc.)."},"createdAt":{"type":"string","description":"AuthAccount creation date"},"updatedAt":{"type":"string","description":"AuthAccount updated date"}},"description":"AuthAccount"}}}}}}},"/connection":{"get":{"operationId":"connection/list","summary":"List Connections","tags":["connection"],"description":"List Connections","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"in":"query","name":"q","required":false,"description":"Full-text search across: `connection_name`, `connection_type`."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/Connection"}}},"additionalProperties":false}}}}}},"post":{"operationId":"connection/create","summary":"Create Connection","tags":["connection"],"description":"Create Connection","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["connection_name","connection_type"],"properties":{"connection_name":{"type":"string"},"connection_type":{"enum":["database","custom","github","figma","google_oauth2","oidc","passwordless_email"]},"authorize_url":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"issuer":{"type":"string"},"jwks_url":{"type":"string"},"scope":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"claims_mapping":{"type":"object","additionalProperties":{"type":"string"}},"authorize_params":{"type":"object","description":"Authorize params","default":{},"additionalProperties":{"type":"string"}},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Controls what happens to `user.email` on subsequent OAuth/federated logins when the user previously changed their email manually through this auth server (i.e. `user.email_change_locked_at` is set).\n\n- `preserve_manual` (default): the manually-set email wins. The federated provider's email is ignored on re-sync; `email` and `email_verified` are not touched. The identity link stays valid via `provider_user_id`, so the user can still log in with Google/etc.\n- `always_sync`: the federated provider's email is always written back, overwriting any manual change. Useful for tenants whose source of truth for identity is the IdP (corporate SSO, etc.)."},"password_policy":{"type":"object","required":["level"],"properties":{"level":{"anyOf":[{"type":"string","enum":["none"]},{"type":"string","enum":["low"]},{"type":"string","enum":["fair"]},{"type":"string","enum":["good"]},{"type":"string","enum":["excellent"]}]},"min_length":{"type":"integer","minimum":1,"maximum":128},"require_lowercase":{"type":"boolean"},"require_uppercase":{"type":"boolean"},"require_number":{"type":"boolean"},"require_special":{"type":"boolean"}},"description":"Password policy enforced when writing a password through this database connection (password reset and admin set-password). `level` is an Auth0-style preset (none/low/fair/good/excellent); the dashboard expands it into the explicit rule fields when saving. The rule fields override the preset baseline. When unset on the connection, the server applies the `good` default. Does not affect login."},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"ConnectionCreate","additionalProperties":false}}},"description":"ConnectionCreate"},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Connection","content":{"application/json":{"schema":{"type":"object","required":["id","connection_name","connection_type","authorize_url","token_url","userinfo_url","client_id","client_secret","issuer","jwks_url","response_type","enabled","enabled_clients","scope","authorize_params","is_using_default_credentials","account","createdAt"],"properties":{"id":{"type":"string","description":"Connection ID"},"connection_name":{"type":"string"},"connection_type":{"enum":["database","custom","github","figma","google_oauth2","oidc","passwordless_email"]},"authorize_url":{"type":"string","default":null},"token_url":{"type":"string","default":null},"userinfo_url":{"type":"string","default":null},"client_id":{"type":"string","default":null},"client_secret":{"type":"string","default":null},"issuer":{"type":"string","default":null},"jwks_url":{"type":"string","default":null},"response_type":{"type":"string","default":null},"enabled":{"type":"boolean"},"enabled_clients":{"type":"array","items":{"type":"string"},"default":null,"nullable":true},"scope":{"type":"array","items":{"type":"string"},"default":[]},"authorize_params":{"type":"object","description":"Authorize params","default":{},"additionalProperties":{"type":"string"}},"claims_mapping":{"type":"object","additionalProperties":{"type":"string"}},"is_using_default_credentials":{"type":"boolean","readOnly":true,"description":"Derived: true when the connection_type has shared Faable defaults AND the tenant has not set its own client_id/client_secret. Read-only — set by the server on every read."},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Per-connection override of `Account.email_oauth_sync_policy`. When set on a Connection, takes precedence over the Account-level setting for logins through this IdP. When unset (default), the Account-level policy applies. Use this to allow `always_sync` for a trusted IdP (e.g. corporate SSO) while keeping `preserve_manual` for others within the same tenant."},"password_policy":{"type":"object","required":["level"],"properties":{"level":{"anyOf":[{"type":"string","enum":["none"]},{"type":"string","enum":["low"]},{"type":"string","enum":["fair"]},{"type":"string","enum":["good"]},{"type":"string","enum":["excellent"]}]},"min_length":{"type":"integer","minimum":1,"maximum":128},"require_lowercase":{"type":"boolean"},"require_uppercase":{"type":"boolean"},"require_number":{"type":"boolean"},"require_special":{"type":"boolean"}},"description":"Password policy enforced when writing a password through this database connection (password reset and admin set-password). `level` is an Auth0-style preset (none/low/fair/good/excellent); the dashboard expands it into the explicit rule fields when saving. The rule fields override the preset baseline. When unset on the connection, the server applies the `good` default. Does not affect login."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ConnectionMetadata","default":{}},"createdAt":{"type":"string","description":"Connection creation date"},"updatedAt":{"type":"string","description":"Connection updated date"}},"description":"Connection"}}}}}}},"/connection/{connection_id}":{"get":{"operationId":"connection/get","summary":"Get Connection","tags":["connection"],"description":"Get Connection","parameters":[{"schema":{"type":"string"},"in":"path","name":"connection_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Connection","content":{"application/json":{"schema":{"type":"object","required":["id","connection_name","connection_type","authorize_url","token_url","userinfo_url","client_id","client_secret","issuer","jwks_url","response_type","enabled","enabled_clients","scope","authorize_params","is_using_default_credentials","account","createdAt"],"properties":{"id":{"type":"string","description":"Connection ID"},"connection_name":{"type":"string"},"connection_type":{"enum":["database","custom","github","figma","google_oauth2","oidc","passwordless_email"]},"authorize_url":{"type":"string","default":null},"token_url":{"type":"string","default":null},"userinfo_url":{"type":"string","default":null},"client_id":{"type":"string","default":null},"client_secret":{"type":"string","default":null},"issuer":{"type":"string","default":null},"jwks_url":{"type":"string","default":null},"response_type":{"type":"string","default":null},"enabled":{"type":"boolean"},"enabled_clients":{"type":"array","items":{"type":"string"},"default":null,"nullable":true},"scope":{"type":"array","items":{"type":"string"},"default":[]},"authorize_params":{"type":"object","description":"Authorize params","default":{},"additionalProperties":{"type":"string"}},"claims_mapping":{"type":"object","additionalProperties":{"type":"string"}},"is_using_default_credentials":{"type":"boolean","readOnly":true,"description":"Derived: true when the connection_type has shared Faable defaults AND the tenant has not set its own client_id/client_secret. Read-only — set by the server on every read."},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Per-connection override of `Account.email_oauth_sync_policy`. When set on a Connection, takes precedence over the Account-level setting for logins through this IdP. When unset (default), the Account-level policy applies. Use this to allow `always_sync` for a trusted IdP (e.g. corporate SSO) while keeping `preserve_manual` for others within the same tenant."},"password_policy":{"type":"object","required":["level"],"properties":{"level":{"anyOf":[{"type":"string","enum":["none"]},{"type":"string","enum":["low"]},{"type":"string","enum":["fair"]},{"type":"string","enum":["good"]},{"type":"string","enum":["excellent"]}]},"min_length":{"type":"integer","minimum":1,"maximum":128},"require_lowercase":{"type":"boolean"},"require_uppercase":{"type":"boolean"},"require_number":{"type":"boolean"},"require_special":{"type":"boolean"}},"description":"Password policy enforced when writing a password through this database connection (password reset and admin set-password). `level` is an Auth0-style preset (none/low/fair/good/excellent); the dashboard expands it into the explicit rule fields when saving. The rule fields override the preset baseline. When unset on the connection, the server applies the `good` default. Does not affect login."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ConnectionMetadata","default":{}},"createdAt":{"type":"string","description":"Connection creation date"},"updatedAt":{"type":"string","description":"Connection updated date"}},"description":"Connection"}}}}}},"post":{"operationId":"connection/update","summary":"Update Connection","tags":["connection"],"description":"Update Connection","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"connection_name":{"type":"string"},"enabled":{"type":"boolean"},"enabled_clients":{"type":"array","items":{"type":"string"}},"scope":{"type":"array","items":{"type":"string"}},"client_id":{"type":"string"},"client_secret":{"type":"string"},"issuer":{"type":"string"},"authorize_url":{"type":"string"},"token_url":{"type":"string"},"userinfo_url":{"type":"string"},"jwks_url":{"type":"string"},"response_type":{"type":"string"},"authorize_params":{"type":"object","description":"Authorize params","default":{},"additionalProperties":{"type":"string"}},"claims_mapping":{"type":"object","additionalProperties":{"type":"string"}},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]},{"type":"null"}]},"password_policy":{"anyOf":[{"type":"object","required":["level"],"properties":{"level":{"anyOf":[{"type":"string","enum":["none"]},{"type":"string","enum":["low"]},{"type":"string","enum":["fair"]},{"type":"string","enum":["good"]},{"type":"string","enum":["excellent"]}]},"min_length":{"type":"integer","minimum":1,"maximum":128},"require_lowercase":{"type":"boolean"},"require_uppercase":{"type":"boolean"},"require_number":{"type":"boolean"},"require_special":{"type":"boolean"}},"description":"Password policy enforced when writing a password through this database connection (password reset and admin set-password). `level` is an Auth0-style preset (none/low/fair/good/excellent); the dashboard expands it into the explicit rule fields when saving. The rule fields override the preset baseline. When unset on the connection, the server applies the `good` default. Does not affect login."},{"type":"null"}]}},"description":"Partial update for a Connection. Only the supplied fields are modified. `connection_type` is intentionally excluded — changing it would orphan every identity already linked to this connection.","additionalProperties":false}}},"description":"Partial update for a Connection. Only the supplied fields are modified. `connection_type` is intentionally excluded — changing it would orphan every identity already linked to this connection."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"connection_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Connection","content":{"application/json":{"schema":{"type":"object","required":["id","connection_name","connection_type","authorize_url","token_url","userinfo_url","client_id","client_secret","issuer","jwks_url","response_type","enabled","enabled_clients","scope","authorize_params","is_using_default_credentials","account","createdAt"],"properties":{"id":{"type":"string","description":"Connection ID"},"connection_name":{"type":"string"},"connection_type":{"enum":["database","custom","github","figma","google_oauth2","oidc","passwordless_email"]},"authorize_url":{"type":"string","default":null},"token_url":{"type":"string","default":null},"userinfo_url":{"type":"string","default":null},"client_id":{"type":"string","default":null},"client_secret":{"type":"string","default":null},"issuer":{"type":"string","default":null},"jwks_url":{"type":"string","default":null},"response_type":{"type":"string","default":null},"enabled":{"type":"boolean"},"enabled_clients":{"type":"array","items":{"type":"string"},"default":null,"nullable":true},"scope":{"type":"array","items":{"type":"string"},"default":[]},"authorize_params":{"type":"object","description":"Authorize params","default":{},"additionalProperties":{"type":"string"}},"claims_mapping":{"type":"object","additionalProperties":{"type":"string"}},"is_using_default_credentials":{"type":"boolean","readOnly":true,"description":"Derived: true when the connection_type has shared Faable defaults AND the tenant has not set its own client_id/client_secret. Read-only — set by the server on every read."},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Per-connection override of `Account.email_oauth_sync_policy`. When set on a Connection, takes precedence over the Account-level setting for logins through this IdP. When unset (default), the Account-level policy applies. Use this to allow `always_sync` for a trusted IdP (e.g. corporate SSO) while keeping `preserve_manual` for others within the same tenant."},"password_policy":{"type":"object","required":["level"],"properties":{"level":{"anyOf":[{"type":"string","enum":["none"]},{"type":"string","enum":["low"]},{"type":"string","enum":["fair"]},{"type":"string","enum":["good"]},{"type":"string","enum":["excellent"]}]},"min_length":{"type":"integer","minimum":1,"maximum":128},"require_lowercase":{"type":"boolean"},"require_uppercase":{"type":"boolean"},"require_number":{"type":"boolean"},"require_special":{"type":"boolean"}},"description":"Password policy enforced when writing a password through this database connection (password reset and admin set-password). `level` is an Auth0-style preset (none/low/fair/good/excellent); the dashboard expands it into the explicit rule fields when saving. The rule fields override the preset baseline. When unset on the connection, the server applies the `good` default. Does not affect login."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ConnectionMetadata","default":{}},"createdAt":{"type":"string","description":"Connection creation date"},"updatedAt":{"type":"string","description":"Connection updated date"}},"description":"Connection"}}}}}},"delete":{"operationId":"connection/delete","summary":"Delete Connection","tags":["connection"],"description":"Delete Connection","parameters":[{"schema":{"type":"string"},"in":"path","name":"connection_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Connection","content":{"application/json":{"schema":{"type":"object","required":["id","connection_name","connection_type","authorize_url","token_url","userinfo_url","client_id","client_secret","issuer","jwks_url","response_type","enabled","enabled_clients","scope","authorize_params","is_using_default_credentials","account","createdAt"],"properties":{"id":{"type":"string","description":"Connection ID"},"connection_name":{"type":"string"},"connection_type":{"enum":["database","custom","github","figma","google_oauth2","oidc","passwordless_email"]},"authorize_url":{"type":"string","default":null},"token_url":{"type":"string","default":null},"userinfo_url":{"type":"string","default":null},"client_id":{"type":"string","default":null},"client_secret":{"type":"string","default":null},"issuer":{"type":"string","default":null},"jwks_url":{"type":"string","default":null},"response_type":{"type":"string","default":null},"enabled":{"type":"boolean"},"enabled_clients":{"type":"array","items":{"type":"string"},"default":null,"nullable":true},"scope":{"type":"array","items":{"type":"string"},"default":[]},"authorize_params":{"type":"object","description":"Authorize params","default":{},"additionalProperties":{"type":"string"}},"claims_mapping":{"type":"object","additionalProperties":{"type":"string"}},"is_using_default_credentials":{"type":"boolean","readOnly":true,"description":"Derived: true when the connection_type has shared Faable defaults AND the tenant has not set its own client_id/client_secret. Read-only — set by the server on every read."},"email_oauth_sync_policy":{"anyOf":[{"type":"string","enum":["preserve_manual"]},{"type":"string","enum":["always_sync"]}],"description":"Per-connection override of `Account.email_oauth_sync_policy`. When set on a Connection, takes precedence over the Account-level setting for logins through this IdP. When unset (default), the Account-level policy applies. Use this to allow `always_sync` for a trusted IdP (e.g. corporate SSO) while keeping `preserve_manual` for others within the same tenant."},"password_policy":{"type":"object","required":["level"],"properties":{"level":{"anyOf":[{"type":"string","enum":["none"]},{"type":"string","enum":["low"]},{"type":"string","enum":["fair"]},{"type":"string","enum":["good"]},{"type":"string","enum":["excellent"]}]},"min_length":{"type":"integer","minimum":1,"maximum":128},"require_lowercase":{"type":"boolean"},"require_uppercase":{"type":"boolean"},"require_number":{"type":"boolean"},"require_special":{"type":"boolean"}},"description":"Password policy enforced when writing a password through this database connection (password reset and admin set-password). `level` is an Auth0-style preset (none/low/fair/good/excellent); the dashboard expands it into the explicit rule fields when saving. The rule fields override the preset baseline. When unset on the connection, the server applies the `good` default. Does not affect login."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ConnectionMetadata","default":{}},"createdAt":{"type":"string","description":"Connection creation date"},"updatedAt":{"type":"string","description":"Connection updated date"}},"description":"Connection"}}}}}}},"/client":{"get":{"operationId":"client/list","summary":"List Clients","tags":["client"],"description":"List Clients","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"in":"query","name":"q","required":false,"description":"Full-text search across: `name`, `description`, `client_id`."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/Client"}}},"additionalProperties":false}}}}}},"post":{"operationId":"client/create","summary":"Create Client","tags":["client"],"description":"Create Client","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"callbacks":{"type":"array","items":{"type":"string"}},"logout_urls":{"type":"array","items":{"type":"string"}},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"ClientCreate","additionalProperties":false}}},"description":"ClientCreate"},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Client","content":{"application/json":{"schema":{"type":"object","required":["id","name","description","client_id","client_secret","callbacks","logout_urls","refresh_token","account","createdAt"],"properties":{"id":{"type":"string","description":"Client ID"},"name":{"type":"string"},"description":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"callbacks":{"type":"array","items":{"type":"string"}},"logout_urls":{"type":"array","items":{"type":"string"}},"refresh_token":{"type":"object","required":["expiration_mode","infinite_token_lifetime","token_lifetime"],"properties":{"expiration_mode":{"enum":["expire","not-expire"]},"infinite_token_lifetime":{"type":"boolean"},"token_lifetime":{"type":"number"}}},"client_uri":{"type":"string","nullable":true},"logo_uri":{"type":"string","nullable":true},"tos_uri":{"type":"string","nullable":true},"policy_uri":{"type":"string","nullable":true},"contacts":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"application_type":{"type":"string"},"software_id":{"type":"string","nullable":true},"software_version":{"type":"string","nullable":true},"frontchannel_logout_uri":{"type":"string","nullable":true},"frontchannel_logout_session_required":{"type":"boolean"},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ClientMetadata","default":{}},"createdAt":{"type":"string","description":"Client creation date"},"updatedAt":{"type":"string","description":"Client updated date"}},"description":"Client"}}}}}}},"/client/{client_id}":{"get":{"operationId":"client/get","summary":"Get Client","tags":["client"],"description":"Get Client","parameters":[{"schema":{"type":"string"},"in":"path","name":"client_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Client","content":{"application/json":{"schema":{"type":"object","required":["id","name","description","client_id","client_secret","callbacks","logout_urls","refresh_token","account","createdAt"],"properties":{"id":{"type":"string","description":"Client ID"},"name":{"type":"string"},"description":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"callbacks":{"type":"array","items":{"type":"string"}},"logout_urls":{"type":"array","items":{"type":"string"}},"refresh_token":{"type":"object","required":["expiration_mode","infinite_token_lifetime","token_lifetime"],"properties":{"expiration_mode":{"enum":["expire","not-expire"]},"infinite_token_lifetime":{"type":"boolean"},"token_lifetime":{"type":"number"}}},"client_uri":{"type":"string","nullable":true},"logo_uri":{"type":"string","nullable":true},"tos_uri":{"type":"string","nullable":true},"policy_uri":{"type":"string","nullable":true},"contacts":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"application_type":{"type":"string"},"software_id":{"type":"string","nullable":true},"software_version":{"type":"string","nullable":true},"frontchannel_logout_uri":{"type":"string","nullable":true},"frontchannel_logout_session_required":{"type":"boolean"},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ClientMetadata","default":{}},"createdAt":{"type":"string","description":"Client creation date"},"updatedAt":{"type":"string","description":"Client updated date"}},"description":"Client"}}}}}},"post":{"operationId":"client/update","summary":"Update Client","tags":["client"],"description":"Update Client","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Human-readable client name shown in consent screens."},"description":{"type":"string","description":"Free-form description for internal admin use."},"callbacks":{"type":"array","items":{"type":"string"},"description":"Whitelist of allowed OAuth `redirect_uri` values."},"logout_urls":{"type":"array","items":{"type":"string"},"description":"Whitelist of allowed `post_logout_redirect_uri` values."},"refresh_token":{"type":"object","required":["expiration_mode","infinite_token_lifetime","token_lifetime"],"properties":{"expiration_mode":{"enum":["expire","not-expire"]},"infinite_token_lifetime":{"type":"boolean"},"token_lifetime":{"type":"number"}}},"client_uri":{"type":"string","nullable":true},"logo_uri":{"type":"string","nullable":true},"tos_uri":{"type":"string","nullable":true},"policy_uri":{"type":"string","nullable":true},"contacts":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"application_type":{"type":"string"},"software_id":{"type":"string","nullable":true},"software_version":{"type":"string","nullable":true},"frontchannel_logout_uri":{"type":"string","nullable":true},"frontchannel_logout_session_required":{"type":"boolean"}},"description":"Partial update for a Client. Only the supplied fields are modified. `client_id` and `client_secret` are not editable through this endpoint to prevent accidental rotation; use a dedicated endpoint when secret rotation is added.","additionalProperties":false}}},"description":"Partial update for a Client. Only the supplied fields are modified. `client_id` and `client_secret` are not editable through this endpoint to prevent accidental rotation; use a dedicated endpoint when secret rotation is added."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"client_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Client","content":{"application/json":{"schema":{"type":"object","required":["id","name","description","client_id","client_secret","callbacks","logout_urls","refresh_token","account","createdAt"],"properties":{"id":{"type":"string","description":"Client ID"},"name":{"type":"string"},"description":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"callbacks":{"type":"array","items":{"type":"string"}},"logout_urls":{"type":"array","items":{"type":"string"}},"refresh_token":{"type":"object","required":["expiration_mode","infinite_token_lifetime","token_lifetime"],"properties":{"expiration_mode":{"enum":["expire","not-expire"]},"infinite_token_lifetime":{"type":"boolean"},"token_lifetime":{"type":"number"}}},"client_uri":{"type":"string","nullable":true},"logo_uri":{"type":"string","nullable":true},"tos_uri":{"type":"string","nullable":true},"policy_uri":{"type":"string","nullable":true},"contacts":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"application_type":{"type":"string"},"software_id":{"type":"string","nullable":true},"software_version":{"type":"string","nullable":true},"frontchannel_logout_uri":{"type":"string","nullable":true},"frontchannel_logout_session_required":{"type":"boolean"},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ClientMetadata","default":{}},"createdAt":{"type":"string","description":"Client creation date"},"updatedAt":{"type":"string","description":"Client updated date"}},"description":"Client"}}}}}},"delete":{"operationId":"client/delete","summary":"Delete Client","tags":["client"],"description":"Delete Client","parameters":[{"schema":{"type":"string"},"in":"path","name":"client_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Client","content":{"application/json":{"schema":{"type":"object","required":["id","name","description","client_id","client_secret","callbacks","logout_urls","refresh_token","account","createdAt"],"properties":{"id":{"type":"string","description":"Client ID"},"name":{"type":"string"},"description":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"callbacks":{"type":"array","items":{"type":"string"}},"logout_urls":{"type":"array","items":{"type":"string"}},"refresh_token":{"type":"object","required":["expiration_mode","infinite_token_lifetime","token_lifetime"],"properties":{"expiration_mode":{"enum":["expire","not-expire"]},"infinite_token_lifetime":{"type":"boolean"},"token_lifetime":{"type":"number"}}},"client_uri":{"type":"string","nullable":true},"logo_uri":{"type":"string","nullable":true},"tos_uri":{"type":"string","nullable":true},"policy_uri":{"type":"string","nullable":true},"contacts":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"application_type":{"type":"string"},"software_id":{"type":"string","nullable":true},"software_version":{"type":"string","nullable":true},"frontchannel_logout_uri":{"type":"string","nullable":true},"frontchannel_logout_session_required":{"type":"boolean"},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ClientMetadata","default":{}},"createdAt":{"type":"string","description":"Client creation date"},"updatedAt":{"type":"string","description":"Client updated date"}},"description":"Client"}}}}}}},"/client/{client_id}/rotate-secret":{"post":{"operationId":"client/rotateSecret","summary":"Rotate a Client's secret","tags":["client"],"description":"Generates a fresh `client_secret` for the given Client and persists it. The previous secret is invalidated immediately — there is no grace period. Returns the full Client; the dashboard must surface the new secret to the admin once. Existing client_credentials / authorization_code integrations using the old secret will start failing at the token endpoint immediately after this call.","parameters":[{"schema":{"type":"string"},"in":"path","name":"client_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Client","content":{"application/json":{"schema":{"type":"object","required":["id","name","description","client_id","client_secret","callbacks","logout_urls","refresh_token","account","createdAt"],"properties":{"id":{"type":"string","description":"Client ID"},"name":{"type":"string"},"description":{"type":"string"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"callbacks":{"type":"array","items":{"type":"string"}},"logout_urls":{"type":"array","items":{"type":"string"}},"refresh_token":{"type":"object","required":["expiration_mode","infinite_token_lifetime","token_lifetime"],"properties":{"expiration_mode":{"enum":["expire","not-expire"]},"infinite_token_lifetime":{"type":"boolean"},"token_lifetime":{"type":"number"}}},"client_uri":{"type":"string","nullable":true},"logo_uri":{"type":"string","nullable":true},"tos_uri":{"type":"string","nullable":true},"policy_uri":{"type":"string","nullable":true},"contacts":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"application_type":{"type":"string"},"software_id":{"type":"string","nullable":true},"software_version":{"type":"string","nullable":true},"frontchannel_logout_uri":{"type":"string","nullable":true},"frontchannel_logout_session_required":{"type":"boolean"},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ClientMetadata","default":{}},"createdAt":{"type":"string","description":"Client creation date"},"updatedAt":{"type":"string","description":"Client updated date"}},"description":"Client"}}}}}}},"/user":{"get":{"operationId":"user/list","summary":"List Users","tags":["user"],"description":"List Users","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"in":"query","name":"q","required":false,"description":"Full-text search across: `name`, `email`, `phone`."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/User"}}},"additionalProperties":false}}}}}},"post":{"operationId":"user/create","summary":"Create User","tags":["user"],"description":"Create User","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"The user's full name."},"given_name":{"type":"string","description":"The user's given name."},"family_name":{"type":"string","description":"The user's family name."},"email":{"type":"string","description":"The user's email."},"phone":{"type":"string","description":"contact phone number"},"birth_date":{"type":"string","description":"The user's birth date"},"locale":{"type":"string","description":"The user's default locale lang."},"picture":{"type":"string","description":"A URI pointing to the user's picture."},"user_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"User Metadata"},"app_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"App Metadata"}},"description":"UserCreate","additionalProperties":false}}},"description":"UserCreate"},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"User","content":{"application/json":{"schema":{"type":"object","required":["id","email_verified","phone_verified","logins_count","user_metadata","app_metadata","account","createdAt"],"properties":{"id":{"type":"string","description":"User ID"},"name":{"type":"string","description":"User name","nullable":true},"username":{"type":"string","description":"unique username for this user","nullable":true},"given_name":{"type":"string","description":"Given name","nullable":true},"family_name":{"type":"string","description":"Family name","nullable":true},"middle_name":{"type":"string","description":"Middle name (OIDC §5.1)","nullable":true},"nickname":{"type":"string","description":"Casual name. Distinct from given_name (e.g. \"Mike\" vs \"Michael\"). OIDC §5.1","nullable":true},"email":{"type":"string","description":"User email","nullable":true},"email_verified":{"type":"boolean","description":"true if email is verified","default":false},"email_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `email_verified` was last set. `manual` — admin flipped the flag via `POST /user/:id`. `verification_flow` — user clicked the verification link. `passwordless_otp` — user completed passwordless OTP login. `team_invite` — user clicked a team invitation link. `email_change` — user confirmed a self-service email change. `federated` — verified by the external IdP on OAuth callback. `null` — the field was cleared (admin un-verified the email)."},"email_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `email_verified` was last flipped to true.","nullable":true},"email_change_locked_at":{"type":"string","description":"ISO 8601 timestamp of the user's last verified email change. When set, OAuth callbacks will not overwrite `email`/`email_verified` from the federated provider — the manually-chosen email wins.","nullable":true},"email_bounced_at":{"type":"string","description":"ISO 8601 timestamp of the last Postmark hard bounce / spam complaint for this address. When set, the email is treated as undeliverable and no further emails are sent to the user until the address changes.","nullable":true},"phone":{"type":"string","description":"contact phone number","nullable":true},"phone_verified":{"type":"boolean","description":"phone is verified"},"phone_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `phone_verified` was last set. Same enum as `email_verified_method`."},"phone_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `phone_verified` was last flipped to true.","nullable":true},"country_iso":{"type":"string","description":"country iso code","nullable":true},"birth_date":{"type":"string","description":"user birth_date","nullable":true},"gender":{"type":"string","description":"User gender (free-form, OIDC §5.1)","nullable":true},"zoneinfo":{"type":"string","description":"IANA time-zone name (e.g. \"Europe/Madrid\"). OIDC §5.1 — used for the `zoneinfo` claim.","nullable":true},"locale":{"type":"string","description":"user main language","nullable":true},"region":{"type":"string","description":"customer region","nullable":true},"website":{"type":"string","description":"URL of the User's personal Web page or blog (OIDC §5.1)","nullable":true},"address":{"type":"object","properties":{"formatted":{"type":"string","description":"Full mailing address, formatted for display (may contain newlines)","nullable":true},"street_address":{"type":"string","nullable":true},"locality":{"type":"string","description":"City or locality","nullable":true},"region":{"type":"string","description":"State, province, or region","nullable":true},"postal_code":{"type":"string","nullable":true},"country":{"type":"string","description":"Country name","nullable":true}},"additionalProperties":false,"nullable":true},"picture":{"type":"string","description":"User picture url","nullable":true},"logins_count":{"type":"number","description":"Total number of logins this user has performed."},"last_ip":{"type":"string","description":"Last IP address from which this user logged in","nullable":true},"last_login":{"type":"string","description":"Last date and time this user logged in (ISO_8601 format)","nullable":true},"user_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"User Metadata","default":{}},"app_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"App Metadata","default":{}},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"UserMetadata","default":{}},"createdAt":{"type":"string","description":"User creation date"},"updatedAt":{"type":"string","description":"User updated date"}},"description":"User"}}}}}}},"/user/{user_id}":{"get":{"operationId":"user/get","summary":"Get User","tags":["user"],"description":"Get User","parameters":[{"schema":{"type":"string"},"in":"path","name":"user_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"User","content":{"application/json":{"schema":{"type":"object","required":["id","email_verified","phone_verified","logins_count","user_metadata","app_metadata","account","createdAt"],"properties":{"id":{"type":"string","description":"User ID"},"name":{"type":"string","description":"User name","nullable":true},"username":{"type":"string","description":"unique username for this user","nullable":true},"given_name":{"type":"string","description":"Given name","nullable":true},"family_name":{"type":"string","description":"Family name","nullable":true},"middle_name":{"type":"string","description":"Middle name (OIDC §5.1)","nullable":true},"nickname":{"type":"string","description":"Casual name. Distinct from given_name (e.g. \"Mike\" vs \"Michael\"). OIDC §5.1","nullable":true},"email":{"type":"string","description":"User email","nullable":true},"email_verified":{"type":"boolean","description":"true if email is verified","default":false},"email_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `email_verified` was last set. `manual` — admin flipped the flag via `POST /user/:id`. `verification_flow` — user clicked the verification link. `passwordless_otp` — user completed passwordless OTP login. `team_invite` — user clicked a team invitation link. `email_change` — user confirmed a self-service email change. `federated` — verified by the external IdP on OAuth callback. `null` — the field was cleared (admin un-verified the email)."},"email_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `email_verified` was last flipped to true.","nullable":true},"email_change_locked_at":{"type":"string","description":"ISO 8601 timestamp of the user's last verified email change. When set, OAuth callbacks will not overwrite `email`/`email_verified` from the federated provider — the manually-chosen email wins.","nullable":true},"email_bounced_at":{"type":"string","description":"ISO 8601 timestamp of the last Postmark hard bounce / spam complaint for this address. When set, the email is treated as undeliverable and no further emails are sent to the user until the address changes.","nullable":true},"phone":{"type":"string","description":"contact phone number","nullable":true},"phone_verified":{"type":"boolean","description":"phone is verified"},"phone_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `phone_verified` was last set. Same enum as `email_verified_method`."},"phone_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `phone_verified` was last flipped to true.","nullable":true},"country_iso":{"type":"string","description":"country iso code","nullable":true},"birth_date":{"type":"string","description":"user birth_date","nullable":true},"gender":{"type":"string","description":"User gender (free-form, OIDC §5.1)","nullable":true},"zoneinfo":{"type":"string","description":"IANA time-zone name (e.g. \"Europe/Madrid\"). OIDC §5.1 — used for the `zoneinfo` claim.","nullable":true},"locale":{"type":"string","description":"user main language","nullable":true},"region":{"type":"string","description":"customer region","nullable":true},"website":{"type":"string","description":"URL of the User's personal Web page or blog (OIDC §5.1)","nullable":true},"address":{"type":"object","properties":{"formatted":{"type":"string","description":"Full mailing address, formatted for display (may contain newlines)","nullable":true},"street_address":{"type":"string","nullable":true},"locality":{"type":"string","description":"City or locality","nullable":true},"region":{"type":"string","description":"State, province, or region","nullable":true},"postal_code":{"type":"string","nullable":true},"country":{"type":"string","description":"Country name","nullable":true}},"additionalProperties":false,"nullable":true},"picture":{"type":"string","description":"User picture url","nullable":true},"logins_count":{"type":"number","description":"Total number of logins this user has performed."},"last_ip":{"type":"string","description":"Last IP address from which this user logged in","nullable":true},"last_login":{"type":"string","description":"Last date and time this user logged in (ISO_8601 format)","nullable":true},"user_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"User Metadata","default":{}},"app_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"App Metadata","default":{}},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"UserMetadata","default":{}},"createdAt":{"type":"string","description":"User creation date"},"updatedAt":{"type":"string","description":"User updated date"}},"description":"User"}}}}}},"post":{"operationId":"user/update","summary":"Update User","tags":["user"],"description":"Update User","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"name"},"given_name":{"type":"string","description":"given name"},"family_name":{"type":"string","description":"family name"},"email":{"type":"string","description":"Contact email. Changing the email to a new value automatically resets `email_verified` to false (and clears `email_verified_method` / `email_verified_at`) unless the same patch sets `email_verified` explicitly. The override is the documented way to import a pre-verified user from another IdP."},"email_verified":{"type":"boolean","description":"Flip the email verification flag. Setting `true` marks the email as verified by the admin (`email_verified_method=manual`). Setting `false` clears the verification metadata."},"phone":{"type":"string","description":"Contact phone number. Changing it to a new value automatically resets `phone_verified` to false (and clears `phone_verified_method` / `phone_verified_at`) unless the same patch sets `phone_verified` explicitly."},"phone_verified":{"type":"boolean","description":"Flip the phone verification flag. Setting `true` marks the phone as verified by the admin (`phone_verified_method=manual`)."},"country_iso":{"type":"string","description":"user country as iso string"},"birth_date":{"type":"string","description":"user birth_date"},"locale":{"type":"string","description":"user main language","nullable":true},"picture":{"type":"string","description":"User picture url"},"user_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"User defined metadata"},"app_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"App defined metadata"}},"description":"UserUpdate","additionalProperties":false}}},"description":"UserUpdate"},"parameters":[{"schema":{"type":"string"},"in":"path","name":"user_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"User","content":{"application/json":{"schema":{"type":"object","required":["id","email_verified","phone_verified","logins_count","user_metadata","app_metadata","account","createdAt"],"properties":{"id":{"type":"string","description":"User ID"},"name":{"type":"string","description":"User name","nullable":true},"username":{"type":"string","description":"unique username for this user","nullable":true},"given_name":{"type":"string","description":"Given name","nullable":true},"family_name":{"type":"string","description":"Family name","nullable":true},"middle_name":{"type":"string","description":"Middle name (OIDC §5.1)","nullable":true},"nickname":{"type":"string","description":"Casual name. Distinct from given_name (e.g. \"Mike\" vs \"Michael\"). OIDC §5.1","nullable":true},"email":{"type":"string","description":"User email","nullable":true},"email_verified":{"type":"boolean","description":"true if email is verified","default":false},"email_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `email_verified` was last set. `manual` — admin flipped the flag via `POST /user/:id`. `verification_flow` — user clicked the verification link. `passwordless_otp` — user completed passwordless OTP login. `team_invite` — user clicked a team invitation link. `email_change` — user confirmed a self-service email change. `federated` — verified by the external IdP on OAuth callback. `null` — the field was cleared (admin un-verified the email)."},"email_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `email_verified` was last flipped to true.","nullable":true},"email_change_locked_at":{"type":"string","description":"ISO 8601 timestamp of the user's last verified email change. When set, OAuth callbacks will not overwrite `email`/`email_verified` from the federated provider — the manually-chosen email wins.","nullable":true},"email_bounced_at":{"type":"string","description":"ISO 8601 timestamp of the last Postmark hard bounce / spam complaint for this address. When set, the email is treated as undeliverable and no further emails are sent to the user until the address changes.","nullable":true},"phone":{"type":"string","description":"contact phone number","nullable":true},"phone_verified":{"type":"boolean","description":"phone is verified"},"phone_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `phone_verified` was last set. Same enum as `email_verified_method`."},"phone_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `phone_verified` was last flipped to true.","nullable":true},"country_iso":{"type":"string","description":"country iso code","nullable":true},"birth_date":{"type":"string","description":"user birth_date","nullable":true},"gender":{"type":"string","description":"User gender (free-form, OIDC §5.1)","nullable":true},"zoneinfo":{"type":"string","description":"IANA time-zone name (e.g. \"Europe/Madrid\"). OIDC §5.1 — used for the `zoneinfo` claim.","nullable":true},"locale":{"type":"string","description":"user main language","nullable":true},"region":{"type":"string","description":"customer region","nullable":true},"website":{"type":"string","description":"URL of the User's personal Web page or blog (OIDC §5.1)","nullable":true},"address":{"type":"object","properties":{"formatted":{"type":"string","description":"Full mailing address, formatted for display (may contain newlines)","nullable":true},"street_address":{"type":"string","nullable":true},"locality":{"type":"string","description":"City or locality","nullable":true},"region":{"type":"string","description":"State, province, or region","nullable":true},"postal_code":{"type":"string","nullable":true},"country":{"type":"string","description":"Country name","nullable":true}},"additionalProperties":false,"nullable":true},"picture":{"type":"string","description":"User picture url","nullable":true},"logins_count":{"type":"number","description":"Total number of logins this user has performed."},"last_ip":{"type":"string","description":"Last IP address from which this user logged in","nullable":true},"last_login":{"type":"string","description":"Last date and time this user logged in (ISO_8601 format)","nullable":true},"user_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"User Metadata","default":{}},"app_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"App Metadata","default":{}},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"UserMetadata","default":{}},"createdAt":{"type":"string","description":"User creation date"},"updatedAt":{"type":"string","description":"User updated date"}},"description":"User"}}}}}},"delete":{"operationId":"user/delete","summary":"Delete User","tags":["user"],"description":"Delete User","parameters":[{"schema":{"type":"string"},"in":"path","name":"user_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"User","content":{"application/json":{"schema":{"type":"object","required":["id","email_verified","phone_verified","logins_count","user_metadata","app_metadata","account","createdAt"],"properties":{"id":{"type":"string","description":"User ID"},"name":{"type":"string","description":"User name","nullable":true},"username":{"type":"string","description":"unique username for this user","nullable":true},"given_name":{"type":"string","description":"Given name","nullable":true},"family_name":{"type":"string","description":"Family name","nullable":true},"middle_name":{"type":"string","description":"Middle name (OIDC §5.1)","nullable":true},"nickname":{"type":"string","description":"Casual name. Distinct from given_name (e.g. \"Mike\" vs \"Michael\"). OIDC §5.1","nullable":true},"email":{"type":"string","description":"User email","nullable":true},"email_verified":{"type":"boolean","description":"true if email is verified","default":false},"email_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `email_verified` was last set. `manual` — admin flipped the flag via `POST /user/:id`. `verification_flow` — user clicked the verification link. `passwordless_otp` — user completed passwordless OTP login. `team_invite` — user clicked a team invitation link. `email_change` — user confirmed a self-service email change. `federated` — verified by the external IdP on OAuth callback. `null` — the field was cleared (admin un-verified the email)."},"email_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `email_verified` was last flipped to true.","nullable":true},"email_change_locked_at":{"type":"string","description":"ISO 8601 timestamp of the user's last verified email change. When set, OAuth callbacks will not overwrite `email`/`email_verified` from the federated provider — the manually-chosen email wins.","nullable":true},"email_bounced_at":{"type":"string","description":"ISO 8601 timestamp of the last Postmark hard bounce / spam complaint for this address. When set, the email is treated as undeliverable and no further emails are sent to the user until the address changes.","nullable":true},"phone":{"type":"string","description":"contact phone number","nullable":true},"phone_verified":{"type":"boolean","description":"phone is verified"},"phone_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `phone_verified` was last set. Same enum as `email_verified_method`."},"phone_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `phone_verified` was last flipped to true.","nullable":true},"country_iso":{"type":"string","description":"country iso code","nullable":true},"birth_date":{"type":"string","description":"user birth_date","nullable":true},"gender":{"type":"string","description":"User gender (free-form, OIDC §5.1)","nullable":true},"zoneinfo":{"type":"string","description":"IANA time-zone name (e.g. \"Europe/Madrid\"). OIDC §5.1 — used for the `zoneinfo` claim.","nullable":true},"locale":{"type":"string","description":"user main language","nullable":true},"region":{"type":"string","description":"customer region","nullable":true},"website":{"type":"string","description":"URL of the User's personal Web page or blog (OIDC §5.1)","nullable":true},"address":{"type":"object","properties":{"formatted":{"type":"string","description":"Full mailing address, formatted for display (may contain newlines)","nullable":true},"street_address":{"type":"string","nullable":true},"locality":{"type":"string","description":"City or locality","nullable":true},"region":{"type":"string","description":"State, province, or region","nullable":true},"postal_code":{"type":"string","nullable":true},"country":{"type":"string","description":"Country name","nullable":true}},"additionalProperties":false,"nullable":true},"picture":{"type":"string","description":"User picture url","nullable":true},"logins_count":{"type":"number","description":"Total number of logins this user has performed."},"last_ip":{"type":"string","description":"Last IP address from which this user logged in","nullable":true},"last_login":{"type":"string","description":"Last date and time this user logged in (ISO_8601 format)","nullable":true},"user_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"User Metadata","default":{}},"app_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"App Metadata","default":{}},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"UserMetadata","default":{}},"createdAt":{"type":"string","description":"User creation date"},"updatedAt":{"type":"string","description":"User updated date"}},"description":"User"}}}}}}},"/user/{user_id}/change-email":{"post":{"operationId":"user/changeEmail","summary":"Start the user's email change flow","tags":["user"],"description":"Initiates the email-change flow for the given user. Validates the new email, ensures it is not already in use in the tenant, revokes any pending change for the same user, creates a Ticket (`type='change_email'`), and sends a verification email to the new address. Re-authentication is not required — an active session/Bearer is enough. The change does NOT take effect until the user clicks the link in the email and confirms via `/change-email-confirm`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["new_email"],"properties":{"new_email":{"type":"string","description":"The email address the user wants to switch to."},"verification_mode":{"anyOf":[{"type":"string","enum":["new_only"]},{"type":"string","enum":["old_and_new"]}],"description":"Override the account-wide policy. Can only raise the bar: passing `old_and_new` forces double verification; `new_only` is ignored if the account requires `old_and_new`."},"redirect_uri":{"type":"string","description":"Where to send the user after they click the link in the verification email. The status of the operation is appended as a `?status=applied|pending_old` query param so the calling app can render the right screen. When omitted, the user lands on the auth host's `/flow/email-change-done` fallback."}},"additionalProperties":false,"description":"Payload for `POST /user/:user_id/change-email`. Triggers the verification flow: a Ticket is created and an email is sent to the new address with a confirmation link."}}},"description":"Payload for `POST /user/:user_id/change-email`. Triggers the verification flow: a Ticket is created and an email is sent to the new address with a confirmation link."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"user_id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["status","ticket_id","verification_mode"],"properties":{"status":{"type":"string","enum":["verification_sent"]},"ticket_id":{"type":"string"},"verification_mode":{"anyOf":[{"type":"string","enum":["new_only"]},{"type":"string","enum":["old_and_new"]}]}}}}}}}}},"/change-email-verify":{"get":{"operationId":"user_change_email_verify","summary":"Verify a change-email ticket and apply the change","tags":["user"],"description":"Entry point for the link sent to the new email. Consumes the ticket, applies the email swap (in `new_only` mode) or issues a secondary verification ticket to the old email (in `old_and_new` mode, first step). Redirects to the `redirect_uri` supplied at flow start with `?status=applied|pending_old` appended; falls back to `/flow/email-change-done` on the auth host when no `redirect_uri` was given.","parameters":[{"schema":{"type":"string"},"in":"query","name":"ticket","required":true}],"responses":{"200":{"description":"Default Response"}}}},"/user/{user_id}/verify-email/start":{"post":{"operationId":"user/verifyEmailStart","summary":"Start the user's email verification flow","tags":["user"],"description":"Initiates the email-verification flow for the given user. Creates a `verify_email` Ticket and queues the verification email. Idempotent — returns `{status:'already_verified'}` without emitting a ticket if the user is already verified. Re-authentication is not required: an active session/Bearer is enough.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"redirect_uri":{"type":"string","description":"Where to send the user after they click the link. The status of the operation is appended as `?status=verified|already_verified|invalid_link|expired` so the calling app can render the right screen. When omitted, the user lands on the auth host's `/flow/verify-email-done` fallback."}},"additionalProperties":false,"description":"Optional payload for `POST /user/:user_id/verify-email/start`. Trigger a verification email send for the given user."}}},"description":"Optional payload for `POST /user/:user_id/verify-email/start`. Trigger a verification email send for the given user."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"user_id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"anyOf":[{"type":"string","enum":["verification_sent"]},{"type":"string","enum":["already_verified"]}]},"ticket_id":{"type":"string"}}}}}}}}},"/verify-email":{"get":{"operationId":"user_verify_email_confirm","summary":"Verify a verify-email ticket and mark the user verified","tags":["user"],"description":"Entry point for the link sent to the user. Consumes the ticket, sets `email_verified=true` with `email_verified_method='verification_flow'`. Redirects to the `redirect_uri` supplied at start with `?status=verified|already_verified` appended; falls back to `/flow/verify-email-done` on the auth host when no `redirect_uri` was given. Invalid/expired tickets redirect to the same fallback with `?status=invalid_link` or `?status=expired`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"ticket","required":true}],"responses":{"200":{"description":"Default Response"}}}},"/identity":{"get":{"operationId":"identity/list","summary":"List Identitys","tags":["identity"],"description":"List Identitys","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"array","items":{"type":"string","enum":["user","connection"],"description":"Allowed expand paths on `identity`: `user`, `connection`."},"maxItems":2},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `?expand=user`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/Identity"}}},"additionalProperties":false}}}}}},"post":{"operationId":"identity/create","summary":"Create Identity","tags":["identity"],"description":"Create Identity","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["account","user","identity_id","connection","profile_data"],"properties":{"account":{"type":"string"},"user":{"type":"string"},"identity_id":{"type":"string"},"connection":{"type":"string"},"access_token":{"type":"string"},"access_token_secret":{"type":"string"},"refresh_token":{"type":"string"},"profile_data":{}}}}}},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Identity","content":{"application/json":{"schema":{"type":"object","required":["id","connection","user","identity_id","profile_data","account","createdAt"],"properties":{"id":{"type":"string","description":"Identity ID"},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"identity_id":{"type":"string"},"access_token":{"type":"string"},"access_token_secret":{"type":"string"},"refresh_token":{"type":"string"},"access_token_expires_at":{"type":"string","description":"ISO 8601 timestamp when the stored provider `access_token` expires. Stamped from the provider `expires_in` on (re-)authorization and refresh. Absent when the provider issues non-expiring tokens."},"profile_data":{},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"IdentityMetadata","default":{}},"createdAt":{"type":"string","description":"Identity creation date"},"updatedAt":{"type":"string","description":"Identity updated date"}},"description":"Identity"}}}}}}},"/identity/{identity_id}":{"get":{"operationId":"identity/get","summary":"Get Identity","tags":["identity"],"description":"Get Identity","parameters":[{"schema":{"type":"array","items":{"type":"string","enum":["user","connection"],"description":"Allowed expand paths on `identity`: `user`, `connection`."},"maxItems":2},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `?expand=user`)."},{"schema":{"type":"string"},"in":"path","name":"identity_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Identity","content":{"application/json":{"schema":{"type":"object","required":["id","connection","user","identity_id","profile_data","account","createdAt"],"properties":{"id":{"type":"string","description":"Identity ID"},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"identity_id":{"type":"string"},"access_token":{"type":"string"},"access_token_secret":{"type":"string"},"refresh_token":{"type":"string"},"access_token_expires_at":{"type":"string","description":"ISO 8601 timestamp when the stored provider `access_token` expires. Stamped from the provider `expires_in` on (re-)authorization and refresh. Absent when the provider issues non-expiring tokens."},"profile_data":{},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"IdentityMetadata","default":{}},"createdAt":{"type":"string","description":"Identity creation date"},"updatedAt":{"type":"string","description":"Identity updated date"}},"description":"Identity"}}}}}},"delete":{"operationId":"identity/delete","summary":"Delete Identity","tags":["identity"],"description":"Delete Identity","parameters":[{"schema":{"type":"string"},"in":"path","name":"identity_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Identity","content":{"application/json":{"schema":{"type":"object","required":["id","connection","user","identity_id","profile_data","account","createdAt"],"properties":{"id":{"type":"string","description":"Identity ID"},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"identity_id":{"type":"string"},"access_token":{"type":"string"},"access_token_secret":{"type":"string"},"refresh_token":{"type":"string"},"access_token_expires_at":{"type":"string","description":"ISO 8601 timestamp when the stored provider `access_token` expires. Stamped from the provider `expires_in` on (re-)authorization and refresh. Absent when the provider issues non-expiring tokens."},"profile_data":{},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"IdentityMetadata","default":{}},"createdAt":{"type":"string","description":"Identity creation date"},"updatedAt":{"type":"string","description":"Identity updated date"}},"description":"Identity"}}}}}}},"/identity/{identity_id}/provider-token":{"get":{"operationId":"identity/getProviderToken","summary":"Get a guaranteed-valid provider access_token","tags":["identity"],"description":"Returns the identity's upstream provider `access_token`, refreshing it transparently via the stored `refresh_token` when it is (about to be) expired. Pass `?fresh=true` to force a refresh. Fails with 400 when the token is expired and no `refresh_token` is available (the user must re-authorize).","parameters":[{"schema":{"type":"boolean"},"in":"query","name":"fresh","required":false,"description":"Force a refresh against the provider even when the stored token still looks valid."},{"schema":{"type":"string"},"in":"path","name":"identity_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["access_token","refreshed"],"properties":{"access_token":{"type":"string"},"access_token_expires_at":{"type":"string"},"refreshed":{"type":"boolean"}}}}}}}}},"/credentials":{"get":{"operationId":"credentials/list","summary":"List Credentialss","tags":["credentials"],"description":"List Credentialss","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"array","items":{"type":"string","enum":["user","connection"],"description":"Allowed expand paths on `credentials`: `user`, `connection`."},"maxItems":2},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `?expand=user`)."},{"schema":{"type":"string","minLength":1,"maxLength":200},"in":"query","name":"q","required":false,"description":"Full-text search across: `email`, `username`."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/Credential"}}},"additionalProperties":false}}}}}},"post":{"operationId":"credentials/create","summary":"Create Credentials","tags":["credentials"],"description":"Create Credentials","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["user","connection"],"properties":{"user":{"type":"string"},"connection":{"type":"string"},"email":{"type":"string"},"username":{"type":"string"}}}}}},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Credential","content":{"application/json":{"schema":{"type":"object","required":["id","connection","user","account","createdAt"],"properties":{"id":{"type":"string","description":"Credential ID"},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"email":{"type":"string","description":"Email login identifier (unique within the connection)."},"username":{"type":"string","description":"Username login identifier (unique within the connection)."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CredentialMetadata","default":{}},"createdAt":{"type":"string","description":"Credential creation date"},"updatedAt":{"type":"string","description":"Credential updated date"}},"description":"Credential"}}}}}}},"/credentials/{credentials_id}":{"get":{"operationId":"credentials/get","summary":"Get Credentials","tags":["credentials"],"description":"Get Credentials","parameters":[{"schema":{"type":"array","items":{"type":"string","enum":["user","connection"],"description":"Allowed expand paths on `credentials`: `user`, `connection`."},"maxItems":2},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `?expand=user`)."},{"schema":{"type":"string"},"in":"path","name":"credentials_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Credential","content":{"application/json":{"schema":{"type":"object","required":["id","connection","user","account","createdAt"],"properties":{"id":{"type":"string","description":"Credential ID"},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"email":{"type":"string","description":"Email login identifier (unique within the connection)."},"username":{"type":"string","description":"Username login identifier (unique within the connection)."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CredentialMetadata","default":{}},"createdAt":{"type":"string","description":"Credential creation date"},"updatedAt":{"type":"string","description":"Credential updated date"}},"description":"Credential"}}}}}},"post":{"operationId":"credentials/update","summary":"Update Credentials","tags":["credentials"],"description":"Update Credentials","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string"},"username":{"type":"string"}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"credentials_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Credential","content":{"application/json":{"schema":{"type":"object","required":["id","connection","user","account","createdAt"],"properties":{"id":{"type":"string","description":"Credential ID"},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"email":{"type":"string","description":"Email login identifier (unique within the connection)."},"username":{"type":"string","description":"Username login identifier (unique within the connection)."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CredentialMetadata","default":{}},"createdAt":{"type":"string","description":"Credential creation date"},"updatedAt":{"type":"string","description":"Credential updated date"}},"description":"Credential"}}}}}},"delete":{"operationId":"credentials/delete","summary":"Delete Credentials","tags":["credentials"],"description":"Delete Credentials","parameters":[{"schema":{"type":"string"},"in":"path","name":"credentials_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Credential","content":{"application/json":{"schema":{"type":"object","required":["id","connection","user","account","createdAt"],"properties":{"id":{"type":"string","description":"Credential ID"},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"email":{"type":"string","description":"Email login identifier (unique within the connection)."},"username":{"type":"string","description":"Username login identifier (unique within the connection)."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CredentialMetadata","default":{}},"createdAt":{"type":"string","description":"Credential creation date"},"updatedAt":{"type":"string","description":"Credential updated date"}},"description":"Credential"}}}}}}},"/credentials/{credentials_id}/set-password":{"post":{"operationId":"credentials/setPassword","summary":"Set a credential's password","tags":["credentials"],"description":"Sets or rotates the password for a database credential. The previous password is invalidated immediately. Records a `credential.password_changed` audit entry (initiated_by=admin) for traceability. The password is never returned.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["password"],"properties":{"password":{"type":"string","description":"New plaintext password (hashed on write)."}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"credentials_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Credential","content":{"application/json":{"schema":{"type":"object","required":["id","connection","user","account","createdAt"],"properties":{"id":{"type":"string","description":"Credential ID"},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"email":{"type":"string","description":"Email login identifier (unique within the connection)."},"username":{"type":"string","description":"Username login identifier (unique within the connection)."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CredentialMetadata","default":{}},"createdAt":{"type":"string","description":"Credential creation date"},"updatedAt":{"type":"string","description":"Credential updated date"}},"description":"Credential"}}}}}}},"/role":{"get":{"operationId":"role/list","summary":"List Roles","tags":["role"],"description":"List Roles","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"in":"query","name":"q","required":false,"description":"Full-text search across: `name`, `description`."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/Role"}}},"additionalProperties":false}}}}}},"post":{"operationId":"role/create","summary":"Create Role","tags":["role"],"description":"Create Role","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Short, human-readable identifier for the role (e.g. `admin`, `editor`).","example":"admin"},"description":{"type":"string","description":"Free-form explanation of what users in this role are expected to do or have access to."},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"RoleCreate","additionalProperties":false}}},"description":"RoleCreate"},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Role","content":{"application/json":{"schema":{"type":"object","required":["id","name","description","account","createdAt"],"properties":{"id":{"type":"string","description":"Role ID"},"name":{"type":"string","description":"Short, human-readable identifier for the role (e.g. `admin`, `editor`, `billing-manager`). Surfaced in the dashboard role pickers.","example":"admin"},"description":{"type":"string","description":"Free-form explanation of what users in this role are expected to do or have access to. Shown alongside the role in the dashboard."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"RoleMetadata","default":{}},"createdAt":{"type":"string","description":"Role creation date"},"updatedAt":{"type":"string","description":"Role updated date"}},"description":"Role"}}}}}}},"/role/{role_id}":{"get":{"operationId":"role/get","summary":"Get Role","tags":["role"],"description":"Get Role","parameters":[{"schema":{"type":"string"},"in":"path","name":"role_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Role","content":{"application/json":{"schema":{"type":"object","required":["id","name","description","account","createdAt"],"properties":{"id":{"type":"string","description":"Role ID"},"name":{"type":"string","description":"Short, human-readable identifier for the role (e.g. `admin`, `editor`, `billing-manager`). Surfaced in the dashboard role pickers.","example":"admin"},"description":{"type":"string","description":"Free-form explanation of what users in this role are expected to do or have access to. Shown alongside the role in the dashboard."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"RoleMetadata","default":{}},"createdAt":{"type":"string","description":"Role creation date"},"updatedAt":{"type":"string","description":"Role updated date"}},"description":"Role"}}}}}},"post":{"operationId":"role/update","summary":"Update Role","tags":["role"],"description":"Update Role","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New human-readable identifier for the role."},"description":{"type":"string","description":"New free-form description of what users in this role do."}},"description":"Partial update for a Role. Only the supplied fields are modified.","additionalProperties":false}}},"description":"Partial update for a Role. Only the supplied fields are modified."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"role_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Role","content":{"application/json":{"schema":{"type":"object","required":["id","name","description","account","createdAt"],"properties":{"id":{"type":"string","description":"Role ID"},"name":{"type":"string","description":"Short, human-readable identifier for the role (e.g. `admin`, `editor`, `billing-manager`). Surfaced in the dashboard role pickers.","example":"admin"},"description":{"type":"string","description":"Free-form explanation of what users in this role are expected to do or have access to. Shown alongside the role in the dashboard."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"RoleMetadata","default":{}},"createdAt":{"type":"string","description":"Role creation date"},"updatedAt":{"type":"string","description":"Role updated date"}},"description":"Role"}}}}}},"delete":{"operationId":"role/delete","summary":"Delete Role","tags":["role"],"description":"Delete Role","parameters":[{"schema":{"type":"string"},"in":"path","name":"role_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Role","content":{"application/json":{"schema":{"type":"object","required":["id","name","description","account","createdAt"],"properties":{"id":{"type":"string","description":"Role ID"},"name":{"type":"string","description":"Short, human-readable identifier for the role (e.g. `admin`, `editor`, `billing-manager`). Surfaced in the dashboard role pickers.","example":"admin"},"description":{"type":"string","description":"Free-form explanation of what users in this role are expected to do or have access to. Shown alongside the role in the dashboard."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"RoleMetadata","default":{}},"createdAt":{"type":"string","description":"Role creation date"},"updatedAt":{"type":"string","description":"Role updated date"}},"description":"Role"}}}}}}},"/role/{role_id}/users":{"get":{"operationId":"role/users","summary":"List Users with Role","tags":["role"],"description":"List Users with Role","parameters":[{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Start from this cursor"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Start from this cursor"},{"schema":{"type":"number"},"in":"query","name":"pageSize","required":false,"description":"Size of the results array"},{"schema":{"type":"string"},"in":"path","name":"role_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"PaginatedResponse","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"type":"string","description":"next cursor","nullable":true},"results":{"type":"array","items":{"$ref":"#/components/schemas/RoleMember"},"description":"List of results"}},"description":"PaginatedResponse","additionalProperties":false}}}}}},"post":{"operationId":"role/assign_users","summary":"Assign Users to Role","tags":["role"],"description":"Assign Users to Role","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["users"],"properties":{"users":{"type":"array","items":{"type":"string"},"description":"List of User ids to grant the role to. Existing role memberships are preserved; passing a user that already holds the role is a no-op.","example":["user_6555fd293acc2f0fac0e3452"]}},"additionalProperties":false,"description":"Payload for granting a role to one or more users in a single call. Posted to `POST /role/:role_id/users`."}}},"description":"Payload for granting a role to one or more users in a single call. Posted to `POST /role/:role_id/users`."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"role_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response"}}}},"/rolemember":{"get":{"operationId":"rolemember/list","summary":"List Rolemembers","tags":["rolemember"],"description":"List Rolemembers","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"array","items":{"type":"string","enum":["user","role"],"description":"Allowed expand paths on `rolemember`: `user`, `role`."},"maxItems":2},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `?expand=user`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/RoleMember"}}},"additionalProperties":false}}}}}},"post":{"operationId":"rolemember/create","summary":"Create Rolemember","tags":["rolemember"],"description":"Create Rolemember","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["users"],"properties":{"users":{"type":"array","items":{"type":"string"},"description":"List of User ids to grant the role to. Existing role memberships are preserved; passing a user that already holds the role is a no-op.","example":["user_6555fd293acc2f0fac0e3452"]}},"additionalProperties":false,"description":"Payload for granting a role to one or more users in a single call. Posted to `POST /role/:role_id/users`."}}},"description":"Payload for granting a role to one or more users in a single call. Posted to `POST /role/:role_id/users`."},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"RoleMember","content":{"application/json":{"schema":{"type":"object","required":["id","role","user","account","createdAt"],"properties":{"id":{"type":"string","description":"RoleMember ID"},"role":{"anyOf":[{"$ref":"#/components/schemas/Role"},{"type":"string"},{}],"description":"Role granted to the user. Returned as an id by default; pass `?expand=role` to inline the full Role object."},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User the role is granted to. Returned as an id by default; pass `?expand=user` to inline the full User object."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"RoleMemberMetadata","default":{}},"createdAt":{"type":"string","description":"RoleMember creation date"},"updatedAt":{"type":"string","description":"RoleMember updated date"}},"description":"RoleMember"}}}}}}},"/rolemember/{rolemember_id}":{"get":{"operationId":"rolemember/get","summary":"Get Rolemember","tags":["rolemember"],"description":"Get Rolemember","parameters":[{"schema":{"type":"array","items":{"type":"string","enum":["user","role"],"description":"Allowed expand paths on `rolemember`: `user`, `role`."},"maxItems":2},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `?expand=user`)."},{"schema":{"type":"string"},"in":"path","name":"rolemember_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"RoleMember","content":{"application/json":{"schema":{"type":"object","required":["id","role","user","account","createdAt"],"properties":{"id":{"type":"string","description":"RoleMember ID"},"role":{"anyOf":[{"$ref":"#/components/schemas/Role"},{"type":"string"},{}],"description":"Role granted to the user. Returned as an id by default; pass `?expand=role` to inline the full Role object."},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User the role is granted to. Returned as an id by default; pass `?expand=user` to inline the full User object."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"RoleMemberMetadata","default":{}},"createdAt":{"type":"string","description":"RoleMember creation date"},"updatedAt":{"type":"string","description":"RoleMember updated date"}},"description":"RoleMember"}}}}}},"delete":{"operationId":"rolemember/delete","summary":"Delete Rolemember","tags":["rolemember"],"description":"Delete Rolemember","parameters":[{"schema":{"type":"string"},"in":"path","name":"rolemember_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"RoleMember","content":{"application/json":{"schema":{"type":"object","required":["id","role","user","account","createdAt"],"properties":{"id":{"type":"string","description":"RoleMember ID"},"role":{"anyOf":[{"$ref":"#/components/schemas/Role"},{"type":"string"},{}],"description":"Role granted to the user. Returned as an id by default; pass `?expand=role` to inline the full Role object."},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User the role is granted to. Returned as an id by default; pass `?expand=user` to inline the full User object."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"RoleMemberMetadata","default":{}},"createdAt":{"type":"string","description":"RoleMember creation date"},"updatedAt":{"type":"string","description":"RoleMember updated date"}},"description":"RoleMember"}}}}}}},"/team":{"get":{"operationId":"team/list","summary":"List Teams","tags":["team"],"description":"List Teams","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"in":"query","name":"q","required":false,"description":"Full-text search across: `name`, `slug`."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/Team"}}},"additionalProperties":false}}}}}},"post":{"operationId":"team/create","summary":"Create Team","tags":["team"],"description":"Create Team","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Human-readable name of the team.","example":"Acme Engineering"},"description":{"type":"string","description":"Optional free-form description of the team."},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"TeamCreate","additionalProperties":false}}},"description":"TeamCreate"},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Team","content":{"application/json":{"schema":{"type":"object","required":["id","name","slug","description","logo_url","account","createdAt"],"properties":{"id":{"type":"string","description":"Team ID"},"name":{"type":"string","description":"Human-readable name of the team. Shown in the dashboard and in team-picker UI.","example":"Acme Engineering"},"slug":{"type":"string","description":"URL-safe identifier auto-derived from `name`. Unique within the tenant; used in routes that address a team by slug.","example":"acme-engineering"},"description":{"type":"string","description":"Optional free-form description of the team.","nullable":true},"logo_url":{"type":"string","description":"Optional URL of an image used as the team avatar/logo.","nullable":true},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMetadata","default":{}},"createdAt":{"type":"string","description":"Team creation date"},"updatedAt":{"type":"string","description":"Team updated date"}},"description":"Team"}}}}}}},"/team/{team_id}":{"get":{"operationId":"team/get","summary":"Get Team","tags":["team"],"description":"Get Team","parameters":[{"schema":{"type":"string"},"in":"path","name":"team_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Team","content":{"application/json":{"schema":{"type":"object","required":["id","name","slug","description","logo_url","account","createdAt"],"properties":{"id":{"type":"string","description":"Team ID"},"name":{"type":"string","description":"Human-readable name of the team. Shown in the dashboard and in team-picker UI.","example":"Acme Engineering"},"slug":{"type":"string","description":"URL-safe identifier auto-derived from `name`. Unique within the tenant; used in routes that address a team by slug.","example":"acme-engineering"},"description":{"type":"string","description":"Optional free-form description of the team.","nullable":true},"logo_url":{"type":"string","description":"Optional URL of an image used as the team avatar/logo.","nullable":true},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMetadata","default":{}},"createdAt":{"type":"string","description":"Team creation date"},"updatedAt":{"type":"string","description":"Team updated date"}},"description":"Team"}}}}}},"post":{"operationId":"team/update","summary":"Update Team","tags":["team"],"description":"Update Team","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New human-readable name for the team."},"description":{"type":"string","description":"New free-form description for the team."},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Arbitrary key/value pairs attached to the team. Replaces the previous metadata entirely."}},"description":"Partial update for a Team. Only the supplied fields are modified. `slug` is auto-derived from `name` and is not user-editable.","additionalProperties":false}}},"description":"Partial update for a Team. Only the supplied fields are modified. `slug` is auto-derived from `name` and is not user-editable."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"team_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Team","content":{"application/json":{"schema":{"type":"object","required":["id","name","slug","description","logo_url","account","createdAt"],"properties":{"id":{"type":"string","description":"Team ID"},"name":{"type":"string","description":"Human-readable name of the team. Shown in the dashboard and in team-picker UI.","example":"Acme Engineering"},"slug":{"type":"string","description":"URL-safe identifier auto-derived from `name`. Unique within the tenant; used in routes that address a team by slug.","example":"acme-engineering"},"description":{"type":"string","description":"Optional free-form description of the team.","nullable":true},"logo_url":{"type":"string","description":"Optional URL of an image used as the team avatar/logo.","nullable":true},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMetadata","default":{}},"createdAt":{"type":"string","description":"Team creation date"},"updatedAt":{"type":"string","description":"Team updated date"}},"description":"Team"}}}}}},"delete":{"operationId":"team/delete","summary":"Delete Team","tags":["team"],"description":"Delete Team","parameters":[{"schema":{"type":"string"},"in":"path","name":"team_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Team","content":{"application/json":{"schema":{"type":"object","required":["id","name","slug","description","logo_url","account","createdAt"],"properties":{"id":{"type":"string","description":"Team ID"},"name":{"type":"string","description":"Human-readable name of the team. Shown in the dashboard and in team-picker UI.","example":"Acme Engineering"},"slug":{"type":"string","description":"URL-safe identifier auto-derived from `name`. Unique within the tenant; used in routes that address a team by slug.","example":"acme-engineering"},"description":{"type":"string","description":"Optional free-form description of the team.","nullable":true},"logo_url":{"type":"string","description":"Optional URL of an image used as the team avatar/logo.","nullable":true},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMetadata","default":{}},"createdAt":{"type":"string","description":"Team creation date"},"updatedAt":{"type":"string","description":"Team updated date"}},"description":"Team"}}}}}}},"/teammember":{"get":{"operationId":"teammember/list","summary":"List Teammembers","tags":["teammember"],"description":"List Teammembers","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"array","items":{"type":"string","enum":["user","team","roles"],"description":"Allowed expand paths on `teammember`: `user`, `team`, `roles`."},"maxItems":3},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `?expand=user`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/TeamMember"}}},"additionalProperties":false}}}}}},"post":{"operationId":"teammember/create","summary":"Create Teammember","tags":["teammember"],"description":"Create Teammember","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["users"],"properties":{"users":{"type":"array","items":{"type":"string"},"description":"List of User ids to add as members of the team. Users already in the team are skipped.","example":["user_6555fd293acc2f0fac0e3452"]},"roles":{"type":"array","items":{"type":"string"},"description":"Role ids to grant to the added members within the scope of this team.","default":[],"example":["role_6555fd293acc2f0fac0e3452"]}},"additionalProperties":false,"description":"Payload for adding one or more users to a team in a single call. Posted to `POST /team/:team_id/member`."}}},"description":"Payload for adding one or more users to a team in a single call. Posted to `POST /team/:team_id/member`."},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"TeamMember","content":{"application/json":{"schema":{"type":"object","required":["id","user","team","roles","account","createdAt"],"properties":{"id":{"type":"string","description":"TeamMember ID"},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User that belongs to the team. Returned as an id by default; pass `?expand=user` to inline the full User object."},"team":{"anyOf":[{"$ref":"#/components/schemas/Team"},{"type":"string"},{}],"description":"Team the user belongs to. Returned as an id by default; pass `?expand=team` to inline the full Team object."},"roles":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/Role"},{"type":"string"},{}]},"description":"Roles granted to the user *within this team*. Distinct from account-wide RoleMember grants — these only apply in the scope of the team. Each entry is an id by default; pass `?expand=roles` to inline."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMemberMetadata","default":{}},"createdAt":{"type":"string","description":"TeamMember creation date"},"updatedAt":{"type":"string","description":"TeamMember updated date"}},"description":"TeamMember"}}}}}}},"/teammember/{teammember_id}":{"get":{"operationId":"teammember/get","summary":"Get Teammember","tags":["teammember"],"description":"Get Teammember","parameters":[{"schema":{"type":"array","items":{"type":"string","enum":["user","team","roles"],"description":"Allowed expand paths on `teammember`: `user`, `team`, `roles`."},"maxItems":3},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `?expand=user`)."},{"schema":{"type":"string"},"in":"path","name":"teammember_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"TeamMember","content":{"application/json":{"schema":{"type":"object","required":["id","user","team","roles","account","createdAt"],"properties":{"id":{"type":"string","description":"TeamMember ID"},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User that belongs to the team. Returned as an id by default; pass `?expand=user` to inline the full User object."},"team":{"anyOf":[{"$ref":"#/components/schemas/Team"},{"type":"string"},{}],"description":"Team the user belongs to. Returned as an id by default; pass `?expand=team` to inline the full Team object."},"roles":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/Role"},{"type":"string"},{}]},"description":"Roles granted to the user *within this team*. Distinct from account-wide RoleMember grants — these only apply in the scope of the team. Each entry is an id by default; pass `?expand=roles` to inline."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMemberMetadata","default":{}},"createdAt":{"type":"string","description":"TeamMember creation date"},"updatedAt":{"type":"string","description":"TeamMember updated date"}},"description":"TeamMember"}}}}}},"delete":{"operationId":"teammember/delete","summary":"Delete Teammember","tags":["teammember"],"description":"Delete Teammember","parameters":[{"schema":{"type":"string"},"in":"path","name":"teammember_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"TeamMember","content":{"application/json":{"schema":{"type":"object","required":["id","user","team","roles","account","createdAt"],"properties":{"id":{"type":"string","description":"TeamMember ID"},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User that belongs to the team. Returned as an id by default; pass `?expand=user` to inline the full User object."},"team":{"anyOf":[{"$ref":"#/components/schemas/Team"},{"type":"string"},{}],"description":"Team the user belongs to. Returned as an id by default; pass `?expand=team` to inline the full Team object."},"roles":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/Role"},{"type":"string"},{}]},"description":"Roles granted to the user *within this team*. Distinct from account-wide RoleMember grants — these only apply in the scope of the team. Each entry is an id by default; pass `?expand=roles` to inline."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMemberMetadata","default":{}},"createdAt":{"type":"string","description":"TeamMember creation date"},"updatedAt":{"type":"string","description":"TeamMember updated date"}},"description":"TeamMember"}}}}}}},"/team/{team_id}/member":{"get":{"operationId":"team/listMembers","summary":"List Team Members","tags":["team"],"description":"List all Users that belong to the given Team in the current Account. Supports `?expand=user,team,roles` to inline referenced rows.","parameters":[{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Start from this cursor"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Start from this cursor"},{"schema":{"type":"number"},"in":"query","name":"pageSize","required":false,"description":"Size of the results array"},{"schema":{"type":"array","items":{"type":"string","enum":["user","team","roles"],"description":"Allowed expand paths: `user`, `team`, `roles`."}},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Accepts repeated params (`expand=user&expand=roles`) or comma-separated (`expand=user,roles`)."},{"schema":{"type":"string"},"in":"path","name":"team_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"PaginatedResponse","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"type":"string","description":"next cursor","nullable":true},"results":{"type":"array","items":{"$ref":"#/components/schemas/TeamMember"},"description":"List of results"}},"description":"PaginatedResponse","additionalProperties":false}}}}}},"post":{"operationId":"team/addMembers","summary":"Add Users to a Team","tags":["team"],"description":"Adds one or more Users as members of the given Team. Returns the resulting TeamMember record.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["users"],"properties":{"users":{"type":"array","items":{"type":"string"},"description":"List of User ids to add as members of the team. Users already in the team are skipped.","example":["user_6555fd293acc2f0fac0e3452"]},"roles":{"type":"array","items":{"type":"string"},"description":"Role ids to grant to the added members within the scope of this team.","default":[],"example":["role_6555fd293acc2f0fac0e3452"]}},"additionalProperties":false,"description":"Payload for adding one or more users to a team in a single call. Posted to `POST /team/:team_id/member`."}}},"description":"Payload for adding one or more users to a team in a single call. Posted to `POST /team/:team_id/member`."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"team_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"TeamMember","content":{"application/json":{"schema":{"type":"object","required":["id","user","team","roles","account","createdAt"],"properties":{"id":{"type":"string","description":"TeamMember ID"},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User that belongs to the team. Returned as an id by default; pass `?expand=user` to inline the full User object."},"team":{"anyOf":[{"$ref":"#/components/schemas/Team"},{"type":"string"},{}],"description":"Team the user belongs to. Returned as an id by default; pass `?expand=team` to inline the full Team object."},"roles":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/Role"},{"type":"string"},{}]},"description":"Roles granted to the user *within this team*. Distinct from account-wide RoleMember grants — these only apply in the scope of the team. Each entry is an id by default; pass `?expand=roles` to inline."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMemberMetadata","default":{}},"createdAt":{"type":"string","description":"TeamMember creation date"},"updatedAt":{"type":"string","description":"TeamMember updated date"}},"description":"TeamMember"}}}}}}},"/team/{team_id}/member/check/{user_id}":{"get":{"operationId":"team/checkMember","summary":"Check User is member of a Team","tags":["team"],"description":"Returns the TeamMember record if the User belongs to the given Team, or 404 otherwise.","parameters":[{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Start from this cursor"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Start from this cursor"},{"schema":{"type":"number"},"in":"query","name":"pageSize","required":false,"description":"Size of the results array"},{"schema":{"type":"string"},"in":"path","name":"team_id","required":true},{"schema":{"type":"string"},"in":"path","name":"user_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"TeamMember","content":{"application/json":{"schema":{"type":"object","required":["id","user","team","roles","account","createdAt"],"properties":{"id":{"type":"string","description":"TeamMember ID"},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User that belongs to the team. Returned as an id by default; pass `?expand=user` to inline the full User object."},"team":{"anyOf":[{"$ref":"#/components/schemas/Team"},{"type":"string"},{}],"description":"Team the user belongs to. Returned as an id by default; pass `?expand=team` to inline the full Team object."},"roles":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/Role"},{"type":"string"},{}]},"description":"Roles granted to the user *within this team*. Distinct from account-wide RoleMember grants — these only apply in the scope of the team. Each entry is an id by default; pass `?expand=roles` to inline."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMemberMetadata","default":{}},"createdAt":{"type":"string","description":"TeamMember creation date"},"updatedAt":{"type":"string","description":"TeamMember updated date"}},"description":"TeamMember"}}}}}}},"/team/{team_id}/invite":{"post":{"operationId":"team/invite","summary":"Invite a user to a Team by email","tags":["team"],"description":"Invites a user by email. `mode='auto'` (default) adds the user directly when the email already corresponds to a user in this tenant and falls back to a ticketed invite + email otherwise. `mode='invite'` always issues a ticket + email even when the user exists. Re-inviting the same email to the same team invalidates the previous pending invite.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string","description":"Email of the user to invite to the team.","example":"someone@example.com"},"roles":{"type":"array","items":{"type":"string"},"description":"Role ids granted to the resulting TeamMember within the scope of this team.","default":[]},"mode":{"anyOf":[{"type":"string","enum":["auto"]},{"type":"string","enum":["invite"]}],"description":"`auto` adds the user directly if they already exist in the tenant and only falls back to a ticketed invite when the email is unknown. `invite` always issues a ticket + email regardless of whether the user exists."},"redirect_uri":{"type":"string","description":"Where to redirect the invitee after a successful accept. Defaults to `/`."}},"additionalProperties":false,"description":"Payload for inviting a user to a team by email. `mode='auto'` (default) adds the user immediately if they already exist in the tenant and falls back to a ticketed invite otherwise. `mode='invite'` always issues a ticket + email."}}},"description":"Payload for inviting a user to a team by email. `mode='auto'` (default) adds the user immediately if they already exist in the tenant and falls back to a ticketed invite otherwise. `mode='invite'` always issues a ticket + email."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"team_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"anyOf":[{"type":"string","enum":["invited"]},{"type":"string","enum":["added"]}],"description":"`invited` when a ticket + email was issued, `added` when the user was added directly (auto mode + existing user)."},"ticket_id":{"type":"string","description":"ID of the issued invite ticket (when status=invited)."},"member":{"type":"object","required":["id","user","team","roles","account","createdAt"],"properties":{"id":{"type":"string","description":"TeamMember ID"},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User that belongs to the team. Returned as an id by default; pass `?expand=user` to inline the full User object."},"team":{"anyOf":[{"$ref":"#/components/schemas/Team"},{"type":"string"},{}],"description":"Team the user belongs to. Returned as an id by default; pass `?expand=team` to inline the full Team object."},"roles":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/Role"},{"type":"string"},{}]},"description":"Roles granted to the user *within this team*. Distinct from account-wide RoleMember grants — these only apply in the scope of the team. Each entry is an id by default; pass `?expand=roles` to inline."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamMemberMetadata","default":{}},"createdAt":{"type":"string","description":"TeamMember creation date"},"updatedAt":{"type":"string","description":"TeamMember updated date"}},"description":"TeamMember"}},"additionalProperties":false}}}}}},"get":{"operationId":"team/listInvites","summary":"List pending invites for a Team","tags":["team"],"description":"Returns all pending (not consumed, not expired) team invites for the given team. Accepts a FaableQL `query` parameter on the `email` field.","parameters":[{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"FaableQL filter. Supported fields: `email`. Example: `?query=email:foo@bar.com`"},{"schema":{"type":"string"},"in":"path","name":"team_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["id","email","team","roles","mode","expires_at","account","createdAt"],"properties":{"id":{"type":"string","description":"TeamInvite ID"},"email":{"type":"string","description":"Email address that was invited"},"team":{"anyOf":[{"$ref":"#/components/schemas/Team"},{"type":"string"},{}],"description":"Team the invitee will be added to upon acceptance."},"inviter":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}],"description":"User that created the invitation, if known."},"roles":{"type":"array","items":{"type":"string"},"description":"Role ids that will be applied to the new TeamMember on acceptance."},"mode":{"anyOf":[{"type":"string","enum":["auto"]},{"type":"string","enum":["invite"]}],"description":"`auto` adds the user directly if they already exist in the tenant and only falls back to a ticketed invite when the email is unknown. `invite` always issues a ticket + email regardless of whether the user exists."},"redirect_uri":{"type":"string","description":"URI to redirect the invitee to after a successful accept."},"expires_at":{"type":"string","description":"ISO 8601 timestamp at which the invite stops being valid."},"consume_date":{"type":"string","description":"ISO 8601 timestamp at which the invite was accepted. Absent for pending invites."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"TeamInviteMetadata","default":{}},"createdAt":{"type":"string","description":"TeamInvite creation date"},"updatedAt":{"type":"string","description":"TeamInvite updated date"}},"description":"TeamInvite"}}}}}}}}}},"/team/{team_id}/invite/{ticket_id}":{"delete":{"operationId":"team/revokeInvite","summary":"Revoke a pending team invite","tags":["team"],"description":"Marks a pending team invite as consumed so it can no longer be accepted. Returns 400 if the invite is already consumed and 404 if it does not exist or belongs to a different team.","parameters":[{"schema":{"type":"string"},"in":"path","name":"team_id","required":true},{"schema":{"type":"string"},"in":"path","name":"ticket_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["revoked"]}}}}}}}}},"/invite-verify":{"get":{"operationId":"team_invite_verify","summary":"Verify a team-invite ticket and add the user to the team","tags":["team"],"description":"Entry point for the link sent to the invitee. Consumes the ticket, creates the user if needed (with `email_verified=true` — the click proves ownership), and adds them to the team with the invited roles. Then redirects to the `redirect_uri` supplied at invite time with `?status=accepted` appended; falls back to `/flow/team-invite-done` on the auth host when no `redirect_uri` was given. Idempotent if the user is already a member.","parameters":[{"schema":{"type":"string"},"in":"query","name":"ticket","required":true}],"responses":{"200":{"description":"Default Response"}}}},"/api":{"get":{"operationId":"api/list","summary":"List Apis","tags":["api"],"description":"List Apis","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"in":"query","name":"q","required":false,"description":"Full-text search across: `name`, `description`, `identifier`, `slug`."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/Api"}}},"additionalProperties":false}}}}}},"post":{"operationId":"api/create","summary":"Create Api","tags":["api"],"description":"Create Api","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","identifier"],"properties":{"name":{"type":"string","description":"Human-readable name for the API.","example":"My Backend API"},"identifier":{"type":"string","description":"Audience URL clients pass as `audience=` when requesting a token for this API. Must be unique within the tenant and is immutable after creation.","example":"https://api.faable.com"},"description":{"type":"string","description":"Optional human-readable description of the API."},"permissions":{"type":"array","items":{"$ref":"#/components/schemas/PermissionCreate"},"description":"Set of permissions (scopes) this API exposes. Tokens issued with `audience=identifier` will only carry these in their `permissions` claim.","default":[]},"signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign access_tokens issued for this API. Currently only RS256 (the account keystore default) is implemented."},"token_dialect":{"anyOf":[{"type":"string","enum":["access_token"]},{"type":"string","enum":["access_token_authz"]}],"description":"Shape of access_tokens issued for this API. `access_token` emits the standard OAuth2 token. `access_token_authz` additionally embeds a `permissions` claim listing the permissions granted to the subject for this API."},"token_lifetime":{"type":"integer","description":"Access_token lifetime in seconds. Defaults to 86400 (24h) if omitted.","minimum":60,"maximum":2592000},"enforce_policies":{"type":"boolean","description":"When true, requested scopes are filtered against `permissions` at token issuance."},"allow_offline_access":{"type":"boolean","description":"When true, clients can request `offline_access` and receive a refresh_token for this API."},"skip_consent":{"type":"boolean","description":"When true, skip the consent prompt for first-party clients."},"include_teams_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `teams` claim with the subject team slugs."},"include_roles_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `roles` claim with the subject role names."},"include_teams_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `teams` claim with the subject team slugs."},"include_roles_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `roles` claim with the subject role names."}},"additionalProperties":false,"description":"Payload for creating an Api (a.k.a. Resource Server / Audience). The `identifier` becomes the `aud` claim in tokens issued for this API and cannot be changed after creation."}}},"description":"Payload for creating an Api (a.k.a. Resource Server / Audience). The `identifier` becomes the `aud` claim in tokens issued for this API and cannot be changed after creation."},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Api","content":{"application/json":{"schema":{"type":"object","required":["id","name","slug","identifier","permissions","signing_alg","token_dialect","token_lifetime","enforce_policies","allow_offline_access","skip_consent","include_teams_in_access_token","include_roles_in_access_token","include_teams_in_id_token","include_roles_in_id_token","account","createdAt"],"properties":{"id":{"type":"string","description":"Api ID"},"name":{"type":"string","description":"Human-readable name for the API. Shown in the dashboard and consent prompts.","example":"My Backend API"},"slug":{"type":"string","description":"URL-safe identifier auto-derived from `name`. Unique within the tenant."},"identifier":{"type":"string","description":"Audience URL that clients pass as `audience=` when requesting a token for this API. Becomes the `aud` claim in the issued access_token. Immutable after creation and unique within the tenant.","example":"https://api.faable.com"},"description":{"type":"string","description":"Optional human-readable description of the API."},"permissions":{"type":"array","items":{"$ref":"#/components/schemas/Permission"},"description":"Set of permissions (scopes) this API exposes. When a token is issued with `audience=identifier`, the requested `scope` is intersected with this list to populate the `permissions` claim."},"signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign access_tokens issued for this API. Currently only RS256 (the account keystore default) is implemented."},"token_dialect":{"anyOf":[{"type":"string","enum":["access_token"]},{"type":"string","enum":["access_token_authz"]}],"description":"Shape of access_tokens issued for this API. `access_token` emits the standard OAuth2 token. `access_token_authz` additionally embeds a `permissions` claim listing the permissions granted to the subject for this API."},"token_lifetime":{"type":"integer","description":"Access_token lifetime in seconds. Default 86400 (24h). Applied at token issuance time (overrides the generic default).","minimum":60,"maximum":2592000},"enforce_policies":{"type":"boolean","description":"When true, only scopes that match a permission in `permissions` are forwarded into the access_token. When false, requested scopes are echoed back verbatim with no filtering."},"allow_offline_access":{"type":"boolean","description":"When true, the API is eligible to be the target of a `refresh_token` (i.e. clients can request `offline_access` against it)."},"skip_consent":{"type":"boolean","description":"When true, the consent prompt is skipped for first-party clients (clients owned by the same tenant as the API)."},"include_teams_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `teams` claim listing the slugs of the teams the subject is a member of within the tenant."},"include_roles_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `roles` claim listing the names of the roles the subject holds across their team memberships within the tenant."},"include_teams_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `teams` claim with the subject team slugs. The id_token only sees the flag when the client requested `audience=` so this API is resolved at issuance time."},"include_roles_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `roles` claim with the subject role names. Same audience caveat as `include_teams_in_id_token`."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ApiMetadata","default":{}},"createdAt":{"type":"string","description":"Api creation date"},"updatedAt":{"type":"string","description":"Api updated date"}},"description":"Api"}}}}}}},"/api/{api_id}":{"get":{"operationId":"api/get","summary":"Get Api","tags":["api"],"description":"Get Api","parameters":[{"schema":{"type":"string"},"in":"path","name":"api_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Api","content":{"application/json":{"schema":{"type":"object","required":["id","name","slug","identifier","permissions","signing_alg","token_dialect","token_lifetime","enforce_policies","allow_offline_access","skip_consent","include_teams_in_access_token","include_roles_in_access_token","include_teams_in_id_token","include_roles_in_id_token","account","createdAt"],"properties":{"id":{"type":"string","description":"Api ID"},"name":{"type":"string","description":"Human-readable name for the API. Shown in the dashboard and consent prompts.","example":"My Backend API"},"slug":{"type":"string","description":"URL-safe identifier auto-derived from `name`. Unique within the tenant."},"identifier":{"type":"string","description":"Audience URL that clients pass as `audience=` when requesting a token for this API. Becomes the `aud` claim in the issued access_token. Immutable after creation and unique within the tenant.","example":"https://api.faable.com"},"description":{"type":"string","description":"Optional human-readable description of the API."},"permissions":{"type":"array","items":{"$ref":"#/components/schemas/Permission"},"description":"Set of permissions (scopes) this API exposes. When a token is issued with `audience=identifier`, the requested `scope` is intersected with this list to populate the `permissions` claim."},"signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign access_tokens issued for this API. Currently only RS256 (the account keystore default) is implemented."},"token_dialect":{"anyOf":[{"type":"string","enum":["access_token"]},{"type":"string","enum":["access_token_authz"]}],"description":"Shape of access_tokens issued for this API. `access_token` emits the standard OAuth2 token. `access_token_authz` additionally embeds a `permissions` claim listing the permissions granted to the subject for this API."},"token_lifetime":{"type":"integer","description":"Access_token lifetime in seconds. Default 86400 (24h). Applied at token issuance time (overrides the generic default).","minimum":60,"maximum":2592000},"enforce_policies":{"type":"boolean","description":"When true, only scopes that match a permission in `permissions` are forwarded into the access_token. When false, requested scopes are echoed back verbatim with no filtering."},"allow_offline_access":{"type":"boolean","description":"When true, the API is eligible to be the target of a `refresh_token` (i.e. clients can request `offline_access` against it)."},"skip_consent":{"type":"boolean","description":"When true, the consent prompt is skipped for first-party clients (clients owned by the same tenant as the API)."},"include_teams_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `teams` claim listing the slugs of the teams the subject is a member of within the tenant."},"include_roles_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `roles` claim listing the names of the roles the subject holds across their team memberships within the tenant."},"include_teams_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `teams` claim with the subject team slugs. The id_token only sees the flag when the client requested `audience=` so this API is resolved at issuance time."},"include_roles_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `roles` claim with the subject role names. Same audience caveat as `include_teams_in_id_token`."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ApiMetadata","default":{}},"createdAt":{"type":"string","description":"Api creation date"},"updatedAt":{"type":"string","description":"Api updated date"}},"description":"Api"}}}}}},"post":{"operationId":"api/update","summary":"Update Api","tags":["api"],"description":"Update Api","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Human-readable name for the API."},"description":{"type":"string","description":"Optional human-readable description of the API."},"permissions":{"type":"array","items":{"$ref":"#/components/schemas/PermissionCreate"},"description":"Replaces the full permissions list. Tokens issued AFTER the update will use the new list; tokens already in circulation are unchanged."},"signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign access_tokens issued for this API. Currently only RS256 (the account keystore default) is implemented."},"token_dialect":{"anyOf":[{"type":"string","enum":["access_token"]},{"type":"string","enum":["access_token_authz"]}],"description":"Shape of access_tokens issued for this API. `access_token` emits the standard OAuth2 token. `access_token_authz` additionally embeds a `permissions` claim listing the permissions granted to the subject for this API."},"token_lifetime":{"type":"integer","description":"Access_token lifetime in seconds.","minimum":60,"maximum":2592000},"enforce_policies":{"type":"boolean","description":"When true, requested scopes are filtered against `permissions` at token issuance."},"allow_offline_access":{"type":"boolean","description":"When true, clients can request `offline_access` and receive a refresh_token for this API."},"skip_consent":{"type":"boolean","description":"When true, skip the consent prompt for first-party clients."},"include_teams_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `teams` claim with the subject team slugs."},"include_roles_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `roles` claim with the subject role names."},"include_teams_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `teams` claim with the subject team slugs."},"include_roles_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `roles` claim with the subject role names."}},"additionalProperties":false,"description":"Partial update for an Api. `identifier` is immutable and not present here; recreate the API if you need to change it."}}},"description":"Partial update for an Api. `identifier` is immutable and not present here; recreate the API if you need to change it."},"parameters":[{"schema":{"type":"string"},"in":"path","name":"api_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Api","content":{"application/json":{"schema":{"type":"object","required":["id","name","slug","identifier","permissions","signing_alg","token_dialect","token_lifetime","enforce_policies","allow_offline_access","skip_consent","include_teams_in_access_token","include_roles_in_access_token","include_teams_in_id_token","include_roles_in_id_token","account","createdAt"],"properties":{"id":{"type":"string","description":"Api ID"},"name":{"type":"string","description":"Human-readable name for the API. Shown in the dashboard and consent prompts.","example":"My Backend API"},"slug":{"type":"string","description":"URL-safe identifier auto-derived from `name`. Unique within the tenant."},"identifier":{"type":"string","description":"Audience URL that clients pass as `audience=` when requesting a token for this API. Becomes the `aud` claim in the issued access_token. Immutable after creation and unique within the tenant.","example":"https://api.faable.com"},"description":{"type":"string","description":"Optional human-readable description of the API."},"permissions":{"type":"array","items":{"$ref":"#/components/schemas/Permission"},"description":"Set of permissions (scopes) this API exposes. When a token is issued with `audience=identifier`, the requested `scope` is intersected with this list to populate the `permissions` claim."},"signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign access_tokens issued for this API. Currently only RS256 (the account keystore default) is implemented."},"token_dialect":{"anyOf":[{"type":"string","enum":["access_token"]},{"type":"string","enum":["access_token_authz"]}],"description":"Shape of access_tokens issued for this API. `access_token` emits the standard OAuth2 token. `access_token_authz` additionally embeds a `permissions` claim listing the permissions granted to the subject for this API."},"token_lifetime":{"type":"integer","description":"Access_token lifetime in seconds. Default 86400 (24h). Applied at token issuance time (overrides the generic default).","minimum":60,"maximum":2592000},"enforce_policies":{"type":"boolean","description":"When true, only scopes that match a permission in `permissions` are forwarded into the access_token. When false, requested scopes are echoed back verbatim with no filtering."},"allow_offline_access":{"type":"boolean","description":"When true, the API is eligible to be the target of a `refresh_token` (i.e. clients can request `offline_access` against it)."},"skip_consent":{"type":"boolean","description":"When true, the consent prompt is skipped for first-party clients (clients owned by the same tenant as the API)."},"include_teams_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `teams` claim listing the slugs of the teams the subject is a member of within the tenant."},"include_roles_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `roles` claim listing the names of the roles the subject holds across their team memberships within the tenant."},"include_teams_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `teams` claim with the subject team slugs. The id_token only sees the flag when the client requested `audience=` so this API is resolved at issuance time."},"include_roles_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `roles` claim with the subject role names. Same audience caveat as `include_teams_in_id_token`."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ApiMetadata","default":{}},"createdAt":{"type":"string","description":"Api creation date"},"updatedAt":{"type":"string","description":"Api updated date"}},"description":"Api"}}}}}},"delete":{"operationId":"api/delete","summary":"Delete Api","tags":["api"],"description":"Delete Api","parameters":[{"schema":{"type":"string"},"in":"path","name":"api_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Api","content":{"application/json":{"schema":{"type":"object","required":["id","name","slug","identifier","permissions","signing_alg","token_dialect","token_lifetime","enforce_policies","allow_offline_access","skip_consent","include_teams_in_access_token","include_roles_in_access_token","include_teams_in_id_token","include_roles_in_id_token","account","createdAt"],"properties":{"id":{"type":"string","description":"Api ID"},"name":{"type":"string","description":"Human-readable name for the API. Shown in the dashboard and consent prompts.","example":"My Backend API"},"slug":{"type":"string","description":"URL-safe identifier auto-derived from `name`. Unique within the tenant."},"identifier":{"type":"string","description":"Audience URL that clients pass as `audience=` when requesting a token for this API. Becomes the `aud` claim in the issued access_token. Immutable after creation and unique within the tenant.","example":"https://api.faable.com"},"description":{"type":"string","description":"Optional human-readable description of the API."},"permissions":{"type":"array","items":{"$ref":"#/components/schemas/Permission"},"description":"Set of permissions (scopes) this API exposes. When a token is issued with `audience=identifier`, the requested `scope` is intersected with this list to populate the `permissions` claim."},"signing_alg":{"anyOf":[{"type":"string","enum":["RS256"]}],"description":"JWA algorithm used to sign access_tokens issued for this API. Currently only RS256 (the account keystore default) is implemented."},"token_dialect":{"anyOf":[{"type":"string","enum":["access_token"]},{"type":"string","enum":["access_token_authz"]}],"description":"Shape of access_tokens issued for this API. `access_token` emits the standard OAuth2 token. `access_token_authz` additionally embeds a `permissions` claim listing the permissions granted to the subject for this API."},"token_lifetime":{"type":"integer","description":"Access_token lifetime in seconds. Default 86400 (24h). Applied at token issuance time (overrides the generic default).","minimum":60,"maximum":2592000},"enforce_policies":{"type":"boolean","description":"When true, only scopes that match a permission in `permissions` are forwarded into the access_token. When false, requested scopes are echoed back verbatim with no filtering."},"allow_offline_access":{"type":"boolean","description":"When true, the API is eligible to be the target of a `refresh_token` (i.e. clients can request `offline_access` against it)."},"skip_consent":{"type":"boolean","description":"When true, the consent prompt is skipped for first-party clients (clients owned by the same tenant as the API)."},"include_teams_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `teams` claim listing the slugs of the teams the subject is a member of within the tenant."},"include_roles_in_access_token":{"type":"boolean","description":"When true, access_tokens issued for this API carry a `roles` claim listing the names of the roles the subject holds across their team memberships within the tenant."},"include_teams_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `teams` claim with the subject team slugs. The id_token only sees the flag when the client requested `audience=` so this API is resolved at issuance time."},"include_roles_in_id_token":{"type":"boolean","description":"When true, id_tokens issued together with an access_token for this API carry a `roles` claim with the subject role names. Same audience caveat as `include_teams_in_id_token`."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ApiMetadata","default":{}},"createdAt":{"type":"string","description":"Api creation date"},"updatedAt":{"type":"string","description":"Api updated date"}},"description":"Api"}}}}}}},"/account/keys":{"get":{"operationId":"account/getKeys","summary":"Get Account signing keys info","tags":["account"],"description":"Returns metadata for the Account signing keys: the current production kid, the kid queued for next rotation, and all kids currently published in the JWK Set. Does not expose private key material.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["production_kid","next_in_queue_kid","kids_active"],"properties":{"production_kid":{"type":"string","description":"kid currently used to sign new tokens"},"next_in_queue_kid":{"type":"string","description":"kid that will be promoted on the next rotation"},"kids_active":{"type":"array","items":{"type":"string"},"description":"All kids currently published in the JWK Set"}},"additionalProperties":false}}}}}}},"/account/keys/rotate":{"post":{"operationId":"account/rotateKeys","summary":"Rotate Account signing keys","tags":["account"],"description":"Promotes the queued key to production and generates a fresh queued key. The previously-active key is retained inside the JWK Set so tokens already issued remain verifiable via `/.well-known/jwks.json`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["rotated_at","previous_production_kid","production_kid","next_in_queue_kid","kids_active"],"properties":{"rotated_at":{"type":"string","description":"ISO 8601 timestamp of the rotation"},"previous_production_kid":{"type":"string","description":"kid that was active before rotation. Tokens signed with it are still verifiable via /.well-known/jwks.json"},"production_kid":{"type":"string","description":"kid now used to sign new tokens"},"next_in_queue_kid":{"type":"string","description":"kid that will be promoted on the next rotation"},"kids_active":{"type":"array","items":{"type":"string"},"description":"All kids currently published in the JWK Set"}},"additionalProperties":false}}}}}}},"/action":{"get":{"operationId":"action/list","summary":"List Actions","tags":["action"],"description":"List Actions","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/Action"}}},"additionalProperties":false}}}}}},"post":{"operationId":"action/create","summary":"Create Action","tags":["action"],"description":"Create Action","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","trigger"],"properties":{"name":{"type":"string","description":"Action Name","maxLength":200},"trigger":{"type":"string","description":"Trigger event name (e.g., post-login)"},"code":{"type":"string","description":"JavaScript Code to execute"},"enabled":{"type":"boolean","description":"Is this action active?","default":true},"order":{"type":"number","description":"Execution order","default":0}}}}}},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Action","content":{"application/json":{"schema":{"type":"object","required":["id","name","trigger","code","enabled","account","createdAt"],"properties":{"id":{"type":"string","description":"Action ID"},"name":{"type":"string","description":"Action Name","maxLength":200},"trigger":{"enum":["continue","post-login"],"description":"Trigger event name","default":"post-login"},"code":{"type":"string","description":"JavaScript Code to execute"},"enabled":{"type":"boolean","description":"Is this action active?","default":true},"order":{"type":"number","description":"Execution order","default":0},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ActionMetadata","default":{}},"createdAt":{"type":"string","description":"Action creation date"},"updatedAt":{"type":"string","description":"Action updated date"}},"description":"Action"}}}}}}},"/action/{action_id}":{"get":{"operationId":"action/get","summary":"Get Action","tags":["action"],"description":"Get Action","parameters":[{"schema":{"type":"string"},"in":"path","name":"action_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Action","content":{"application/json":{"schema":{"type":"object","required":["id","name","trigger","code","enabled","account","createdAt"],"properties":{"id":{"type":"string","description":"Action ID"},"name":{"type":"string","description":"Action Name","maxLength":200},"trigger":{"enum":["continue","post-login"],"description":"Trigger event name","default":"post-login"},"code":{"type":"string","description":"JavaScript Code to execute"},"enabled":{"type":"boolean","description":"Is this action active?","default":true},"order":{"type":"number","description":"Execution order","default":0},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ActionMetadata","default":{}},"createdAt":{"type":"string","description":"Action creation date"},"updatedAt":{"type":"string","description":"Action updated date"}},"description":"Action"}}}}}},"delete":{"operationId":"action/delete","summary":"Delete Action","tags":["action"],"description":"Delete Action","parameters":[{"schema":{"type":"string"},"in":"path","name":"action_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Action","content":{"application/json":{"schema":{"type":"object","required":["id","name","trigger","code","enabled","account","createdAt"],"properties":{"id":{"type":"string","description":"Action ID"},"name":{"type":"string","description":"Action Name","maxLength":200},"trigger":{"enum":["continue","post-login"],"description":"Trigger event name","default":"post-login"},"code":{"type":"string","description":"JavaScript Code to execute"},"enabled":{"type":"boolean","description":"Is this action active?","default":true},"order":{"type":"number","description":"Execution order","default":0},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"ActionMetadata","default":{}},"createdAt":{"type":"string","description":"Action creation date"},"updatedAt":{"type":"string","description":"Action updated date"}},"description":"Action"}}}}}}},"/notificationsubscription":{"get":{"operationId":"notificationsubscription/list","summary":"List Notificationsubscriptions","tags":["notificationsubscription"],"description":"List Notificationsubscriptions","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/NotificationSubscription"}}},"additionalProperties":false}}}}}},"post":{"operationId":"notificationsubscription/create","summary":"Create Notificationsubscription","tags":["notificationsubscription"],"description":"Create Notificationsubscription","requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"type":"object","required":["events","channel","config"],"properties":{"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["email"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}},"additionalProperties":false},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"NotificationSubscriptionEmailCreate","additionalProperties":false},{"type":"object","required":["events","channel","config"],"properties":{"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["webhook"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}},"additionalProperties":false},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"NotificationSubscriptionWebhookCreate","additionalProperties":false}],"description":"NotificationSubscriptionCreate"}}},"description":"NotificationSubscriptionCreate"},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"NotificationSubscription","content":{"application/json":{"schema":{"anyOf":[{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionEmail ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["email"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionEmailMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionEmail creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionEmail updated date"}},"description":"NotificationSubscriptionEmail"},{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionWebhook ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["webhook"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionWebhookMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionWebhook creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionWebhook updated date"}},"description":"NotificationSubscriptionWebhook"}],"description":"NotificationSubscription"}}}}}}},"/notificationsubscription/{notificationsubscription_id}":{"get":{"operationId":"notificationsubscription/get","summary":"Get Notificationsubscription","tags":["notificationsubscription"],"description":"Get Notificationsubscription","parameters":[{"schema":{"type":"string"},"in":"path","name":"notificationsubscription_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"NotificationSubscription","content":{"application/json":{"schema":{"anyOf":[{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionEmail ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["email"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionEmailMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionEmail creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionEmail updated date"}},"description":"NotificationSubscriptionEmail"},{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionWebhook ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["webhook"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionWebhookMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionWebhook creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionWebhook updated date"}},"description":"NotificationSubscriptionWebhook"}],"description":"NotificationSubscription"}}}}}},"post":{"operationId":"notificationsubscription/update","summary":"Update Notificationsubscription","tags":["notificationsubscription"],"description":"Update Notificationsubscription","requestBody":{"required":true,"content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["email"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}}},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Metadata update"}}},{"type":"object","properties":{"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["webhook"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}}},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Metadata update"}}}],"description":"NotificationSubscriptionUpdate"}}},"description":"NotificationSubscriptionUpdate"},"parameters":[{"schema":{"type":"string"},"in":"path","name":"notificationsubscription_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"NotificationSubscription","content":{"application/json":{"schema":{"anyOf":[{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionEmail ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["email"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionEmailMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionEmail creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionEmail updated date"}},"description":"NotificationSubscriptionEmail"},{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionWebhook ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["webhook"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionWebhookMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionWebhook creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionWebhook updated date"}},"description":"NotificationSubscriptionWebhook"}],"description":"NotificationSubscription"}}}}}},"delete":{"operationId":"notificationsubscription/delete","summary":"Delete Notificationsubscription","tags":["notificationsubscription"],"description":"Delete Notificationsubscription","parameters":[{"schema":{"type":"string"},"in":"path","name":"notificationsubscription_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"NotificationSubscription","content":{"application/json":{"schema":{"anyOf":[{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionEmail ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["email"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["recipients"],"properties":{"recipients":{"type":"array","items":{"type":"string","description":"List of email addresses receiving notifications","format":"email"}}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionEmailMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionEmail creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionEmail updated date"}},"description":"NotificationSubscriptionEmail"},{"type":"object","required":["id","events","channel","active","config","account","createdAt"],"properties":{"id":{"type":"string","description":"NotificationSubscriptionWebhook ID"},"events":{"type":"array","items":{"type":"string","description":"Events to subscribe to (e.g., user.created)"}},"channel":{"type":"string","enum":["webhook"]},"active":{"type":"boolean","description":"Whether the subscription is active"},"config":{"type":"object","required":["url","secret"],"properties":{"url":{"type":"string","description":"Webhook URL","format":"uri"},"secret":{"type":"string","description":"Secret used to sign the webhook payload"}},"additionalProperties":false},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"NotificationSubscriptionWebhookMetadata","default":{}},"createdAt":{"type":"string","description":"NotificationSubscriptionWebhook creation date"},"updatedAt":{"type":"string","description":"NotificationSubscriptionWebhook updated date"}},"description":"NotificationSubscriptionWebhook"}],"description":"NotificationSubscription"}}}}}}},"/log":{"get":{"operationId":"log/list","summary":"List Logs","tags":["log"],"description":"List Logs","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"array","items":{"type":"string","enum":["user","client","connection","team","identity"],"description":"Allowed expand paths on `log`: `user`, `client`, `connection`, `team`, `identity`."},"maxItems":5},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `?expand=user`)."},{"schema":{"type":"string","minLength":1,"maxLength":200},"in":"query","name":"q","required":false,"description":"Full-text search across: `message`."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/Log"}}},"additionalProperties":false}}}}}}},"/log/{log_id}":{"get":{"operationId":"log/get","summary":"Get Log","tags":["log"],"description":"Get Log","parameters":[{"schema":{"type":"array","items":{"type":"string","enum":["user","client","connection","team","identity"],"description":"Allowed expand paths on `log`: `user`, `client`, `connection`, `team`, `identity`."},"maxItems":5},"in":"query","name":"expand","required":false,"description":"Expand id-only fields in the response. Pass one path per entry (e.g. `?expand=user`)."},{"schema":{"type":"string"},"in":"path","name":"log_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Log","content":{"application/json":{"schema":{"type":"object","required":["id","type","status","account","createdAt"],"properties":{"id":{"type":"string","description":"Log ID"},"type":{"type":"string","description":"Log type, e.g. email.user.created"},"status":{"anyOf":[{"type":"string","enum":["success"]},{"type":"string","enum":["failed"]},{"type":"string","enum":["skipped"]},{"type":"string","enum":["info"]}],"description":"Log status"},"message":{"type":"string","description":"Optional log message"},"data":{"description":"Type-specific structured payload"},"user":{"anyOf":[{"$ref":"#/components/schemas/User"},{"type":"string"},{}]},"client":{"anyOf":[{"$ref":"#/components/schemas/Client"},{"type":"string"},{}]},"connection":{"anyOf":[{"$ref":"#/components/schemas/Connection"},{"type":"string"},{}]},"team":{"anyOf":[{"$ref":"#/components/schemas/Team"},{"type":"string"},{}]},"identity":{"anyOf":[{"$ref":"#/components/schemas/Identity"},{"type":"string"},{}]},"ticket":{"type":"string"},"expires_at":{"type":"string","format":"date-time","description":"When this log row will be auto-deleted by the Mongo TTL monitor. Absent on rows recorded without `ttl_seconds`."},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"LogMetadata","default":{}},"createdAt":{"type":"string","description":"Log creation date"},"updatedAt":{"type":"string","description":"Log updated date"}},"description":"Log"}}}}}}},"/customdomain/{customdomain_id}/retry":{"post":{"operationId":"customdomain/retry","summary":"Retry manual domain verification","tags":["customdomain"],"description":"Forces a re-verification of a Custom Domain that is in FAILED, DEGRADED or VERIFYING state. Rate-limited to one retry per minute.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string"},"in":"path","name":"customdomain_id","required":true}],"responses":{"200":{"description":"Default Response"}}}},"/customdomain":{"get":{"operationId":"customdomain/list","summary":"List Customdomains","tags":["customdomain"],"description":"List Customdomains","parameters":[{"schema":{"type":"number","minimum":1,"maximum":200},"in":"query","name":"pageSize","required":false,"description":"Number of items per page (max 200)"},{"schema":{"type":"string"},"in":"query","name":"cursor","required":false,"description":"Cursor for next page"},{"schema":{"type":"string"},"in":"query","name":"next","required":false,"description":"Cursor returned by the previous page"},{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Filter using a FaableQL query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"in":"query","name":"q","required":false,"description":"Full-text search across: `domain`."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["next","results"],"properties":{"next":{"anyOf":[{"type":"string"},{"type":"null"}]},"results":{"type":"array","items":{"$ref":"#/components/schemas/Customdomain"}}},"additionalProperties":false}}}}}},"post":{"operationId":"customdomain/create","summary":"Create Customdomain","tags":["customdomain"],"description":"Create Customdomain","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["domain"],"properties":{"domain":{"type":"string"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"Add Metadata"}},"description":"CustomdomainCreate","additionalProperties":false}}},"description":"CustomdomainCreate"},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Customdomain","content":{"application/json":{"schema":{"type":"object","required":["id","domain","token","status","attempts","account","createdAt"],"properties":{"id":{"type":"string","description":"Customdomain ID"},"domain":{"type":"string"},"token":{"type":"string"},"status":{"enum":["PENDING","VERIFYING","ACTIVE","FAILED","DEGRADED"]},"attempts":{"type":"number"},"nextCheck":{"type":"string","format":"date-time"},"lastCheck":{"type":"string","format":"date-time"},"errorLog":{"type":"string","description":"User feedback error from last check"},"verifiedAt":{"type":"string","format":"date-time"},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CustomdomainMetadata","default":{}},"createdAt":{"type":"string","description":"Customdomain creation date"},"updatedAt":{"type":"string","description":"Customdomain updated date"}},"description":"Customdomain"}}}}}}},"/customdomain/{customdomain_id}":{"get":{"operationId":"customdomain/get","summary":"Get Customdomain","tags":["customdomain"],"description":"Get Customdomain","parameters":[{"schema":{"type":"string"},"in":"path","name":"customdomain_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Customdomain","content":{"application/json":{"schema":{"type":"object","required":["id","domain","token","status","attempts","account","createdAt"],"properties":{"id":{"type":"string","description":"Customdomain ID"},"domain":{"type":"string"},"token":{"type":"string"},"status":{"enum":["PENDING","VERIFYING","ACTIVE","FAILED","DEGRADED"]},"attempts":{"type":"number"},"nextCheck":{"type":"string","format":"date-time"},"lastCheck":{"type":"string","format":"date-time"},"errorLog":{"type":"string","description":"User feedback error from last check"},"verifiedAt":{"type":"string","format":"date-time"},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CustomdomainMetadata","default":{}},"createdAt":{"type":"string","description":"Customdomain creation date"},"updatedAt":{"type":"string","description":"Customdomain updated date"}},"description":"Customdomain"}}}}}},"delete":{"operationId":"customdomain/delete","summary":"Delete Customdomain","tags":["customdomain"],"description":"Delete Customdomain","parameters":[{"schema":{"type":"string"},"in":"path","name":"customdomain_id","required":true}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Customdomain","content":{"application/json":{"schema":{"type":"object","required":["id","domain","token","status","attempts","account","createdAt"],"properties":{"id":{"type":"string","description":"Customdomain ID"},"domain":{"type":"string"},"token":{"type":"string"},"status":{"enum":["PENDING","VERIFYING","ACTIVE","FAILED","DEGRADED"]},"attempts":{"type":"number"},"nextCheck":{"type":"string","format":"date-time"},"lastCheck":{"type":"string","format":"date-time"},"errorLog":{"type":"string","description":"User feedback error from last check"},"verifiedAt":{"type":"string","format":"date-time"},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"CustomdomainMetadata","default":{}},"createdAt":{"type":"string","description":"Customdomain creation date"},"updatedAt":{"type":"string","description":"Customdomain updated date"}},"description":"Customdomain"}}}}}}},"/passwordless/verify_redirect":{"get":{"operationId":"passwordless/verify_redirect","summary":"Receive a passwordless token via email link and convert it to a valid session","tags":["passwordless"],"description":"Receive a passwordless token and convert it to a valid session","parameters":[{"schema":{"type":"string"},"in":"query","name":"token","required":true}],"responses":{"200":{"description":"Default Response"}}}},"/passwordless/start":{"post":{"operationId":"passwordless/start","summary":"Start Passwordless authentication flow","tags":["passwordless"],"description":"Start Passwordless authentication flow","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["client_id","email","send"],"properties":{"client_id":{"type":"string"},"email":{"type":"string"},"send":{"type":"string","default":"link"},"connection_id":{"type":"string"},"auth_params":{"type":"object","additionalProperties":{"type":"string"}}}}}}},"responses":{"200":{"description":"Default Response"}}}},"/me":{"get":{"operationId":"session/me","summary":"Get current User","tags":["session"],"description":"Returns the User behind the current session or bearer token. Requires a valid session cookie or `Authorization: Bearer <access_token>` header.","responses":{"200":{"description":"User","content":{"application/json":{"schema":{"type":"object","required":["id","email_verified","phone_verified","logins_count","user_metadata","app_metadata","account","createdAt"],"properties":{"id":{"type":"string","description":"User ID"},"name":{"type":"string","description":"User name","nullable":true},"username":{"type":"string","description":"unique username for this user","nullable":true},"given_name":{"type":"string","description":"Given name","nullable":true},"family_name":{"type":"string","description":"Family name","nullable":true},"middle_name":{"type":"string","description":"Middle name (OIDC §5.1)","nullable":true},"nickname":{"type":"string","description":"Casual name. Distinct from given_name (e.g. \"Mike\" vs \"Michael\"). OIDC §5.1","nullable":true},"email":{"type":"string","description":"User email","nullable":true},"email_verified":{"type":"boolean","description":"true if email is verified","default":false},"email_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `email_verified` was last set. `manual` — admin flipped the flag via `POST /user/:id`. `verification_flow` — user clicked the verification link. `passwordless_otp` — user completed passwordless OTP login. `team_invite` — user clicked a team invitation link. `email_change` — user confirmed a self-service email change. `federated` — verified by the external IdP on OAuth callback. `null` — the field was cleared (admin un-verified the email)."},"email_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `email_verified` was last flipped to true.","nullable":true},"email_change_locked_at":{"type":"string","description":"ISO 8601 timestamp of the user's last verified email change. When set, OAuth callbacks will not overwrite `email`/`email_verified` from the federated provider — the manually-chosen email wins.","nullable":true},"email_bounced_at":{"type":"string","description":"ISO 8601 timestamp of the last Postmark hard bounce / spam complaint for this address. When set, the email is treated as undeliverable and no further emails are sent to the user until the address changes.","nullable":true},"phone":{"type":"string","description":"contact phone number","nullable":true},"phone_verified":{"type":"boolean","description":"phone is verified"},"phone_verified_method":{"anyOf":[{"type":"string","enum":["manual"]},{"type":"string","enum":["verification_flow"]},{"type":"string","enum":["passwordless_otp"]},{"type":"string","enum":["team_invite"]},{"type":"string","enum":["email_change"]},{"type":"string","enum":["federated"]},{"type":"null"}],"description":"How `phone_verified` was last set. Same enum as `email_verified_method`."},"phone_verified_at":{"type":"string","description":"ISO 8601 timestamp of when `phone_verified` was last flipped to true.","nullable":true},"country_iso":{"type":"string","description":"country iso code","nullable":true},"birth_date":{"type":"string","description":"user birth_date","nullable":true},"gender":{"type":"string","description":"User gender (free-form, OIDC §5.1)","nullable":true},"zoneinfo":{"type":"string","description":"IANA time-zone name (e.g. \"Europe/Madrid\"). OIDC §5.1 — used for the `zoneinfo` claim.","nullable":true},"locale":{"type":"string","description":"user main language","nullable":true},"region":{"type":"string","description":"customer region","nullable":true},"website":{"type":"string","description":"URL of the User's personal Web page or blog (OIDC §5.1)","nullable":true},"address":{"type":"object","properties":{"formatted":{"type":"string","description":"Full mailing address, formatted for display (may contain newlines)","nullable":true},"street_address":{"type":"string","nullable":true},"locality":{"type":"string","description":"City or locality","nullable":true},"region":{"type":"string","description":"State, province, or region","nullable":true},"postal_code":{"type":"string","nullable":true},"country":{"type":"string","description":"Country name","nullable":true}},"additionalProperties":false,"nullable":true},"picture":{"type":"string","description":"User picture url","nullable":true},"logins_count":{"type":"number","description":"Total number of logins this user has performed."},"last_ip":{"type":"string","description":"Last IP address from which this user logged in","nullable":true},"last_login":{"type":"string","description":"Last date and time this user logged in (ISO_8601 format)","nullable":true},"user_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"User Metadata","default":{}},"app_metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"App Metadata","default":{}},"account":{"type":"string","description":"Object is related with this account"},"metadata":{"type":"object","properties":{},"additionalProperties":true,"description":"UserMetadata","default":{}},"createdAt":{"type":"string","description":"User creation date"},"updatedAt":{"type":"string","description":"User updated date"}},"description":"User"}}}}}}},"/logout":{"get":{"operationId":"session/logout","summary":"OpenID Connect RP-Initiated Logout","tags":["session"],"description":"Destroys the current session. Implements OIDC RP-Initiated Logout 1.0 and Front-Channel Logout 1.0: when RPs with a registered `frontchannel_logout_uri` participated in the session, returns an HTML page with one iframe per RP and (when applicable) auto-redirects to `post_logout_redirect_uri`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"id_token_hint","required":false,"description":"Previously issued id_token. RECOMMENDED per OIDC §3 — used to identify the client/session being logged out."},{"schema":{"type":"string"},"in":"query","name":"logout_hint","required":false,"description":"Hint about the End-User that is logging out (e.g. session id, email). Provider-specific."},{"schema":{"type":"string"},"in":"query","name":"client_id","required":false,"description":"OAuth Client identifier. Derived from `id_token_hint.aud` if omitted."},{"schema":{"type":"string"},"in":"query","name":"post_logout_redirect_uri","required":false,"description":"URL to redirect the User to after logout. MUST be pre-registered in the client `logout_urls` (exact match)."},{"schema":{"type":"string"},"in":"query","name":"state","required":false,"description":"Opaque value echoed back as `state` query param on the post-logout redirect, to mitigate CSRF."},{"schema":{"type":"string"},"in":"query","name":"ui_locales","required":false,"description":"Space-separated list of preferred UI languages."},{"schema":{"type":"string"},"in":"query","name":"returnTo","required":false,"description":"Deprecated alias of `post_logout_redirect_uri`. Kept for backwards compatibility."}],"responses":{"200":{"description":"Default Response"}}}},"/authorize":{"get":{"operationId":"authorize","summary":"Authorization request","tags":["oauth"],"description":"Authorization request","parameters":[{"schema":{"type":"string"},"in":"query","name":"response_type","required":false},{"schema":{"type":"string"},"in":"query","name":"code_challenge_method","required":false,"description":"Challenge method for PKCE. Only S256 is supported."},{"schema":{"type":"string"},"in":"query","name":"code_challenge","required":false,"description":"Challenge for PKCE authorization code flow"},{"schema":{"type":"string"},"in":"query","name":"redirect_to","required":false,"description":"Same-origin path to return the user to after authentication, instead of the OAuth client redirect. Used by first-party interactive flows (e.g. device-code confirm). Non same-origin values are ignored."},{"schema":{"type":"string"},"in":"query","name":"client_id","required":true},{"schema":{"type":"string"},"in":"query","name":"connection","required":false,"description":"Deprecated. Use connection_id"},{"schema":{"type":"string"},"in":"query","name":"connection_id","required":false,"description":"Which oauth connection to use. Leave empty to use default connection"},{"schema":{"type":"string"},"in":"query","name":"scope","required":false},{"schema":{"type":"string"},"in":"query","name":"redirect_uri","required":false,"description":"The URL to which Faable will redirect the browser after authorization has been granted by the user."},{"schema":{"type":"string"},"in":"query","name":"state","required":false,"description":"An opaque value the applications adds to the initial request that the authorization server includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks."},{"schema":{"type":"string"},"in":"query","name":"nonce","required":false,"description":"OIDC §3.1.2.1 — string value used to associate a Client session with an ID Token, to mitigate replay attacks. If passed at /authorize, the same value MUST appear in the issued id_token."},{"schema":{"type":"number","minimum":0},"in":"query","name":"max_age","required":false,"description":"OIDC §3.1.2.1 — maximum allowable elapsed time in seconds since the last End-User authentication. If exceeded, the OP re-authenticates and `auth_time` is REQUIRED in the resulting id_token."},{"schema":{"type":"string"},"in":"query","name":"prompt","required":false},{"schema":{"type":"string"},"in":"query","name":"audience","required":false,"description":"Auth0-compatible alias for `resource` (RFC 8707). When both are sent they must match. Identifier of the Api the client wants to access; persisted in the auth state so the token issued at /oauth/token targets the matching Api resource."},{"schema":{"type":"string"},"in":"query","name":"resource","required":false,"description":"RFC 8707 Resource Indicator. MUST be an absolute URI without fragment. When matched against a registered Api in the tenant the issued access_token gets `aud = <api.identifier>`."}],"responses":{"200":{"description":"Default Response"}}}},"/oauth/token":{"get":{"operationId":"oauth/tokenGet","summary":"OAuth2 Token endpoint (GET)","tags":["oauth"],"description":"OAuth2 Token endpoint (RFC 6749 §3.2). Exchanges credentials for tokens depending on `grant_type` (authorization_code, client_credentials, refresh_token, password, otp, token_exchange, device_code). The GET variant accepts the same parameters as querystring.","parameters":[{"schema":{"anyOf":[{"type":"string","enum":["authorization_code"]},{"type":"string","enum":["client_credentials"]},{"type":"string","enum":["refresh_token"]},{"type":"string","enum":["password"]},{"type":"string","enum":["http://auth0.com/oauth/grant-type/passwordless/otp"]},{"type":"string","enum":["urn:ietf:params:oauth:grant-type:token-exchange"]},{"type":"string","enum":["urn:ietf:params:oauth:grant-type:device_code"]}]},"in":"query","name":"grant_type","required":false,"description":"Grant Type. https://oauth.net/2/grant-types/"},{"schema":{"type":"string"},"in":"query","name":"client_id","required":false},{"schema":{"type":"string"},"in":"query","name":"client_secret","required":false},{"schema":{"type":"string"},"in":"query","name":"scope","required":false},{"schema":{"type":"string"},"in":"query","name":"code","required":false},{"schema":{"type":"string"},"in":"query","name":"code_verifier","required":false},{"schema":{"type":"string"},"in":"query","name":"username","required":false},{"schema":{"type":"string"},"in":"query","name":"otp","required":false},{"schema":{"type":"string"},"in":"query","name":"refresh_token","required":false},{"schema":{"type":"string"},"in":"query","name":"subject_token","required":false},{"schema":{"type":"string"},"in":"query","name":"subject_token_type","required":false},{"schema":{"type":"string"},"in":"query","name":"device_code","required":false,"description":"The device code returned by the authorization server."},{"schema":{"type":"string"},"in":"query","name":"audience","required":false,"description":"Auth0-compatible alias for `resource` (RFC 8707). When both are provided they must match."},{"schema":{"type":"string"},"in":"query","name":"resource","required":false,"description":"RFC 8707 Resource Indicator. Absolute URI of the target Api, no fragment. Matched against `Api.identifier` in the tenant."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["token_type","expires_in","access_token"],"properties":{"token_type":{"type":"string"},"expires_in":{"type":"number"},"access_token":{"type":"string"},"refresh_token":{"type":"string"},"id_token":{"type":"string"},"scope":{"type":"string"}}}}}}}},"post":{"operationId":"oauth/token","summary":"OAuth2 Token endpoint","tags":["oauth"],"description":"OAuth2 Token endpoint (RFC 6749 §3.2). Exchanges credentials for tokens depending on `grant_type` (authorization_code, client_credentials, refresh_token, password, otp, token_exchange, device_code).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"grant_type":{"anyOf":[{"type":"string","enum":["authorization_code"]},{"type":"string","enum":["client_credentials"]},{"type":"string","enum":["refresh_token"]},{"type":"string","enum":["password"]},{"type":"string","enum":["http://auth0.com/oauth/grant-type/passwordless/otp"]},{"type":"string","enum":["urn:ietf:params:oauth:grant-type:token-exchange"]},{"type":"string","enum":["urn:ietf:params:oauth:grant-type:device_code"]}],"description":"Grant Type. https://oauth.net/2/grant-types/"},"client_id":{"type":"string"},"client_secret":{"type":"string"},"scope":{"type":"string"},"code":{"type":"string"},"code_verifier":{"type":"string"},"username":{"type":"string"},"otp":{"type":"string"},"refresh_token":{"type":"string"},"subject_token":{"type":"string"},"subject_token_type":{"type":"string"},"device_code":{"type":"string","description":"The device code returned by the authorization server."},"audience":{"type":"string","description":"Auth0-compatible alias for `resource` (RFC 8707). When both are provided they must match."},"resource":{"type":"string","description":"RFC 8707 Resource Indicator. Absolute URI of the target Api, no fragment. Matched against `Api.identifier` in the tenant."}},"additionalProperties":true}}}},"parameters":[{"schema":{"anyOf":[{"type":"string","enum":["authorization_code"]},{"type":"string","enum":["client_credentials"]},{"type":"string","enum":["refresh_token"]},{"type":"string","enum":["password"]},{"type":"string","enum":["http://auth0.com/oauth/grant-type/passwordless/otp"]},{"type":"string","enum":["urn:ietf:params:oauth:grant-type:token-exchange"]},{"type":"string","enum":["urn:ietf:params:oauth:grant-type:device_code"]}]},"in":"query","name":"grant_type","required":false,"description":"Grant Type. https://oauth.net/2/grant-types/"},{"schema":{"type":"string"},"in":"query","name":"client_id","required":false},{"schema":{"type":"string"},"in":"query","name":"client_secret","required":false},{"schema":{"type":"string"},"in":"query","name":"scope","required":false},{"schema":{"type":"string"},"in":"query","name":"code","required":false},{"schema":{"type":"string"},"in":"query","name":"code_verifier","required":false},{"schema":{"type":"string"},"in":"query","name":"username","required":false},{"schema":{"type":"string"},"in":"query","name":"otp","required":false},{"schema":{"type":"string"},"in":"query","name":"refresh_token","required":false},{"schema":{"type":"string"},"in":"query","name":"subject_token","required":false},{"schema":{"type":"string"},"in":"query","name":"subject_token_type","required":false},{"schema":{"type":"string"},"in":"query","name":"device_code","required":false,"description":"The device code returned by the authorization server."},{"schema":{"type":"string"},"in":"query","name":"audience","required":false,"description":"Auth0-compatible alias for `resource` (RFC 8707). When both are provided they must match."},{"schema":{"type":"string"},"in":"query","name":"resource","required":false,"description":"RFC 8707 Resource Indicator. Absolute URI of the target Api, no fragment. Matched against `Api.identifier` in the tenant."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["token_type","expires_in","access_token"],"properties":{"token_type":{"type":"string"},"expires_in":{"type":"number"},"access_token":{"type":"string"},"refresh_token":{"type":"string"},"id_token":{"type":"string"},"scope":{"type":"string"}}}}}}}}},"/oauth/device/code":{"post":{"operationId":"oauth/deviceCode","summary":"Device authorization request","tags":["oauth"],"description":"OAuth2 Device Authorization Grant (RFC 8628) — start step. A device that cannot run a browser calls this endpoint to obtain a `device_code`, a `user_code` to show to the user, and the verification URLs to display.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["client_id"],"properties":{"client_id":{"type":"string","description":"The client ID of the application."},"scope":{"type":"string","description":"The scope of the access request."},"audience":{"type":"string","description":"Identifier of the API the device wants to access. Resolved against the tenant Api resources (`Api.identifier`) at token issuance."},"device_name":{"type":"string","description":"Human-friendly name of the requesting device (e.g. \"marcs-mbp (macOS)\"). Shown on the confirm page so the user can recognise the device being authorised.","maxLength":200}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["device_code","user_code","verification_uri","verification_uri_complete","expires_in","interval"],"properties":{"device_code":{"type":"string"},"user_code":{"type":"string"},"verification_uri":{"type":"string"},"verification_uri_complete":{"type":"string"},"expires_in":{"type":"number"},"interval":{"type":"number"}}}}}}}}},"/activate":{"get":{"operationId":"oauth/deviceActivate","summary":"Device activation redirect","tags":["oauth"],"description":"Entry URL displayed on the device. Redirects the browser to the external `/flow/device-code/activate` UI where the user enters their `user_code`.","parameters":[{"schema":{"type":"string"},"in":"query","name":"user_code","required":false}],"responses":{"200":{"description":"Default Response"}}}},"/confirm":{"get":{"operationId":"oauth/deviceConfirm","summary":"Device confirmation redirect","tags":["oauth"],"description":"Redirects to the external `/flow/device-code/confirm` UI after the user enters their `user_code`. The UI then calls `/oauth/device/authorize` to grant the device.","parameters":[{"schema":{"type":"string"},"in":"query","name":"user_code","required":false}],"responses":{"200":{"description":"Default Response"}}}},"/oauth/device/verify":{"post":{"operationId":"oauth/deviceVerify","summary":"Verify a device user_code","tags":["oauth"],"description":"Called by the external UI after the user enters their `user_code`. Returns the matching `device_code` and minimal client info so the UI can render \"Authorize <App>?\".","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["user_code"],"properties":{"user_code":{"type":"string"}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["device_code","client"],"properties":{"device_code":{"type":"string"},"device_name":{"type":"string"},"client":{"type":"object","properties":{"name":{"type":"string"},"client_id":{"type":"string"}}}}}}}}}}},"/oauth/device/authorize":{"post":{"operationId":"oauth/deviceAuthorize","summary":"Authorize a pending device request","tags":["oauth"],"description":"Authorizes a `device_code` on behalf of the currently authenticated user, allowing the device to subsequently exchange that code for tokens at `/oauth/token`. Called by the first-party device-code confirm page, so it authenticates with the browser `faable_sess` session — NOT a bearer token (the page has no access token to send).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["device_code"],"properties":{"device_code":{"type":"string"}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["success"],"properties":{"success":{"type":"boolean"}}}}}}}}},"/callback":{"get":{"operationId":"callback","summary":"OAuth2 Callback URL","tags":["oauth"],"description":"OAuth2 Callback URL","parameters":[{"schema":{"type":"string"},"in":"query","name":"code","required":false},{"schema":{"type":"string"},"in":"query","name":"state","required":false},{"schema":{"type":"string"},"in":"query","name":"error","required":false},{"schema":{"type":"string"},"in":"query","name":"error_uri","required":false},{"schema":{"type":"string"},"in":"query","name":"error_description","required":false}],"responses":{"200":{"description":"Default Response"}}}},"/continue":{"get":{"operationId":"oauth_continue","summary":"OAuth2 Resume URL","tags":["oauth"],"description":"Resume OAuth flow after a progressive profiling action","parameters":[{"schema":{"type":"string","minLength":1},"in":"query","name":"state","required":true}],"responses":{"200":{"description":"Default Response"}}}},"/.well-known/openid-configuration":{"get":{"operationId":"oauth/openidConfiguration","summary":"OpenID Connect Discovery document","tags":["oauth"],"description":"Returns the OpenID Provider Configuration document for this Account (issuer, supported endpoints, response types, signing algorithms, claims, etc.) as defined by OIDC Discovery 1.0.","responses":{"200":{"description":"Default Response"}}}},"/.well-known/jwks.json":{"get":{"operationId":"oauth/jwks","summary":"JSON Web Key Set","tags":["oauth"],"description":"Returns the public JWKs (RFC 7517) used to verify tokens issued by this Account. Consumers MUST use the `kid` from a token header to select the right key.","responses":{"200":{"description":"Default Response"}}}},"/userinfo":{"get":{"operationId":"oauth/userinfo","summary":"OpenID Connect UserInfo endpoint","tags":["oauth"],"description":"Returns claims about the authenticated User. Authentication is via a Bearer access token (RFC 6750). Returned claims are filtered by the `scope` claim of the access token (OIDC §5.3.2). The response always contains `sub`. See https://openid.net/specs/openid-connect-core-1_0.html#UserInfo.","responses":{"200":{"description":"OpenID Connect UserInfo response (https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse).","content":{"application/json":{"schema":{"type":"object","required":["sub"],"properties":{"sub":{"type":"string","description":"Subject identifier (user id)"},"name":{"type":"string"},"family_name":{"type":"string"},"given_name":{"type":"string"},"nickname":{"type":"string"},"preferred_username":{"type":"string"},"picture":{"type":"string"},"birthdate":{"type":"string"},"locale":{"type":"string"},"updated_at":{"type":"number"},"email":{"type":"string"},"email_verified":{"type":"boolean"},"phone_number":{"type":"string"},"phone_number_verified":{"type":"boolean"}},"additionalProperties":true,"description":"OpenID Connect UserInfo response (https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse)."}}}}}},"post":{"operationId":"oauth/userinfoPost","summary":"OpenID Connect UserInfo endpoint (POST)","tags":["oauth"],"description":"Same as `GET /userinfo`. Provided for clients that prefer to send the Bearer token in a POST body or are required to by spec compliance audits.","responses":{"200":{"description":"OpenID Connect UserInfo response (https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse).","content":{"application/json":{"schema":{"type":"object","required":["sub"],"properties":{"sub":{"type":"string","description":"Subject identifier (user id)"},"name":{"type":"string"},"family_name":{"type":"string"},"given_name":{"type":"string"},"nickname":{"type":"string"},"preferred_username":{"type":"string"},"picture":{"type":"string"},"birthdate":{"type":"string"},"locale":{"type":"string"},"updated_at":{"type":"number"},"email":{"type":"string"},"email_verified":{"type":"boolean"},"phone_number":{"type":"string"},"phone_number_verified":{"type":"boolean"}},"additionalProperties":true,"description":"OpenID Connect UserInfo response (https://openid.net/specs/openid-connect-core-1_0.html#UserInfoResponse)."}}}}}}},"/oidc/register":{"post":{"operationId":"oauth/register","summary":"OpenID Connect Dynamic Client Registration","tags":["oauth"],"description":"Register a new OAuth/OIDC client dynamically (OIDC Dynamic Client Registration 1.0 / RFC 7591). The new client is bound to the Account resolved from the request context.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["redirect_uris"],"properties":{"redirect_uris":{"type":"array","items":{"type":"string","format":"uri"},"description":"Array of redirection URI values used by the client (RFC 7591 §2). REQUIRED for any client that uses an authorization grant.","minItems":1},"client_name":{"type":"string","description":"Human-readable name of the client (RFC 7591 §2)"},"client_uri":{"type":"string","description":"URL of the home page of the client"},"logo_uri":{"type":"string"},"tos_uri":{"type":"string"},"policy_uri":{"type":"string"},"contacts":{"type":"array","items":{"type":"string"},"description":"Array of email addresses responsible for the client"},"grant_types":{"type":"array","items":{"type":"string"},"description":"Grant types the client will use. Defaults to [\"authorization_code\"]. Must be a subset of what the server supports."},"response_types":{"type":"array","items":{"type":"string"},"description":"Response types the client will use. Defaults to [\"code\"]."},"token_endpoint_auth_method":{"type":"string","description":"How the client authenticates at the token endpoint. Defaults to \"client_secret_basic\"."},"application_type":{"anyOf":[{"type":"string","enum":["web"]},{"type":"string","enum":["native"]}],"description":"OIDC §2 — application type. Defaults to \"web\"."},"post_logout_redirect_uris":{"type":"array","items":{"type":"string"},"description":"OIDC RP-Initiated Logout — URIs the OP MAY redirect to after end-session."},"scope":{"type":"string","description":"Space-separated list of scope values the client may use."},"software_id":{"type":"string"},"software_version":{"type":"string"},"frontchannel_logout_uri":{"type":"string","description":"OIDC Front-Channel Logout 1.0 — URL the OP loads inside an iframe at end-session to let the RP clear its session."},"frontchannel_logout_session_required":{"type":"boolean","description":"OIDC Front-Channel Logout 1.0 — when true, the OP MUST include `iss` and `sid` parameters when calling the frontchannel_logout_uri."}},"additionalProperties":true}}}},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["client_id","client_secret","client_id_issued_at","client_secret_expires_at","redirect_uris","grant_types","response_types","token_endpoint_auth_method","application_type"],"properties":{"client_id":{"type":"string"},"client_secret":{"type":"string"},"client_id_issued_at":{"type":"number","description":"Unix timestamp (seconds) at which the client_id was issued"},"client_secret_expires_at":{"type":"number","description":"0 if the client_secret does not expire"},"redirect_uris":{"type":"array","items":{"type":"string"}},"client_name":{"type":"string"},"client_uri":{"type":"string"},"logo_uri":{"type":"string"},"tos_uri":{"type":"string"},"policy_uri":{"type":"string"},"contacts":{"type":"array","items":{"type":"string"}},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string"},"application_type":{"type":"string"},"post_logout_redirect_uris":{"type":"array","items":{"type":"string"}},"scope":{"type":"string"},"software_id":{"type":"string"},"software_version":{"type":"string"},"frontchannel_logout_uri":{"type":"string"},"frontchannel_logout_session_required":{"type":"boolean"}},"additionalProperties":true}}}}}}},"/usernamepassword/login":{"post":{"operationId":"usernamepassword/login","summary":"Username + password login","tags":["usernamepassword"],"description":"Authenticates a user with username/password credentials against the database connection and renders an auto-submitting form that posts the resulting token to `/login/callback`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["username","password","client_id"],"properties":{"username":{"type":"string"},"password":{"type":"string"},"state":{"type":"string","description":"An opaque value the applications adds to the initial request that the authorization server includes when redirecting the back to the application. This value must be used by the application to prevent CSRF attacks."},"response_type":{"type":"string"},"redirect_to":{"type":"string","description":"Same-origin path to return the user to after authentication, instead of the OAuth client redirect. Used by first-party interactive flows (e.g. device-code confirm). Non same-origin values are ignored."},"client_id":{"type":"string"},"connection":{"type":"string","description":"Deprecated. Use connection_id"},"connection_id":{"type":"string","description":"Which oauth connection to use. Leave empty to use default connection"},"scope":{"type":"string"},"redirect_uri":{"type":"string","description":"The URL to which Faable will redirect the browser after authorization has been granted by the user."},"nonce":{"type":"string","description":"OIDC §3.1.2.1 — string value used to associate a Client session with an ID Token, to mitigate replay attacks. If passed at /authorize, the same value MUST appear in the issued id_token."},"max_age":{"type":"number","description":"OIDC §3.1.2.1 — maximum allowable elapsed time in seconds since the last End-User authentication. If exceeded, the OP re-authenticates and `auth_time` is REQUIRED in the resulting id_token.","minimum":0},"prompt":{"type":"string"},"audience":{"type":"string","description":"Auth0-compatible alias for `resource` (RFC 8707). When both are sent they must match. Identifier of the Api the client wants to access; persisted in the auth state so the token issued at /oauth/token targets the matching Api resource."},"resource":{"type":"string","description":"RFC 8707 Resource Indicator. MUST be an absolute URI without fragment. When matched against a registered Api in the tenant the issued access_token gets `aud = <api.identifier>`."}},"description":"UsernamepasswordLoginBody","additionalProperties":false}}},"description":"UsernamepasswordLoginBody"},"responses":{"200":{"description":"Default Response"}}}},"/login/callback":{"post":{"operationId":"usernamepassword/loginCallback","summary":"Username + password login callback","tags":["usernamepassword"],"description":"Completes the username/password login flow. The token issued by `/usernamepassword/login` is posted back here together with the serialized state (`wctx`) so the server can redirect the user agent to the original client `redirect_uri`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["wa","wresult","wctx"],"properties":{"wa":{"type":"string","description":"is always wsignin1.0"},"wresult":{"type":"string","description":"JWT"},"wctx":{"type":"string","description":"Serialized JSON with context"}}}}}},"responses":{"200":{"description":"Default Response"}}}},"/dbconnections/change_password":{"post":{"operationId":"change_password","summary":"Change password","tags":["dbconnection"],"description":"Change password","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email"],"properties":{"email":{"type":"string"}}}}}},"responses":{"200":{"description":"Default Response"}}}},"/reset-verify":{"get":{"operationId":"change_password_verify","summary":"Change password verify","tags":["dbconnection"],"description":"Change password verify","parameters":[{"schema":{"type":"string"},"in":"query","name":"ticket","required":true}],"responses":{"200":{"description":"Default Response"}}}},"/reset-change":{"post":{"operationId":"change_password_change","summary":"Reset password change","tags":["dbconnection"],"description":"Reset password change","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["state","new_password"],"properties":{"state":{"type":"string"},"new_password":{"type":"string","minLength":1}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["ok"]}}}}}}}}},"/version":{"get":{"operationId":"getVersion","summary":"Get the running service version and git commit","tags":["system"],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"version":{"type":"string"},"commit":{"type":"string"}}}}}}}}}},"servers":[{"url":"https://faable.auth.faable.link","description":"Faable (account_6475c88abdb00153b3494b8e)"}],"tags":[{"name":"user","description":"👨🏻‍💻 Manage Users"},{"name":"passwordless","description":"🪄 Passwordless authorization","externalDocs":{"url":"https://faable.com/docs/auth/passwordless"}},{"name":"session","description":"🪄 Current session endpoints"},{"name":"client","description":"🌏 Manage OAuth Clients","externalDocs":{"url":"https://faable.com/docs/auth/clients"}},{"name":"oauth","description":"OAuth Endpoints","externalDocs":{"url":"https://faable.com/docs/auth/oauth-flows/authorization-code"}},{"name":"connection","description":"Social connections and Authorization Servers","externalDocs":{"url":"https://faable.com/docs/auth/connections"}},{"name":"identity","description":"Identities fetched from Connections like Google, Slack, Facebook, etc."},{"name":"role","description":"Account-wide roles. A Role is a named label (e.g. `admin`, `editor`) that can be granted to users via RoleMember. Roles are the primary RBAC primitive used by downstream services to gate access."},{"name":"rolemember","description":"Grants of a Role to a User at the account level. Each RoleMember binds one (role, user) pair. Use `GET /role/:role_id/users` to list everyone holding a given role, and `POST /role/:role_id/users` to grant a role to one or more users in bulk."},{"name":"team","description":"Groups of Users inside an Account. Teams scope membership and per-team role assignments — a User can belong to multiple Teams and hold different Roles in each. Members are managed via the `/team/:team_id/member` sub-resource."},{"name":"api","description":"Resource Servers protected by Faable Auth. Each Api declares an `identifier` (audience URL clients pass as `audience=` when requesting a token), the `permissions` it exposes, and its token issuance policy (`token_dialect`, `token_lifetime`, `enforce_policies`). Tokens issued with `audience=<identifier>` carry that identifier in the `aud` claim and, when `token_dialect=access_token_authz`, a filtered `permissions` claim.","externalDocs":{"url":"https://faable.com/docs/auth/apis"}}]}