Reference

Errors

All API errors return a JSON body with a standard shape so you can match on a machine-readable code instead of parsing strings.

Error response shape

{
  "error": {
    "code": "invalid_or_revoked_key",
    "message": "This API key is not recognized or has been revoked."
  }
}

HTTP status codes

HTTPcodeMeaning
400invalid_jsonRequest body wasn't valid JSON.
400invalid_bodyBody parsed but the top-level shape is wrong (e.g., missing accounts array).
400batch_too_largeMore than 1,000 accounts/contacts in one request.
400invalid_urlWebhook URL is not HTTPS, points to localhost, or otherwise rejected.
400missing_paramRequired query param missing (e.g., external_id on DELETE).
401missing_authorizationNo Authorization header was sent.
401invalid_key_formatToken doesn't start with fs_live_.
401invalid_or_revoked_keyKey isn't in our DB, or was revoked at Settings → API Keys.
403pro_requiredAccount is not on Pro. API access requires Pro tier — upgrade in Settings.
429quota_exceededPer-tool daily quota hit. Retry after UTC midnight or contact us to raise limits.
500db_errorOur problem — we'll see it in logs. Safe to retry.
500auth_lookup_failed / profile_lookup_failedTransient DB issue during auth. Safe to retry.

Partial success: row-level errors

Batch endpoints (POST /accounts, POST /contacts) accept up to 1,000 rows. If some rows have validation issues, the valid rows are still upserted and the invalid rows come back in the response body:

{
  "upserted": 998,
  "errors": [
    { "index": 14, "error": "external_id is required and must be a non-empty string" },
    { "index": 287, "error": "metadata must be a JSON object" }
  ]
}

HTTP status is still 200 in this case. Always check the errors array length, not just the status. Status 400 is only returned if every row failed validation.

Retry guidance

  • 4xx errors: don't retry. They're bugs in your request — fix the request and resend.
  • 429 quota_exceeded: back off until UTC midnight, or email api@fundingscout.io to discuss higher limits.
  • 5xx errors: retry with exponential backoff (1s, 3s, 9s, 27s). Most transient. If you see persistent 5xx, ping us.

Webhook delivery failures (not API errors)

Separate from API errors: when FundingScout POSTs to your webhook and your endpoint returns non-2xx (or times out after 5s), we mark the match as webhook_status = "failed". These show up in:

curl "https://fundingscout.io/api/v1/matches?status=failed" \
  -H "Authorization: Bearer $FS_KEY"

The response includes webhook_response_code and a short snippet of the response body to help you debug your webhook.