Chariot Donor Accounts API

The Donor Accounts API from Chariot — 4 operation(s) for donor accounts.

OpenAPI Specification

chariot-donor-accounts-api-openapi.yml Raw ↑
openapi: 3.0.0
info:
  title: Chariot FDX Accounts Donor Accounts API
  version: '6.0'
  description: Financial Data Exchange (FDX) v6 compatible API for read-only access to Chariot bank account data. Implements the FDX v6 standard for account information, transactions, and statements.
  contact:
    name: Chariot Development Team
    url: https://givechariot.com/contact
    email: developers@givechariot.com
servers:
- url: https://api.givechariot.com/fdx/v6
  description: Production
- url: https://devapi.givechariot.com/fdx/v6
  description: Staging
security:
- oauth2: []
tags:
- name: Donor Accounts
paths:
  /v1/donor_accounts:
    post:
      summary: Create Donor Account
      description: 'Create a new Donor Account.


        This endpoint is intended for DAF providers who want to set up a Donor Account on behalf of a donor before that donor uses DAFpay for the first time.

        See the [DAF-Initiated Setup guide](/guides/dafpay/donor-accounts/daf-initiated-setup) for the most common use of this endpoint.


        On creation, the Donor Account is placed in `pending` status. To make the account immediately usable for grant submissions, follow up with [Create Authorization Token](/api/donor-accounts/create-authorization-token) and provide the resulting code to the donor — when the donor enters the code in DAFpay, the Donor Account is automatically approved.'
      operationId: create-donor-account
      tags:
      - Donor Accounts
      security:
      - bearerAuth: []
      requestBody:
        $ref: '#/components/requestBodies/CreateDonorAccountRequest'
      responses:
        '201':
          description: Created
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
            Location:
              description: The URI reference of the created donor account.
              schema:
                type: string
                format: uri
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DonorAccount'
              examples:
                Simple:
                  $ref: '#/components/examples/DonorAccountOutput'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '409':
          $ref: '#/components/responses/ConflictError'
        '500':
          $ref: '#/components/responses/InternalServerError'
    get:
      summary: List Donor Accounts
      description: 'Returns a list of Donor Accounts for the authenticated DAF.

        This endpoint supports cursor-based pagination as well as filtering by fund, status, and email.'
      operationId: list-donor-accounts
      tags:
      - Donor Accounts
      security:
      - bearerAuth: []
      parameters:
      - name: giving_pool_id
        in: query
        description: The `id` of a [Giving Pool](/api/giving-pools). When set, filters Donor Accounts to those that have this Giving Pool associated with them.
        schema:
          type: string
        required: false
        example: 0bf40881-8ee2-47fb-98ca-f58c7999aa34
      - name: status
        in: query
        description: Filter Donor Accounts to only those with the specified status.
        schema:
          $ref: '#/components/schemas/DonorAccountStatus'
        required: false
      - name: email
        in: query
        description: Filter Donor Accounts by donor email. The match is case insensitive and exact.
        schema:
          type: string
        required: false
        example: warrenBuffet@example.com
      - name: external_id
        in: query
        description: Filter Donor Accounts by `external_id` — the DAF's internal identifier for the Donor Account.
        schema:
          type: string
        required: false
      - name: page_limit
        in: query
        description: the number of results to return; defaults to 10, max is 100
        schema:
          type: integer
          default: 10
      - name: page_token
        in: query
        description: A token to use to retrieve the next page of results. This is useful for paginating over many pages of results. If set, all other arguments are expected to be kept the same as previous calls and the value of this field should be from the next_page_token in the previous response.
        schema:
          type: string
      responses:
        '200':
          $ref: '#/components/responses/ListDonorAccountsResponse'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v1/donor_accounts/{id}:
    get:
      summary: Get Donor Account
      description: Retrieve a Donor Account with the given ID.
      operationId: get-donor-account
      tags:
      - Donor Accounts
      security:
      - bearerAuth: []
      parameters:
      - name: id
        in: path
        description: The unique id of the Donor Account.
        schema:
          type: string
        required: true
        example: donor_account_01jpjenf5q6cawy43yxfcrxhct
      responses:
        '200':
          description: OK
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DonorAccount'
              examples:
                Simple:
                  $ref: '#/components/examples/DonorAccountOutput'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '500':
          $ref: '#/components/responses/InternalServerError'
    patch:
      summary: Update Donor Account
      description: 'Update mutable properties on a Donor Account such as `external_id`, the nested `donor` fields, and `metadata`.


        The Donor Account''s status is managed automatically through the Authorization Token verification flow and cannot be changed directly via this endpoint.'
      operationId: update-donor-account
      tags:
      - Donor Accounts
      security:
      - bearerAuth: []
      parameters:
      - name: id
        in: path
        description: The unique id of the Donor Account
        schema:
          type: string
        required: true
        example: donor_account_01jpjenf5q6cawy43yxfcrxhct
      requestBody:
        $ref: '#/components/requestBodies/UpdateDonorAccountRequest'
      responses:
        '200':
          description: OK
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DonorAccount'
              examples:
                Simple:
                  $ref: '#/components/examples/DonorAccountOutput'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v1/donor_accounts/{id}/disable:
    post:
      summary: Disable Donor Account
      description: 'Disable an approved Donor Account.


        A disabled Donor Account remains `approved` but cannot submit new Grant Requests. Existing Grant Requests already in flight are unaffected — disabling does not retroactively cancel or reject prior activity. Use this when a DAF needs to temporarily prevent a donor from initiating new grants (e.g. account under review, donor offboarding) without rejecting the underlying identity verification.


        This endpoint is idempotent — calling it on an already-disabled account returns the Donor Account unchanged.


        <Warning>

        - The Donor Account must be in `approved` status. Calls on a `pending` or `rejected` account return status `409 Conflict`.

        </Warning>'
      operationId: disable-donor-account
      tags:
      - Donor Accounts
      security:
      - bearerAuth: []
      parameters:
      - name: id
        in: path
        description: The unique id of the Donor Account.
        schema:
          type: string
        required: true
        example: donor_account_01jpjenf5q6cawy43yxfcrxhct
      responses:
        '200':
          description: The Donor Account was disabled (or was already disabled).
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DonorAccount'
              examples:
                Disabled:
                  $ref: '#/components/examples/DonorAccountDisabledOutput'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '409':
          $ref: '#/components/responses/ConflictError'
        '500':
          $ref: '#/components/responses/InternalServerError'
  /v1/donor_accounts/{id}/enable:
    post:
      summary: Enable Donor Account
      description: 'Re-enable a previously disabled Donor Account. After this call, the Donor Account can submit new Grant Requests again.


        This endpoint is idempotent — calling it on an account that is already enabled returns the Donor Account unchanged.


        <Warning>

        - The Donor Account must be in `approved` status. Calls on a `pending` or `rejected` account return status `409 Conflict`.

        </Warning>'
      operationId: enable-donor-account
      tags:
      - Donor Accounts
      security:
      - bearerAuth: []
      parameters:
      - name: id
        in: path
        description: The unique id of the Donor Account.
        schema:
          type: string
        required: true
        example: donor_account_01jpjenf5q6cawy43yxfcrxhct
      responses:
        '200':
          description: The Donor Account was enabled (or was already enabled).
          headers:
            X-Request-Id:
              $ref: '#/components/headers/X-Request-Id'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DonorAccount'
              examples:
                Enabled:
                  $ref: '#/components/examples/DonorAccountEnabledOutput'
        '400':
          $ref: '#/components/responses/BadRequestError'
        '401':
          $ref: '#/components/responses/AuthenticationError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '409':
          $ref: '#/components/responses/ConflictError'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  examples:
    DonorAccountOutput:
      summary: Pending donor account
      value:
        id: donor_account_01jpjenf5q6cawy43yxfcrxhct
        status: pending
        donor:
          email: warrenBuffet@example.com
          first_name: null
          last_name: null
          phone: null
        external_id: ACME-DAF-DONOR-1042
        approval: null
        rejection: null
        disabled: false
        created_at: '2026-04-01T12:00:00Z'
        updated_at: '2026-04-01T12:00:00Z'
    DonorAccountEnabledOutput:
      summary: Previously-disabled donor account that has been re-enabled
      value:
        id: donor_account_01jpjenf5q6cawy43yxfcrxhct
        status: approved
        donor:
          email: warrenBuffet@example.com
          first_name: Warren
          last_name: Buffet
          phone: '+12125550100'
        external_id: ACME-DAF-DONOR-1042
        approval:
          approved_at: '2026-04-02T18:30:00Z'
          approved_by: daf:fid_01jpjenf5q6cawy43yxfcrxhct
        rejection: null
        disabled: false
        created_at: '2026-04-01T12:00:00Z'
        updated_at: '2026-04-06T11:00:00Z'
    DonorAccountDisabledOutput:
      summary: Approved donor account that has been disabled
      value:
        id: donor_account_01jpjenf5q6cawy43yxfcrxhct
        status: approved
        donor:
          email: warrenBuffet@example.com
          first_name: Warren
          last_name: Buffet
          phone: '+12125550100'
        external_id: ACME-DAF-DONOR-1042
        approval:
          approved_at: '2026-04-02T18:30:00Z'
          approved_by: daf:fid_01jpjenf5q6cawy43yxfcrxhct
        rejection: null
        disabled: true
        created_at: '2026-04-01T12:00:00Z'
        updated_at: '2026-04-05T09:00:00Z'
  responses:
    AuthenticationError:
      description: Unauthorized. The request is missing the security (OAuth2 Bearer token) requirements and the server is unable to verify the identify of the caller.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            Unauthorized:
              value:
                type: about:blank
                title: API Error
                status: 401
                detail: Authentication credentials were missing or invalid.
    ListDonorAccountsResponse:
      description: The response for DonorAccounts.list
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/json:
          schema:
            type: object
            properties:
              results:
                type: array
                items:
                  $ref: '#/components/schemas/DonorAccount'
              next_page_token:
                type: string
                nullable: true
                description: A cursor token to use to retrieve the next page of results by making another API call to the same endpoint with the same parameters (only changing the page_token). If specified, then more results exist on the server that were not returned, otherwise no more results exist on the server.
          example:
            results:
            - id: donor_account_01jpjenf5q6cawy43yxfcrxhct
              status: approved
              donor:
                email: warrenBuffet@example.com
                first_name: Warren
                last_name: Buffet
                phone: '+12125550100'
              external_id: ACME-DAF-DONOR-1042
              approval:
                approved_at: '2026-04-02T18:30:00Z'
                approved_by: daf:fid_01jpjenf5q6cawy43yxfcrxhct
              rejection: null
              disabled: false
              created_at: '2026-04-01T12:00:00Z'
              updated_at: '2026-04-02T18:30:00Z'
            next_page_token: c3f685f2-2dda-4956-815b-39867a5e5638
    BadRequestError:
      description: The request is invalid or contains invalid parameters
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            BadRequest:
              value:
                type: about:blank
                title: API Error
                status: 400
                detail: The request is invalid or contains invalid parameters.
    InternalServerError:
      description: Internal Server Error
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            InternalServerError:
              value:
                type: about:blank
                title: API Error
                status: 500
                detail: The server encountered an error processing your request.
    ConflictError:
      description: Resource Conflicts
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            Conflict:
              value:
                type: about:blank
                title: API Error
                status: 409
                detail: The request conflicts with the current state of the resource.
    ForbiddenError:
      description: Access denied
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            Forbidden:
              value:
                type: about:blank
                title: API Error
                status: 403
                detail: You do not have permission to access this resource.
    NotFoundError:
      description: Resource Not Found
      headers:
        X-Request-Id:
          $ref: '#/components/headers/X-Request-Id'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetails'
          examples:
            NotFound:
              value:
                type: about:blank
                title: API Error
                status: 404
                detail: The requested resource was not found.
  requestBodies:
    UpdateDonorAccountRequest:
      description: 'The request to update mutable properties on a Donor Account.

        Note that the Donor Account''s status is managed automatically through the Authorization Token verification flow and cannot be changed directly via this endpoint.'
      required: true
      content:
        application/json:
          schema:
            type: object
            properties:
              donor:
                type: object
                description: Mutable donor identity fields. Only the fields you pass are updated; omitted fields are left unchanged.
                properties:
                  first_name:
                    type: string
                    description: The donor's first name.
                    example: Warren
                  last_name:
                    type: string
                    description: The donor's last name.
                    example: Buffet
                  phone:
                    type: string
                    description: The donor's phone number.
                    example: '+12125550100'
              external_id:
                type: string
                description: 'The DAF''s internal identifier for this Donor Account. Maximum length: 255 characters.'
                example: ACME-DAF-DONOR-1042
              metadata:
                type: object
                description: A map of arbitrary string keys and values to store information about the object.
                additionalProperties:
                  type: string
    CreateDonorAccountRequest:
      description: 'The request to create a new Donor Account.

        Used by DAFs to pre-establish access for a donor before that donor authenticates through DAFpay.'
      required: true
      content:
        application/json:
          schema:
            type: object
            required:
            - donor
            properties:
              donor:
                type: object
                description: The donor's identity and profile information. `email` is required and **must** match the email the donor will use when authenticating with DAFpay — DAFpay matches incoming verified emails to existing Accounts. Other fields are optional and may be filled in later by the donor during DAFpay profile setup.
                required:
                - email
                properties:
                  email:
                    type: string
                    description: The donor's email. Must match the email the donor will use when authenticating with DAFpay.
                    example: warrenBuffet@example.com
                  first_name:
                    type: string
                    description: The donor's first name.
                    example: Warren
                  last_name:
                    type: string
                    description: The donor's last name.
                    example: Buffet
                  phone:
                    type: string
                    description: The donor's phone number.
                    example: '+12125550100'
              external_id:
                type: string
                description: 'The DAF''s internal identifier for this Donor Account. Optional but strongly recommended — it allows you to reconcile DAFpay grants with the donor''s record in your own system without an additional update later. Maximum length: 255 characters.'
                example: ACME-DAF-DONOR-1042
              metadata:
                type: object
                description: A map of arbitrary string keys and values to store information about the object.
                additionalProperties:
                  type: string
  schemas:
    ProblemDetails:
      type: object
      description: RFC 7807 problem-details error (media type application/problem+json). The `status` field is an integer HTTP status code.
      required:
      - type
      - title
      - status
      - detail
      properties:
        type:
          type: string
          description: A URI reference identifying the problem type.
          example: about:blank
        title:
          type: string
          description: A short, human-readable summary of the problem type.
          example: API Error
        status:
          type: integer
          description: The HTTP status code for this error.
          example: 400
        detail:
          type: string
          description: A human-readable explanation specific to this occurrence.
          example: The request is invalid or contains invalid parameters.
      example:
        type: about:blank
        title: API Error
        status: 400
        detail: The request is invalid or contains invalid parameters.
    DonorAccountStatus:
      type: string
      description: "The status of a [Donor Account](/api/donor-accounts).\n  * `pending`: The Donor Account has been created but the DAF has not yet approved or rejected it.\n  * `approved`: The DAF has verified the donor's identity and Grants from this account can be processed.\n  * `rejected`: The DAF has rejected the Donor Account. Grants from this account will not be processed."
      enum:
      - pending
      - approved
      - rejected
      example: pending
    DonorAccount:
      type: object
      description: 'A Donor Account represents a DAFpay donor identity at a DAF.


        Donor Accounts are the bridge between a donor''s verified DAFpay identity (email, profile) and the donor''s record at the DAF.

        An Account must reach `approved` status — via an [Authorization Token](/api/authorization-tokens) — before its Grant Requests can be processed.


        A Donor Account may optionally have one or more [Giving Pools](/api/giving-pools) associated with it (see [Giving Pool](/api/giving-pools)). The relationship is many-to-one from `GivingPool` to `DonorAccount` — each Giving Pool belongs to exactly one Donor Account.


        There are two flows for how an Account reaches `approved`:


        - **Donor-Initiated Verification**: After a donor submits a Grant Request, DAFpay issues a one-time [Authorization Token](/api/authorization-tokens) and emails the `code` to the donor. The donor provides the code to the DAF, who calls [Verify Authorization Token](/api/authorization-tokens/verify) to approve the account.

        - **DAF-Initiated Setup**: The DAF creates the Donor Account and an Authorization Token in advance (e.g. when a donor opts in via the DAF portal). The donor enters the token''s `code` into DAFpay during profile setup, automatically approving the account.


        See the [Donor Accounts overview](/guides/dafpay/donor-accounts/overview) for a full discussion of these flows.'
      required:
      - id
      - status
      - donor
      - created_at
      - updated_at
      properties:
        id:
          type: string
          readOnly: true
          description: The unique identifier for this object.
          example: donor_account_01jpjenf5q6cawy43yxfcrxhct
        status:
          $ref: '#/components/schemas/DonorAccountStatus'
        donor:
          type: object
          description: The donor's identity and profile information.
          required:
          - email
          properties:
            email:
              type: string
              readOnly: true
              description: The donor's email. This is the donor's verified identifier — DAFpay verifies ownership via an email verification flow before a Donor Account is created.
              example: warrenBuffet@example.com
            first_name:
              type: string
              nullable: true
              description: The donor's first name as captured during DAFpay profile setup. May be null for Donor Accounts created via [Create Donor Account](/api/donor-accounts/create) before the donor has authenticated.
              example: Warren
            last_name:
              type: string
              nullable: true
              description: The donor's last name as captured during DAFpay profile setup. May be null for Donor Accounts created via [Create Donor Account](/api/donor-accounts/create) before the donor has authenticated.
              example: Buffet
            phone:
              type: string
              nullable: true
              description: 'The donor''s phone number as captured during DAFpay profile setup.

                <Note>

                DAFpay does not currently verify ownership of the phone number. Treat this field as donor-asserted information.

                </Note>'
              example: '+12125550100'
        external_id:
          type: string
          nullable: true
          description: The DAF's internal identifier for this Donor Account. Can be set on creation or via [Update Donor Account](/api/donor-accounts/update) to link the DAFpay Donor Account to the donor's record in the DAF's own systems.
          example: ACME-DAF-DONOR-1042
        approval:
          type: object
          nullable: true
          readOnly: true
          description: Details about the approval decision. Present when `status` is `approved`; otherwise `null`.
          properties:
            approved_at:
              type: string
              readOnly: true
              format: date-time
              description: Time when the Donor Account was approved. Expressed in RFC 3339 format.
              example: '2026-04-02T18:30:00Z'
            approved_by:
              type: string
              readOnly: true
              description: Identifier of the actor that approved this Donor Account. For DAF-initiated approvals, this is the DAF's API key principal. For automatic approvals via token verification, this is `system:authorization_token`.
              example: daf:fid_01jpjenf5q6cawy43yxfcrxhct
        rejection:
          type: object
          nullable: true
          readOnly: true
          description: Details about the rejection decision. Present when `status` is `rejected`; otherwise `null`.
          properties:
            rejected_at:
              type: string
              readOnly: true
              format: date-time
              description: Time when the Donor Account was rejected. Expressed in RFC 3339 format.
              example: '2026-04-02T18:30:00Z'
            rejected_by:
              type: string
              readOnly: true
              description: Identifier of the actor that rejected this Donor Account. For DAF-initiated rejections, this is the DAF's API key principal.
              example: daf:fid_01jpjenf5q6cawy43yxfcrxhct
            rejection_reason:
              type: string
              readOnly: true
              description: A human-readable reason provided by the DAF when rejecting the Donor Account.
              example: Donor could not be located in our records.
        disabled:
          type: boolean
          readOnly: true
          description: Whether this Donor Account is currently disabled. A disabled Donor Account remains `approved` but cannot submit new Grant Requests — call [Enable Donor Account](/api/donor-accounts/enable) to re-enable it. Disabling is only available for accounts in `approved` status.
          default: false
          example: false
        created_at:
          type: string
          readOnly: true
          format: date-time
          description: Time when this object was created. Expressed in RFC 3339 format.
          example: '2026-04-01T12:00:00Z'
        updated_at:
          type: string
          readOnly: true
          format: date-time
          description: Time when this object was last updated. Expressed in RFC 3339 format.
          example: '2026-04-02T18:30:00Z'
        metadata:
          type: object
          description: A map of arbitrary string keys and values to store information about the object.
          additionalProperties:
            type: string
  headers:
    X-Request-Id:
      description: The unique identifier for the request
      schema:
        type: string
  securitySchemes:
    oauth2:
      type: oauth2
      description: OAuth 2.0 Bearer token. A client may hold both scopes, but each FDX authorization must contain exactly one — they are mutually exclusive per authorization. An authorization containing both will be rejected. See the Authentication page for token exchange details.
      flows:
        authorizationCode:
          authorizationUrl: https://dashboard.givechariot.com/oauth/authorize
          tokenUrl: https://api.givechariot.com/auth/oauth/token
          scopes:
            read:bank_accounts: Read access to bank account data
            sync:connected_accounts: Sync access to connected account data