Docs
Get in touchPartner Portal

Syncing users

A FounderPass user record represents one member of your community. The Partner API lets you create, list, update, and delete users. Partner admins can also create, invite, and remove members by hand in the Partner Portal (including bulk CSV invites); this guide covers the API path for programmatic sync at scale.

Create or return a user

curl -X POST https://perks.founderpass.com/v1/users \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "alice@example.com",
    "external_user_id": "cust_abc123",
    "tier": "free",
    "user_types": ["Early-stage startup"],
    "regions": ["North America"],
    "eligibility": {
      "eligibility_company_stage": ["seed", "series_a_plus"],
      "eligibility_funding": ["vc_backed_only"]
    }
  }'

If the email already belongs to your partner, the response is the existing user record with already_exists: true. Existing records are returned unchanged; request fields such as tier, user_types, regions, and firebase_uid are only applied when a new user is created. This makes the endpoint idempotent: safe to call from a webhook or batch job.

FieldTypeRequiredNotes
emailstringYesUser’s email
external_user_idstringNoYour own user ID for this member. Unique per partner. Lets you attribute events without Firebase, pass it later as the external_user_id resolver on POST /v1/events/track.
firebase_uidstringNoSet if your users authenticate via Firebase
tierenumNofree or premium; omitted → the partner’s configured default tier (usually free). Drives freemium gating.
user_typesarray of UserTypeNoLifecycle stage(s), e.g. ["Early-stage startup"]
regionsarray of AudienceRegionNoNamed regions, e.g. ["Europe", "North America"]. Omitted → the partner’s own configured regions.
eligibilityobjectNoThe member’s structured eligibility, same eligibility_* arrays a deal carries (see Eligibility criteria). Drives which gated deals the user can see and redeem. See the note below.

Response

{
  "id": "018e4b2a-0000-7def-abcd-000000000099",
  "email": "alice@example.com",
  "external_user_id": "cust_abc123",
  "tier": "free",
  "user_types": ["Early-stage startup"],
  "regions": ["North America"],
  "eligibility_customer_type": ["new_customers_only", "existing_customers_eligible"],
  "eligibility_company_stage": ["seed", "series_a_plus"],
  "eligibility_company_size": ["1_10", "11_50", "51_200", "200_plus"],
  "eligibility_incorporation": ["registered_company_required", "sole_traders_allowed"],
  "eligibility_funding": ["vc_backed_only"],
  "sign_in_url": "/auth/signin?token=...",
  "already_exists": false,
  "created_at": "2026-05-26T16:00:00Z"
}

sign_in_url is a relative magic-link path (/auth/signin?token=...), not an absolute URL. Prefix it with your member’s portal origin (https://<your-slug>.perks.founderpass.com) to build the clickable link that lands them directly inside their portal, useful for onboarding emails.

List users

curl "https://perks.founderpass.com/v1/users?page=1&per_page=50" \
  -H "Authorization: Bearer $TOKEN"

Supports standard pagination, plus an optional tier=free|premium filter.

Update a user

Use PATCH /v1/users/{id} to update existing user fields. Omitted fields remain unchanged.

curl -X PATCH https://perks.founderpass.com/v1/users/{id} \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "tier": "premium",
    "external_user_id": "cust_abc123",
    "user_types": ["Growth-stage startup"],
    "regions": ["Europe", "North America"],
    "eligibility": {
      "eligibility_company_stage": ["series_a_plus"],
      "eligibility_funding": ["vc_backed_only", "accelerator_only"]
    }
  }'

You can update tier, user_types, regions, firebase_uid, external_user_id, and eligibility. Re-running POST /v1/users for an existing email returns the existing record and does not refresh those fields, so use PATCH to set or change a member’s external_user_id or eligibility after creation. external_user_id must be unique within your partner, reusing one that already belongs to another user returns 400 Bad Request (external_user_id already belongs to another user). The same conflict on POST /v1/users also returns 400.

Delete a user

curl -X DELETE https://perks.founderpass.com/v1/users/{id} \
  -H "Authorization: Bearer $TOKEN"

Common patterns

Daily reconciliation

Pull users from your source of truth nightly and create any missing records in FounderPass. Use PATCH /v1/users/{id} for records whose tier, type, region, or Firebase UID changed.

Webhook-driven

When a new user signs up, fire a server-side POST /v1/users. When their tier or audience attributes change, send PATCH /v1/users/{id}. When they leave, DELETE.

See the full schema and every field in the Users API Reference.