we-promise/sure · error · EnableBankingError
access_forbidden
access_forbidden
Error message
Access forbidden - check your application permissions
What it means
Raised by Provider::EnableBanking#handle_response on HTTP 403: the JWT authenticated fine but the application is not permitted to use the endpoint or resource. Enable Banking gates endpoints by application permissions (and production access by licensing/onboarding state), so this is a portal-side configuration issue, not a code bug.
Source
Thrown at app/models/provider/enable_banking.rb:289
{
"Authorization" => "Bearer #{generate_jwt}",
"Accept" => "application/json"
}
end
def handle_response(response)
case response.code
when 200, 201
parse_response_body(response)
when 204
{}
when 400
response_data = parse_error_response_body(response)
raise EnableBankingError.new("Bad request to Enable Banking API: #{response.body}", :bad_request, response_data: response_data)
when 401
raise EnableBankingError.new("Invalid credentials or expired JWT", :unauthorized)
when 403
raise EnableBankingError.new("Access forbidden - check your application permissions", :access_forbidden)
when 404
raise EnableBankingError.new("Resource not found", :not_found)
when 408
raise EnableBankingError.new("Request timeout from Enable Banking API", :timeout)
when 422
response_data = parse_response_body(response)
raise EnableBankingError.new("Validation error from Enable Banking API: #{response.body}", :validation_error, response_data: response_data)
when 429
raise EnableBankingError.new("Rate limit exceeded. Please try again later.", :rate_limited)
else
response_data = parse_error_response_body(response)
raise EnableBankingError.new("Failed to fetch data: #{response.code} #{response.message} - #{response.body}", :fetch_failed, response_data: response_data)
end
end
def parse_error_response_body(response)
return {} if response.body.blank?
View on GitHub (pinned to e69894adb9)
Solutions
- Check the application's permissions and plan in the Enable Banking portal and request access for the endpoint family you're calling
- Confirm the application has been activated for production if you're calling live endpoints
- If the 403 is bank-specific, check whether that ASPSP requires PSU headers (pass psu_headers: on get_account_details/balances/transactions)
- Contact Enable Banking support with the application_id when permissions look correct but the error persists
Example fix
# before
client.get_account_transactions(account_id: uid) # some ASPSPs require PSU context
# after
client.get_account_transactions(
account_id: uid,
psu_headers: { "PSU-IP-Address" => user.last_ip, "PSU-User-Agent" => request.user_agent }
) Defensive patterns
Strategy: validation
Type guard
def eb_forbidden?(error) error.is_a?(Provider::EnableBanking::EnableBankingError) && error.error_type == :access_forbidden end
Try / catch
begin
client.get_account_transactions(account_id: uid)
rescue Provider::EnableBanking::EnableBankingError => e
raise unless e.error_type == :access_forbidden
Rails.logger.warn("EB 403 for #{uid}: application permissions or PSU headers required")
next # skip and surface to ops; retrying will not change the grant
end Prevention
- Complete production onboarding/licensing before pointing at live endpoints
- Pass psu_headers (PSU-IP-Address, PSU-User-Agent) for ASPSPs that require PSU context — safe_psu_headers strips only dangerous keys
- Track per-bank 403 rates to spot banks needing extra headers or permissions
- Escalate to Enable Banking support with application_id when permissions look correct
When it happens
Trigger: A sandbox-only application calling production endpoints (BASE_URL is hardcoded to api.enablebanking.com); the application's plan doesn't include an endpoint family; PSU-context requirements (e.g. some ASPSPs require PSU headers/IP) rejecting the request as forbidden.
Common situations: Moving from sandbox testing to production without completing Enable Banking onboarding, new endpoints enabled in the docs but not on the application, regional/licensing restrictions.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/0b69234dd9984454.
Report an issue: GitHub.