Skip to main content
The Grain API uses standard HTTP status codes. Error responses include a JSON body with a message field describing what went wrong.

Error response format

{
  "message": "You do not have access to this organization."
}
Some validation errors may include additional fields depending on the endpoint.

Common status codes

StatusMeaningTypical cause
400Bad requestMissing X-Organization-Id header or invalid request body
401UnauthorizedMissing or expired Bearer token
403ForbiddenUser lacks permission for the action or organization
404Not foundResource ID does not exist in the organization
409ConflictDuplicate record (for example donor with same name and email)
422Unprocessable entityValidation failed on one or more fields
429Too many requestsRate limit exceeded
500Server errorUnexpected error; retry with backoff

Authentication errors

{
  "message": "Authentication required. Provide a valid Bearer token."
}
Refresh your access token or re-run the OAuth flow.
{
  "message": "X-Organization-Id header is required for all API requests."
}
Add the header on every request. See Organizations.
{
  "message": "You do not have access to this organization."
}
The authenticated user is not a member of the organization in X-Organization-Id.

Handling errors in your integration

Log the status code and message field for debugging. Do not log full Bearer tokens.
const response = await fetch(url, { headers });

if (!response.ok) {
  const error = await response.json().catch(() => ({}));
  throw new Error(`Grain API ${response.status}: ${error.message ?? response.statusText}`);
}
response = requests.get(url, headers=headers)

if not response.ok:
    error = response.json() if response.content else {}
    raise RuntimeError(
        f"Grain API {response.status_code}: {error.get('message', response.reason)}"
    )

Rate limiting

When you exceed the per-organization rate limit, the API returns 429 with rate limit headers. Wait until X-RateLimit-Reset before retrying. See Introduction for default limits.
Last modified on July 8, 2026