Skip to main content

Outcome

An authenticated user has a new Endaoment fund. Your app stores the fund id for donations and grants.

When

After Authenticate. Trigger when the user opens their first fund or creates an additional one. The authenticated user becomes the fund manager. See the glossary for DAF terminology.

Choose your route

Fund creation depends on how the caller authenticated:
CallerRouteWhen to use
OAuth access token from a registered client (token includes clientId)POST /v1/funds/partnerTypical external OAuth integrators — POST /v1/funds returns 400 by design (IS-29676)
Access token without clientId (first-party / direct session)POST /v1/fundsInternal or first-party flows only
Check GET /v1/auth/whoami if unsure: OIDC callers include clientId when issued through a registered OAuth client. Proxy all calls from your backend. See Integration Patterns.

Option A: Registered OAuth client → POST /v1/funds/partner

Use this path for standard OAuth quickstart integrators. Prerequisite: The acting user must have saved identity (PII) on Endaoment before this call. The partner route builds the fund advisor from stored identity — if none exists, the API returns 400: “User must be provisioned with PII before creating a partner fund.” Complete Authenticate with profile/address data, or Provision user on the partner track first.

Auth

Pick one acting-user path (see Partner auth options):
PathHeaders
Registered OAuth user tokenAuthorization: Bearer <access_token> only
API key + body user idx-api-key + partnerUserIdentifier in body
API key + impersonation headerx-api-key + x-endaoment-user-id
Partner OIDC bearerAuthorization: Bearer <partner_oidc_token>
The registered OAuth user token path is the standard quickstart flow after Authenticate. Server-to-server partner flows use x-api-key (see Partner Journey).

Required inputs

Flat body (PartnerCreateFundInputDto) — no fundInput wrapper:
FieldDescription
nameFund display name
partnerAccountIdentifierPartner-scoped idempotency key (16–64 printable ASCII characters)
descriptionOptional fund description
partnerUserIdentifierRequired when using API key + body user resolution (16–64 printable ASCII characters)
API reference: Create fund

Example request (registered OAuth user token)

curl -X POST "https://api.dev.endaoment.org/v1/funds/partner" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Giving Fund",
    "description": "Personal charitable giving account",
    "partnerAccountIdentifier": "550e8400-e29b-41d4-a716-446655440001"
  }'

Example request (API key + impersonation header)

curl -X POST "https://api.dev.endaoment.org/v1/funds/partner" \
  -H "x-api-key: $PARTNER_API_KEY" \
  -H "x-endaoment-user-id: $ENDAOMENT_USER_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Giving Fund",
    "description": "Personal charitable giving account",
    "partnerAccountIdentifier": "550e8400-e29b-41d4-a716-446655440001",
    "partnerUserIdentifier": "550e8400-e29b-41d4-a716-446655440002"
  }'

Option B: First-party token → POST /v1/funds

Use only when the access token has no clientId (not a registered OAuth client token).

Auth

HeaderValue
AuthorizationBearer <access_token>
API reference: Create fund

Required inputs

Minimum fundInput fields:
FieldDescription
nameFund display name
descriptionFund description
advisor.firstNamePrimary advisor first name
advisor.lastNamePrimary advisor last name
advisor.emailPrimary advisor email
advisor.address.line1Street address
advisor.address.cityCity
advisor.address.stateState
advisor.address.zipZIP code

Example request

curl -X POST "https://api.dev.endaoment.org/v1/funds" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "fundInput": {
      "name": "My Giving Fund",
      "description": "Personal charitable giving account",
      "advisor": {
        "firstName": "Alex",
        "lastName": "Donor",
        "email": "alex@example.com",
        "address": {
          "line1": "123 Main St",
          "city": "San Francisco",
          "state": "CA",
          "zip": "94105"
        }
      }
    }
  }'

Response you need

FieldUse
idFund ID for donations and grants
usdcBalanceCurrent balance (microdollars)

Common mistakes

  • Calling POST /v1/funds with a registered OAuth client token (returns 400 — use /v1/funds/partner)
  • Creating a partner fund before the acting user has saved PII/identity on Endaoment
  • Using fundInput / advisor.* schema on the partner route (partner route expects a flat body)
  • Using partner identifiers shorter than 16 characters (validation rejects them)
  • Omitting partnerAccountIdentifier on the partner route
  • Calling the API from the browser with a Bearer token

Full sample

Reference implementation: GitHub quickstart — create DAF. Optional next step: Manage Collaborators. Next: Fund a DAF