Skip to main content
The Grain API supports two authentication methods:
  • Organization API keys for server automation owned by one church. This is the fastest way to test the production API.
  • OAuth 2.1 (Sign in with Grain) for applications that act on behalf of individual users, including Grain-managed OAuth apps that can connect many churches.
MCP access requires Growth or Scale. Organization API keys and unmanaged OAuth sessions require an active Scale plan for the church you are accessing. Grain-managed OAuth apps with an active grant may call /api/v1 on Starter and Growth; Draft apps are limited to their publisher organization.
Store API keys, access tokens, and refresh tokens in a secrets manager. Never expose credentials in client-side code, logs, or public repositories.

Organization API keys

An Owner, Admin, or custom role with Manage API access can create a key in Settings → API. Give the key a descriptive name, choose the smallest required scope set, and select an expiry. The secret is displayed only once. Production organizations receive keys beginning with grain_live_. Sandbox, demo, and test organizations receive grain_test_ keys.
The key determines its organization, so X-Organization-Id is optional. If you include the header, it must match the key’s organization. API keys work only under /api/v1; they cannot sign in to the Grain app, call tRPC or MCP, or authenticate directly with the identity provider.

API key scopes

Write access includes the corresponding read access. Donor and household scopes can expose personal information. Contribution and pledge responses include donor IDs but never embed donor identity; use a donor read scope to retrieve the related donor separately.

Rotation and revocation

Rotating a key displays a new secret once. The previous secret remains valid for up to 24 hours, or until its original expiry if sooner, so you can update automation without downtime. You can revoke the previous secret immediately after deployment. Full revocation permanently disables both secrets; the named key stays visible for audit history. Grain-managed OAuth client secrets are different: rotating a confidential app secret replaces it immediately. The previous secret stops working as soon as rotation succeeds.

OAuth 2.1 flow

1

Redirect to authorize

Send the user to https://auth.grainledger.com/auth/v1/oauth/authorize with your client ID, redirect URI, scopes, and PKCE parameters (code_challenge and code_challenge_method=S256).
2

User consents

The user signs in (if needed) and approves access at https://app.grainledger.com/oauth/consent.
3

Receive authorization code

Grain redirects back to your redirect_uri with an authorization code and state parameter.
4

Exchange for tokens

POST the code to https://auth.grainledger.com/auth/v1/oauth/token with your code_verifier to receive access and refresh tokens. Confidential clients also authenticate with HTTP Basic using their client ID and secret.
5

Call the API

Include Authorization: Bearer <access_token> and X-Organization-Id on resource requests. Grain-managed apps may first call GET /api/v1/organizations without that header to discover churches the user authorized for this client.

Grain-managed OAuth apps

Publisher organizations register apps in Settings → API → Apps. Connecting churches complete org and Grain-scope consent at https://app.grainledger.com/oauth/consent. Effective permission is the intersection of the app’s maximum scopes, the user’s consented scopes, and the user’s current role. Use PKCE S256 for both public and confidential clients. A Draft app can connect only its publisher organization, which supports localhost integration testing before publication. Grain checks app status, the installation, and the grant on every /api/v1 request. Disabling the app or revoking a grant takes effect on the next API call. If the user has SMS two-factor authentication enrolled, Grain requires a fresh challenge while the connection is authorized. OAuth access tokens returned by both the code exchange and refresh remain truthfully marked aal1; Grain records the separate, server-verified MFA result on the managed app grant. Integrators should not reject an otherwise valid token solely because its aal is aal1. If Grain returns Reconnect this application and complete two-factor authentication., start a new authorization-code flow so the user can complete the fresh challenge. Grain also requires reconnection if the verified phone factor used to authorize the grant is later removed. Rate limits are 100 requests per minute per target organization and 100 requests per minute per application.

OAuth endpoints

MCP (AI agents)

Grain exposes a read-only MCP server at https://api.grainledger.com/mcp for ChatGPT and other MCP clients. MCP uses the same OAuth identity and organization permissions; org scoping is via organizationId in tool arguments instead of X-Organization-Id. See MCP. MCP is read-only because it exposes only read tools. OAuth tokens still identify the signed-in user, and Grain checks organization permissions on each tool call.

Authorization request example

Generate code_challenge as the Base64URL-encoded SHA-256 hash of a random code_verifier string. Keep the verifier secret until the token exchange.
The authorization server’s scope parameter accepts standard OIDC scopes such as openid email profile. Do not send Grain resource scopes such as donors:read there. Grain resource scopes come from the app registration and the user’s Grain consent selection.

Token exchange

X-Organization-Id header with OAuth

Every OAuth API request must include the organization (church) whose data you are accessing:
Users can belong to multiple organizations. Unmanaged OAuth does not scope to a single org; your application specifies the org per request. Grain-managed apps can list authorized organizations first. See Organizations for how to obtain the ID.

OAuth scopes

Standard OIDC scopes control user profile data in tokens: API access for unmanaged OAuth follows the signed-in user’s role. Grain-managed apps also intersect that role with the app’s maximum scopes and the scopes the user consented to.

Rate limits

/api/v1 allows 100 requests per minute per target organization. Grain-managed OAuth apps have a second budget of 100 requests per minute per application so one client cannot fan out across installations.

Diagnose API errors

Every Grain API response includes a server-generated X-Request-Id header. Save it with your integration logs and include it in support requests. The same ID links authenticated API activity to any resulting audit records. Schema validation failures return safe field names and machine-readable validation codes:
details.fields contains up to 20 issues. A field reported as request refers to an unlisted or nested field. Submitted values are omitted. Authenticated scope denials and rate-limit responses are recorded in API activity; rejections before authentication are recorded in server diagnostics without trusting a supplied organization ID. Organization discovery is not included in per-organization activity. For contribution retry behavior, see Retry contribution creates safely.

Example API request

Token refresh

Use the refresh token from the token exchange to obtain new access tokens when they expire:
Refresh tokens before they expire to avoid interrupting active integrations.
Last modified on September 15, 2026