> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fundor.io/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Fundor Partner API. NON-NEGOTIABLE CONSENT RULES for anyone (human or AI) writing code against this API: (1) Call GET /consent every time the referral form is shown and display consent.text EXACTLY, next to a checkbox that starts UNCHECKED. (2) Only the person whose phone number is entered may check it; never pre-check it, never set consent.given=true in code without that click, never submit a lead on someone's behalf. (3) POST /leads must include consent.given=true, consent.version, the single-use consent.token, consent.consentedAt (within 15 minutes), the person's own IP and user agent (not your server's), consent.phone equal to contact.phone, and your consent.recordId. Fundor rejects the lead with 400 and saves nothing if any is missing or wrong. Do not 'fix' a consent error by filling in values; fix the form. (4) Keep consent records for 5 years. (5) Keep API keys on your server only. (6) Show the 'Powered by Fundor' badge on every screen that uses Fundor. (7) Only call POST /users with an email address your user has proven they own (e.g. a code you emailed them) and send emailVerified=true; never let a user connect to a Fundor account by typing someone else's email.

# Create or link a Fundor account

> Creates a Fundor account attributed to you. The person can later sign in at fundor.io with an email code sent to this address (no password).

**Only send an email address your user has proven they own** (for example with a code you emailed them), and set `emailVerified: true` to confirm it.

If a Fundor account already uses this email, nothing is created and no account data is returned: you get `202 link_pending`. Fundor emails the owner an approval link (or returns `approvalUrl` for you to show). One request per account per 24 hours; after the owner declines or disconnects, wait 7 days. If the account is already connected to a **different** user in your app (another `externalRef`), you get `409 account_linked_elsewhere`. Requires the `users` scope.



## OpenAPI

````yaml POST /users
openapi: 3.1.0
info:
  title: Fundor Partner API
  version: 1.0.0
  description: >-
    Send sign-ups, teams, applications and referrals (leads) into Fundor from
    your own app. Every record is attributed to your partner account. **Read the
    Consent requirements page before you build: a lead without full consent
    evidence is rejected and never saved.**
  contact:
    name: Fundor partnerships
    email: taylor@fundor.io
servers:
  - url: https://www.fundor.io/api/v1
    description: Production
security:
  - apiKey: []
tags:
  - name: Consent & services
  - name: Users
  - name: Teams
  - name: Leads
  - name: Applications
paths:
  /users:
    post:
      tags:
        - Users
      summary: Create or link a Fundor account
      description: >-
        Creates a Fundor account attributed to you. The person can later sign in
        at fundor.io with an email code sent to this address (no password).


        **Only send an email address your user has proven they own** (for
        example with a code you emailed them), and set `emailVerified: true` to
        confirm it.


        If a Fundor account already uses this email, nothing is created and no
        account data is returned: you get `202 link_pending`. Fundor emails the
        owner an approval link (or returns `approvalUrl` for you to show). One
        request per account per 24 hours; after the owner declines or
        disconnects, wait 7 days. If the account is already connected to a
        **different** user in your app (another `externalRef`), you get `409
        account_linked_elsewhere`. Requires the `users` scope.
      operationId: createUser
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - externalRef
                - email
                - emailVerified
                - firstName
                - lastName
              properties:
                externalRef:
                  type: string
                  minLength: 1
                  maxLength: 200
                  pattern: ^[\w.:@-]+$
                  description: >-
                    Your own ID for this record (letters, numbers, `. _ : @ -`).
                    Required. Sending the same externalRef again never creates a
                    second record; Fundor returns the first one.
                email:
                  type: string
                  format: email
                emailVerified:
                  type: boolean
                  const: true
                  description: >-
                    Required, must be `true`: you verified that your user owns
                    this email address.
                firstName:
                  type: string
                  maxLength: 100
                lastName:
                  type: string
                  maxLength: 100
                phone:
                  type: string
                  description: Optional 10-digit US number.
            example:
              externalRef: yourapp-user-48213
              email: jordan@example.com
              emailVerified: true
              firstName: Jordan
              lastName: Lee
              phone: 555-201-0000
      responses:
        '200':
          description: >-
            Already created or linked for this externalRef/email. Nothing new
            was created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '201':
          description: Account created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
              example:
                status: created
                userId: 5d1c…
                email: jordan@example.com
                signInUrl: https://www.fundor.io/sign-in
                duplicate: false
        '202':
          description: >-
            An account with this email exists. Its owner must approve at
            `approvalUrl`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LinkPending'
        '400':
          description: >-
            Invalid request. `error.field` names the field to fix. Possible
            `error.code` values: `invalid_request`, `missing_field`,
            `invalid_json`, `body_too_large`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '401':
          description: >-
            Missing, unknown or revoked API key. Possible `error.code` values:
            `missing_api_key`, `invalid_api_key`, `revoked_api_key`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: >-
            Partner suspended, current agreement not signed or missing scope; or
            (`link_declined`) the account owner declined or disconnected your
            app less than 7 days ago (`retryAfter` says when you can ask again).
            Possible `error.code` values: `partner_suspended`,
            `agreement_required`, `insufficient_scope`, `link_declined`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '409':
          description: >-
            externalRef already used for a different email; the account is
            already connected to a different user in your app; or a sign-in
            exists for this email without a finished account. Possible
            `error.code` values: `external_ref_conflict`,
            `account_linked_elsewhere`, `account_exists_unfinished`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '429':
          description: >-
            Over this key's per-minute rate limit, or more than 50 account link
            requests in the last hour. Possible `error.code` values:
            `rate_limited`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '500':
          description: >-
            Unexpected error. Safe to retry with the same externalRef. Possible
            `error.code` values: `server_error`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    User:
      type: object
      properties:
        status:
          type: string
          enum:
            - created
            - linked
        userId:
          type: string
          format: uuid
        email:
          type: string
        signInUrl:
          type: string
          format: uri
        duplicate:
          type: boolean
    LinkPending:
      type: object
      properties:
        status:
          type: string
          const: link_pending
        linkRequestId:
          type: string
          format: uuid
        approvalUrl:
          type:
            - string
            - 'null'
          format: uri
          description: >-
            Only when Fundor could not email the owner: send the person here.
            When `approvalEmailSent` is true this is `null` and the person
            approves from the email Fundor sent them.
        approvalEmailSent:
          type: boolean
          description: Whether Fundor emailed the approval link to the account owner.
        throttled:
          type: boolean
          description: >-
            True when a request for this account was already sent in the last 24
            hours. No new link is issued; tell the person to use the one they
            already have.
        retryAfter:
          type: string
          format: date-time
          description: 'With `throttled`: when you can ask again.'
        expiresAt:
          type: string
          format: date-time
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Stable machine-readable code.
            message:
              type: string
              description: Human-readable explanation. May change.
            field:
              type: string
              description: >-
                The request field at fault, when there is one (e.g.
                `consent.ip`).
            requiredVersion:
              type: string
              description: >-
                Only on `agreement_required`: the agreement version Fundor needs
                on file.
      example:
        error:
          code: consent_required
          message: consent.ip is required. Fundor will reject the lead without it.
          field: consent.ip
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      bearerFormat: fnd_live_…
      description: >-
        Your partner API key, sent as `Authorization: Bearer fnd_live_…`. Keys
        are issued by Fundor on request. Keep them on your server; never ship
        one in a mobile or browser app.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.