{"record":{"id":"65df956b26472457","repo":"we-promise/sure","slug":"trading-212-authentication-failed-response-code","errorCode":null,"errorMessage":"Trading 212 authentication failed (#{response.code}). Check your API key.","messagePattern":"Trading 212 authentication failed \\(#(.+?)\\)\\. Check your API key\\.","errorType":"exception","errorClass":"Provider::Trading212::AuthenticationError","httpStatus":401,"severity":"critical","filePath":"app/models/provider/trading212.rb","lineNumber":135,"sourceCode":"      end\n\n      items\n    end\n\n    def extract_cursor(next_page_path)\n      uri = URI.parse(\"https://placeholder#{next_page_path}\")\n      params = URI.decode_www_form(uri.query.to_s).to_h\n      params[\"cursor\"]\n    rescue URI::InvalidURIError\n      nil\n    end\n\n    def handle_response(response)\n      case response.code\n      when 200, 201\n        response.parsed_response\n      when 401, 403\n        raise AuthenticationError, \"Trading 212 authentication failed (#{response.code}). Check your API key.\"\n      when 429\n        raise RateLimitError, \"Trading 212 rate limit exceeded. Please wait before retrying.\"\n      else\n        raise ApiError.new(\n          \"Trading 212 API error (status #{response.code})\",\n          status_code: response.code,\n          response_body: response.body\n        )\n      end\n    end\n\n    def with_retries(label, max_retries: 3)\n      attempt = 0\n      begin\n        attempt += 1\n        yield\n      rescue *RETRYABLE_ERRORS => e\n        raise if attempt >= max_retries","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/trading212.rb#L117-L153","documentation":"Provider::Trading212::AuthenticationError raised in handle_response when the Trading 212 REST API answers HTTP 401 or 403. It means the Basic auth header (Base64 api_key:api_secret) was rejected: wrong credentials, regenerated key, or API access disabled on the account.","triggerScenarios":"Any GET via the provider — /equity/account/summary, /equity/positions, /equity/history/orders pagination — where Trading 212 returns 401 (bad credentials) or 403 (key valid but not entitled, e.g. API not enabled or read-only restriction).","commonSituations":"User regenerated the Trading 212 API key in the app so the stored secret is now stale; the API key was created for the demo environment but the client is set to live (or vice versa); Trading 212 revoked API access for the account; key/secret swapped when copying.","solutions":["Verify the api_key/api_secret pair in Trading 212 under Settings > API and confirm API access is enabled for that environment (live vs demo must match the environment argument)","Re-enter both credentials in the app's provider settings and retry the connection — stale regenerated keys are the most common cause","If using demo, instantiate with environment: \"demo\" and use a key generated in the demo app","Handle this error in sync jobs by marking the account connection as 'needs reconnection' rather than retrying — credentials will not fix themselves"],"exampleFix":"// before\nsummary = client.fetch_account_summary\n\n// after\nbegin\n  summary = client.fetch_account_summary\nrescue Provider::Trading212::AuthenticationError\n  account_provider.update!(status: \"reauth_required\")\n  notify_user(\"Reconnect your Trading 212 account\")\nend","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"begin\n  client.fetch_account_summary\nrescue Provider::Trading212::AuthenticationError\n  account_provider.update!(status: \"reauth_required\")\n  notify_user(\"Trading 212 credentials rejected — reconnect the account\")\n  # never retry: credentials are stale until a human acts\nend","preventionTips":["Treat 401/403 as terminal: mark the connection for reconnection, don't retry","Check credentials with a cheap fetch_account_summary call right after the user saves them","Alert the user when Trading 212 regenerates keys, since stored secrets go stale immediately"],"tags":["ruby","trading212","authentication","http-401","http-403","api"],"backgroundTag":"api-authentication-failed","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}