Skip to content
FidmosDocumentation

Error codes

Fidmos errors come in three different shapes — they depend on which endpoint answered. This page shows each shape and its codes.

  • Embed (/api/v1/embed/*) — the envelope { "error": "<code>" }, HTTP 422 (or 401 for invalid_client).
  • Token (POST /oauth/token) — the OAuth 2.0 standard (RFC 6749): { "error": "...", "error_description": "..." }.
  • UserInfo and Server-to-Server API — the Laravel shape: { "message": "...", "errors": { … } } or 401/403 for token problems.

Flow initialization — POST /api/v1/embed/init

Section titled “Flow initialization — POST /api/v1/embed/init”

This is called by the sign-in widget (sdk.js), not you — the window shows the errors. The envelope is { "error": "<code>" }.

Code HTTP Reason
invalid_client 401 unknown or inactive client_id
invalid_redirect_uri 422 redirect_uri is not in the allow-list
invalid_origin 422 the page origin is not allowed for the client

These are called by the sign-in widget (the steps under /api/v1/embed/: login, login/send, telegram, siwe/*, identity/create, complete) — you, the partner, do not need to call them. Common to any window step are the flow-check errors:

Code Reason
flow_expired the flow was not found or has expired
parent_origin_mismatch the request came from a foreign origin

Sending the code (/login/send):

Code Reason
code_send_limit the code-send limit is exhausted
flow_too_short the flow has too little lifetime left — a new code is not issued
invalid_flow_state the flow is at the wrong step

Verifying the code (/login):

Code Reason
invalid_code the code is wrong
code_expired the code has expired
code_attempts_exhausted attempts are exhausted
identity_taken the binding is taken by another user

Telegram (/telegram) — the Telegram sign-in flow:

Code Reason
telegram_invalid the Telegram data failed the signature check

Wallet — SIWE (/siwe/verify) — the wallet sign-in flow:

Code Reason
nonce_mismatch the nonce in the message did not match the issued one

Plus the codes for verifying the SIWE message and signature themselves — their full list is on the wallet sign-in page.

Creating a user (/identity/create) — for Telegram and wallet sign-in:

Code Reason
no_pending_identity there is no pending sign-in method to create a user from
identity_taken the method being bound is taken by another user

Completion (/complete):

Code HTTP Reason
invalid_completion 409 the flow completion failed
authorization_failed 422 the window could not issue an authorization code

Standard OAuth 2.0 errors in the shape { "error": "...", "error_description": "..." }:

error Reason
invalid_grant the code is wrong, expired, already used, or the code_verifier did not match
invalid_client wrong client credentials
invalid_request a required parameter is missing
unsupported_grant_type an unsupported grant_type

GET /oauth/userinfo and /api/v1/* answer in the Laravel shape:

  • 401 — the token is missing, expired or revoked.
  • 403 — only Server-to-Server /api/v1/*: the client token lacks the users.read scope. /oauth/userinfo does not refuse by scope — it returns sub and the claims the token’s scope allows.
  • 422 with { "message": "...", "errors": { "field": ["…"] } } — validation failed.
  1. Look at the shape of the response — it tells you which endpoint answered.
  2. Take the machine-readable code (error) — branch your logic on it, not on the text.
  3. The text (error_description / message) is for logs and humans, not for conditions in code.
Symptom Reason What to do
invalid_redirect_uri, or a redirect_uri error at /oauth/authorize//oauth/token redirect_uri did not match the registered one — the match is exact Register the exact URL in the application (dashboard → Applications): scheme, host, path, trailing slash; send it unchanged in the request
invalid_origin or parent_origin_mismatch The page with the widget is opened from a non-allowed domain The allowed origin is derived from the application’s redirect_uris — add the domain to redirect_uris (dashboard → Applications) and open the window from it
A CORS error on /api/v1/embed/* in the browser The request went from a domain that is not among the application’s origins Add the window’s domain to the application’s redirect_uris (dashboard → Applications) — the origin is taken from there, and the server returns the right CORS headers for it
invalid_client Wrong client_id / client_secret Check the pair; client_secret is not the public client_id, and it lives only on the backend
invalid_grant on the code exchange The code expired or was already used, the wrong redirect_uri, or the code_verifier does not match the code_challenge (PKCE mismatch) Exchange the code with the same code_verifier that arrived in onSuccess; the code is one-time; redirect_uri is the same one passed to login
No email in the profile, or email_verified: false A user without an email (wallet/Telegram sign-in) or an unverified email Identify by sub, not by email; do not require it to be present and do not trust email_verified: false