we-promise/sure · error · Provider::Trading212::ApiError
Trading 212 API error (status #{response.code})
Error message
Trading 212 API error (status #{response.code}) What it means
Provider::Trading212 raises ApiError for any HTTP status not otherwise mapped in handle_response - i.e. everything except 200/201 (success), 401/403 (AuthenticationError) and 429 (RateLimitError). The error carries status_code and response_body accessors so callers can branch on the exact status.
Source
Thrown at app/models/provider/trading212.rb:139
def extract_cursor(next_page_path)
uri = URI.parse("https://placeholder#{next_page_path}")
params = URI.decode_www_form(uri.query.to_s).to_h
params["cursor"]
rescue URI::InvalidURIError
nil
end
def handle_response(response)
case response.code
when 200, 201
response.parsed_response
when 401, 403
raise AuthenticationError, "Trading 212 authentication failed (#{response.code}). Check your API key."
when 429
raise RateLimitError, "Trading 212 rate limit exceeded. Please wait before retrying."
else
raise ApiError.new(
"Trading 212 API error (status #{response.code})",
status_code: response.code,
response_body: response.body
)
end
end
def with_retries(label, max_retries: 3)
attempt = 0
begin
attempt += 1
yield
rescue *RETRYABLE_ERRORS => e
raise if attempt >= max_retries
delay = [ 2**attempt, 30 ].min
DebugLogEntry.capture(
category: "sync",
level: "warn",View on GitHub (pinned to e69894adb9)
Solutions
- Inspect e.status_code and e.response_body first - the fix depends entirely on the status
- If 404: verify the endpoint path and that environment ("live" vs "demo") matches where the key was created
- If 5xx: retry later with backoff; Trading212 equities API has frequent transient failures
- If 400/422: log response_body for the exact validation message Trading212 returns and fix the request params
- Confirm the account has 'API access' enabled in Trading212 settings for the endpoints being called
Example fix
# before
summary = client.fetch_account_summary
# after
begin
summary = client.fetch_account_summary
rescue Provider::Trading212::ApiError => e
Rails.logger.warn("T212 #{e.status_code}: #{e.response_body}")
raise if e.status_code.to_i / 100 == 4 # client/config problem - do not retry
sleep(30) && retry if (retries += 1) < 3 # 5xx - transient
raise
end Defensive patterns
Strategy: try-catch
Validate before calling
# Confirm environment matches the key before first call expected = item.environment == "demo" ? "demo.trading212.com" : "live.trading212.com" raise ArgumentError, "environment/base_uri mismatch" unless base_uri.include?(expected)
Type guard
def t212_api_error?(err) err.is_a?(Provider::Trading212::ApiError) end def retryable?(err) err.status_code.to_i / 100 == 5 end
Try / catch
retries = 0 begin client.fetch_positions rescue Provider::Trading212::ApiError => e retry if (e.status_code.to_i / 100) == 5 && (retries += 1) < 3 && sleep(2**retries * 5) log_t212_failure(e.status_code, e.response_body) raise end
Prevention
- Branch on e.status_code - never blanket-retry ApiError
- Persist api environment (live/demo) with the key so they never drift apart
- Log response_body - Trading212 includes actionable reasons there
When it happens
Trigger: Calling /equity/account/summary, /equity/positions, /equity/history/* endpoints against the wrong environment (live key against demo.trading212.com returns 404/403-shaped failures that land here); Trading212 5xx outages; 404 for endpoints disabled on the account's API plan; malformed query params producing 400/422.
Common situations: Environment mismatch: api_key issued for the live account used with environment: "demo" or vice versa; Trading212 API version bump moving paths under /v0; equities API enabled but the specific history endpoint not enabled for the key; broker-side maintenance windows.
Related errors
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/d27c1b64007cc7ca.
Report an issue: GitHub.