Bad Request (400)
The request was understood but rejected before any effect. The detail field
names the first problem found. It can quote a value you sent (a site in
origins, for example), so log it as you would log the request.
Common causes
- Missing
Idempotency-Keyheader on a POST (required on every POST). -
A required field missing or with the wrong type (
name,church_id,mode,value,url,event_types). -
An optional field in the wrong format, such as a
donor_phonethat is not E.164 (+15551230000). -
A
valueoutside its range. Withmode: "pct", a whole percentage from 1 to 35 (12, never12.5); withmode: "fixed", dollars from 1 to 20,000 in whole cents (12.50, never12.345). event_typescontaining a type that is not subscribable.-
A
typeonGET /v1/eventsthat is not an activity event type: a typo, a financial type such asdonation.updated(read it fromGET /v1/financial_events), ortypesent more than once.detaillists the accepted values. -
An invalid
since_cursoron the events feed — cursors are opaque; always pass back exactly whatnext_cursorgave you. A cursor also works only with the sametypefilter it was issued with. -
A query parameter the operation does not accept, such as
cursoron/v1/events(the feeds page withsince_cursor).detaillists the ones it accepts. -
A sandbox test EIN (
00-0000001to00-0000099) sent when creating a church — test EINs go in the verification request. InPOST /v1/churches/importthe batch still answers200: that row comes backrejectedwith the samedetail, and the other rows are imported. - A sandbox simulator whose prerequisite is not met —
detailsays which one.
A body the API cannot read is also a 400 with this type, never a 413
or a 415. The detail says what to fix:
detail |
Cause |
|---|---|
request body is not valid JSON |
The body does not parse as JSON |
send the request body as JSON, with Content-Type: application/json |
A body sent without Content-Type: application/json, such as text/plain |
request body is over the 1 MiB limit |
The body is larger than 1 MiB |
request body uses a reserved JSON key name; remove that key and send the request again |
Valid JSON with a reserved key name, such as __proto__ |
Content-Length does not match the request body |
The Content-Length header disagrees with the body |
request rejected |
Any other body the API refuses before reading it |
An empty body with Content-Type: application/json counts as no body, so
operations without a body, such as DELETE /v1/webhook_endpoints/{id}, accept
it.
A path the gateway in front of the API cannot parse, such as one containing
%zz, gets 400 with an HTML body instead of this page's problem body, and
without X-Request-Id: it never reached the API. Fix how you build the URL
(percent-encode ids before placing them in a path); see API errors.
What to do: fix the field named in detail and retry with the same
Idempotency-Key — a request refused with 400 does not hold the key. If an
earlier attempt with that key ended in a 5xx or a timeout, the key stays with
that first body: send the corrected request with a new key.