> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.givechariot.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.givechariot.com/_mcp/server.

# Grant Request Lifecycle

When a donor submits a grant via DAFpay, a Grant Request is created and tied to their Donor Account. Its status advances based on the state of the Donor Account and your actions as a DAF.

## Statuses

| Status                      | Meaning                                                                        | Your action                                                                          |
| --------------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
| `awaiting_account_decision` | The parent Donor Account isn't `approved` yet.                                 | Advances automatically when the Donor Account is approved. You may reject if needed. |
| `pending`                   | The Donor Account is approved and the Grant Request is awaiting your decision. | Submit it in your system, then call Submit. Or call Reject if you can't process it.  |
| `submitted`                 | You've submitted the grant. **Final.**                                         | None.                                                                                |
| `rejected`                  | You've rejected the grant. **Final.**                                          | None.                                                                                |

> **Note**
>
> A Grant Request in `awaiting_account_decision` cannot be submitted until its linked Donor Account reaches `approved` status. If the Donor Account is rejected, all open Grant Requests tied to it are automatically moved to `rejected`.

## Submitting a Grant Request

Once a Grant Request is in `pending`, submit it in your internal system and then call [Submit Grant Request](/api/grant-requests/submit) to mark it as `submitted`. Optionally pass `external_grant_id` to link it to your internal grants ledger.

**`cURL`**

```bash cURL
curl -X POST https://api.givechariot.com/v1/grant_requests/grant_req_01jpjenf5q6cawy43yxfcrxhct/submit \
  -H "Authorization: Bearer $CHARIOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "external_grant_id": "ACME-GRANT-2026-00481",
    "comment": "Submitted per donor schedule"
  }'
```

**`TypeScript`**

```typescript TypeScript
await chariot.grantRequests.submit("grant_req_01jpjenf5q6cawy43yxfcrxhct", {
  external_grant_id: "ACME-GRANT-2026-00481",
  comment: "Submitted per donor schedule",
});
```

The Grant Request moves to `submitted` and a `grant_request.updated` webhook is emitted — fetch the Grant Request to confirm its current status.

## Rejecting a Grant Request

If you cannot process a Grant Request, call [Reject Grant Request](/api/grant-requests/reject). The `reason` is stored for auditing and is not shown to the donor.

**`cURL`**

```bash cURL
curl -X POST https://api.givechariot.com/v1/grant_requests/grant_req_01jpjenf5q6cawy43yxfcrxhct/reject \
  -H "Authorization: Bearer $CHARIOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Grant amount exceeds donor available balance."
  }'
```

**`TypeScript`**

```typescript TypeScript
await chariot.grantRequests.reject("grant_req_01jpjenf5q6cawy43yxfcrxhct", {
  reason: "Grant amount exceeds donor available balance.",
});
```

The Grant Request moves to `rejected` and a `grant_request.updated` webhook is emitted — fetch the Grant Request to confirm its current status. The Donor Account is unaffected — future Grant Requests from the same donor can still be processed.

## Bulk processing

Use [List Grant Requests](/api/grant-requests/list) filtered by `status=pending` and iterate. There is no bulk endpoint — each action is independent.

**`TypeScript`**

```typescript TypeScript
let pageToken: string | undefined;
do {
  const page = await chariot.grantRequests.list({ pageToken, pageLimit: 100 });
  for (const grantRequest of page.results) {
    if (grantRequest.status !== "pending") continue;
    if (await passesInternalChecks(grantRequest)) {
      await chariot.grantRequests.submit(grantRequest.id, {
        external_grant_id: await ledger.recordGrant(grantRequest),
      });
    } else {
      await chariot.grantRequests.reject(grantRequest.id, {
        reason: "Failed automated balance check",
      });
    }
  }
  pageToken = page.next_page_token ?? undefined;
} while (pageToken);
```

## Idempotency

`submitted` and `rejected` are terminal. Calling submit or reject on an already-decided Grant Request returns `409 Conflict`. To safely retry on network errors, call [Get Grant Request](/api/grant-requests/get) first and check `status` before retrying.