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
| HTTP | code | Meaning |
|---|---|---|
| 400 | invalid_json | Request body wasn't valid JSON. |
| 400 | invalid_body | Body parsed but the top-level shape is wrong (e.g., missing accounts array). |
| 400 | batch_too_large | More than 1,000 accounts/contacts in one request. |
| 400 | invalid_url | Webhook URL is not HTTPS, points to localhost, or otherwise rejected. |
| 400 | missing_param | Required query param missing (e.g., external_id on DELETE). |
| 401 | missing_authorization | No Authorization header was sent. |
| 401 | invalid_key_format | Token doesn't start with fs_live_. |
| 401 | invalid_or_revoked_key | Key isn't in our DB, or was revoked at Settings → API Keys. |
| 403 | pro_required | Account is not on Pro. API access requires Pro tier — upgrade in Settings. |
| 429 | quota_exceeded | Per-tool daily quota hit. Retry after UTC midnight or contact us to raise limits. |
| 500 | db_error | Our problem — we'll see it in logs. Safe to retry. |
| 500 | auth_lookup_failed / profile_lookup_failed | Transient 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.