{"record":{"id":"ce2ff1cc1cb4863d","repo":"we-promise/sure","slug":"access-forbidden-ce2ff1","errorCode":"access_forbidden","errorMessage":"Access forbidden - your Redbark plan may not include API access","messagePattern":"Access forbidden - your Redbark plan may not include API access","errorType":"exception","errorClass":"Provider::Redbark::AuthenticationError","httpStatus":403,"severity":"error","filePath":"app/models/provider/redbark.rb","lineNumber":242,"sourceCode":"        \"Authorization\" => \"Bearer #{@api_key}\",\n        \"Content-Type\" => \"application/json\",\n        \"Accept\" => \"application/json\"\n      }\n    end\n\n    # Redbark error envelope: { error: { message, code, details } }\n    # Error messages carry the parsed provider message only, never the raw\n    # response body - callers log and re-log these strings.\n    def handle_response(response)\n      case response.code\n      when 200, 201\n        JSON.parse(response.body, symbolize_names: true)\n      when 400\n        raise Error.new(\"Bad request: #{error_message_from(response)}\", :bad_request)\n      when 401\n        raise AuthenticationError.new(\"Invalid API key\", :unauthorized)\n      when 403\n        raise AuthenticationError.new(\"Access forbidden - your Redbark plan may not include API access\", :access_forbidden)\n      when 404\n        raise Error.new(\"Resource not found\", :not_found)\n      when 410\n        raise Error.new(\"Endpoint requires an accountId: #{error_message_from(response)}\", :bad_request)\n      when 429\n        raise RateLimitError.new(\"Rate limit exceeded\", :rate_limited)\n      when 500..599\n        raise ServerError.new(\"Redbark server error (#{response.code})\", :server_error)\n      else\n        raise Error.new(\"Unexpected response #{response.code}: #{error_message_from(response)}\", :unknown)\n      end\n    end\n\n    def error_message_from(response)\n      parsed = JSON.parse(response.body)\n      parsed.dig(\"error\", \"message\") || \"no error message provided\"\n    rescue JSON::ParserError\n      \"unparseable error response\"","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/redbark.rb#L224-L260","documentation":"Raised by Provider::Redbark's handle_response on HTTP 403 as AuthenticationError with error_type :access_forbidden. Distinct from 401: the key is recognized as valid, but the Redbark plan tied to it is not entitled to API access. Every endpoint will fail with this until the plan changes.","triggerScenarios":"Any authenticated Redbark call with a key whose subscription tier excludes API access — e.g. a free/UI-only plan key used against api.redbark.com.","commonSituations":"Trial expired and dropped to a non-API tier; API entitlement removed in a billing change; using a personal-tier key for a production integration.","solutions":["Upgrade the Redbark plan to one that includes API access","Verify in the Redbark dashboard that the key's account has API entitlement enabled","Contact Redbark support to confirm entitlement status if the dashboard looks correct","Until fixed, disable the Redbark sync job so it stops failing on every run"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def redbark_forbidden?(error)\n  error.is_a?(Provider::Redbark::AuthenticationError) && error.error_type == :access_forbidden\nend","tryCatchPattern":"begin\n  redbark.list_connections\nrescue Provider::Redbark::AuthenticationError => e\n  raise unless e.error_type == :access_forbidden\n  pause_redbark_sync!(reason: \"plan_not_entitled\") # every endpoint will fail until plan changes\nend","preventionTips":["Verify API entitlement in the Redbark dashboard before wiring up the integration","Distinguish 403 (entitlement) from 401 (bad key) in alerting — the fixes differ completely","Add a smoke-test call (list_connections) on first configuration to fail fast on plan problems"],"tags":["redbark","http-403","forbidden","plan-limits","entitlement"],"backgroundTag":"api-plan-access-forbidden","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}