v1.7.0
OpenAPI 3.1.0
Roster Partner API
The Roster Partner API lets a platform partner import its churches, open hosted donor sessions, read enrollment status, and reconcile through an event feed plus signed outbound webhooks.
Conventions (apply to every endpoint)
-
Authentication — every
/v1/*and/sandbox/*request needsAuthorization: Bearer sk_test_...(sandbox) orBearer sk_live_...(production). Test keys only exist on the sandbox stack. A malformed, unknown, or wrong-mode key always gets the same opaque401. -
Idempotency — the
Idempotency-Keyheader (1–255 visible ASCII characters, no spaces) is required on every POST. Keep the key stable when retrying the same action with the same body: a repeated creation returns the original resource (200) and changes nothing. A key belongs to the first body sent with it, from the moment that request arrives: the same key with a different body on the same operation gets409idempotency-key-reusedfor 30 days, and nothing runs — use a new key for a new request. This holds while the first request is still running and after it ends in a5xxor a timeout: repeat it with the same body and the same key to complete it. A request refused with400(or any other4xx) does not hold the key: fix the body and repeat it with the same key — unless an earlier attempt with that key already ended in a5xxor a timeout; then the key stays with that body, and the corrected request needs a new key. On an operation that creates a resource (POST /v1/churches,POST /v1/churches/import,POST /v1/church_consents,POST /v1/donor_sessions,POST /v1/manage_sessions,POST /v1/refundsandPOST /v1/webhook_endpoints), a key whose request succeeded also keeps its body for as long as the resource it created exists: a different body gets409even after the 30 days, and the same body still returns the original resource. On the other operations, the key is held for the 30 days only. Webhook tests run again on every call with the same body, and so do sandbox simulators while what they check still holds, except the simulated deposit, which does not credit twice. Once a first call changed it, a repeat answers400naming what it found: a payroll simulator, the state the enrollment reached; the identity simulator, the donor's final outcome; the account-closure simulator, the closed account; the late-return simulator, the leg already returned; the refund simulator, the refund's status. The per-operation table is in the reliability guide. -
Errors — RFC 7807
application/problem+json:{type, title, detail, request_id}. Every response the API sends to an authenticated call, success included, also carries the same reference in theX-Request-Idheader. Include it when contacting support. The gateway in front of the API answers four cases on its own, withoutX-Request-Id,Roster-Api-Version,RateLimit-*or a problem body: its throttle shared by every partner (429,{"message":"Too Many Requests"}), a call the API did not answer in time (500or503), a path it cannot parse, such as one containing%zz(400with an HTML body), and a browser preflight (OPTIONS,403with an empty body: call the API from your backend). See API errors. -
Request bodies — JSON sent with
Content-Type: application/json, up to 1 MiB. A body in another format, over the limit, or that is not valid JSON gets400bad-request, with the reason indetail. An empty body counts as no body. -
Rate limiting — a per-partner quota (600 requests per minute, fixed
window, shared by all your keys) on top of the gateway's global throttle.
Every response the API sends to an authenticated call carries
RateLimit-Limit,RateLimit-RemainingandRateLimit-Reset(seconds until the window resets); past the quota, expect429withRetry-Afterand no side effect. A429from the gateway's throttle carries none of these headers (see Errors above). -
Pagination — cursor-based: the event feeds take
since_cursor, the church and enrollment lists takecursor, and each returnsnext_cursor. Cursors are opaque; never construct one. - Reading what Roster sends — responses, webhook deliveries and event payloads can gain fields, enum values and event types at any time: that is an additive change, listed in the changelog. Ignore fields you do not recognize, treat an enum value you do not recognize as "something changed; read the resource again", and skip event types you do not handle. The response and event schemas here are open to new fields on purpose, and an enum lists the values sent today: if you generate a validator or a typed client, keep it accepting what it does not know.
-
Versioning — the contract follows semantic versioning:
info.versionabove isMAJOR.MINOR.PATCH, and every response the API sends carries it in theRoster-Api-Versionheader. A breaking change ships only in a new major, under a new path prefix (/v1is major 1); a minor only adds; a patch fixes documentation or behavior without changing the contract. A published version never changes. The newest generally available major is the Default; when a new major replaces it, the previous one becomes LTS for 12 months, with security and critical fixes only. See the changelog. - Donor data — financial events include authorized donor name, contact and mailing address for partner reporting and existing ChMS integrations. Activity events and enrollments retain their narrower allowlists. Raw payroll data and donor bank credentials are not part of this contract.
Certification flow (sandbox, self-service)
GET /sandbox/fixtures returns every test value used below. The full
script, with the other scenarios, is in the
certification guide.
-
Register a webhook endpoint (
POST /v1/webhook_endpoints), store itssecret, and prove your receiver withPOST /v1/webhook_endpoints/{id}/test. -
Register the sites where your pages open the hosted flow
(
PUT /v1/allowed_origins): only a registered site can show the flow inside its pages. -
Create or import a church (
POST /v1/churchesorPOST /v1/churches/import). Do not send a test EIN there. -
Verify the church. Send its legal details with a test EIN from
00-0000001to00-0000093and an incorporation date at least six months ago (POST /v1/churches/{id}/verification), and its receiving account with routing number021000021and an account number that does not end in00,11or22(POST /v1/churches/{id}/bank-account). ReadGET /v1/churches/{id}untilpayout_readyistrue: donors cannot start paycheck giving at a church Roster has not verified. -
Open a donor session (
POST /v1/donor_sessions) and complete the hosted flow on a registered site as a test donor: any number from+1 202-555-0100to+1 202-555-0189, any adult date of birth, code000000. Numbers0190to0199keep the identity check in review, and step 6 refuses them. You receiveenrollment.created. -
Connect the payroll in the hosted flow, through the payroll
provider's window in its test mode, or, from a script that does not
drive that window, simulate the payroll connection
(
POST /sandbox/simulate/payroll-connected). Receiveenrollment.activatedon your webhook endpoint. - Cross-check the same event on the pull feed (
GET /v1/events).
Client Libraries