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

# Create a patient

> Creates a patient chart in the EHR. With `checkForDuplicates: true`, a dedupe hit WITHHOLDS the write and returns 409 `duplicate_candidates` with the candidate ids — review them and either book against an existing chart or retry without the flag. Send an `Idempotency-Key` header to protect retries for 24 hours. An uncertain vendor outcome returns 409 `ehr_write_uncertain` with `requiresReconciliation: true`; verify the chart in the EHR before attempting another create. The same key remains protected during that retention period.



## OpenAPI

````yaml /openapi-v1.json post /patients
openapi: 3.0.0
info:
  title: Max AI Public API
  description: API for third-party marketplace apps
  version: '1.0'
  contact: {}
servers:
  - url: https://api.maxcare.ai/v1
security: []
tags: []
paths:
  /patients:
    post:
      tags:
        - Patients
      summary: Create a patient
      description: >-
        Creates a patient chart in the EHR. With `checkForDuplicates: true`, a
        dedupe hit WITHHOLDS the write and returns 409 `duplicate_candidates`
        with the candidate ids — review them and either book against an existing
        chart or retry without the flag. Send an `Idempotency-Key` header to
        protect retries for 24 hours. An uncertain vendor outcome returns 409
        `ehr_write_uncertain` with `requiresReconciliation: true`; verify the
        chart in the EHR before attempting another create. The same key remains
        protected during that retention period.
      operationId: PatientsPublicController_createPatient
      parameters:
        - name: idempotency-key
          required: false
          in: header
          description: >-
            Client-generated UUID, honoured for 24 hours. Fails closed: if the
            idempotency store is unreachable the write is refused with 503
            `idempotency_unavailable` and nothing reaches the EHR, rather than
            proceeding with the guarantee silently withdrawn. Omit the header to
            accept at-least-once instead.
          schema:
            type: string
        - name: X-Organization-Id
          in: header
          required: true
          schema:
            type: string
          description: Target clinic organization ID
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreatePatientBody'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreatePatientSuccessResponse'
        '400':
          description: Missing or invalid request parameter
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiBadRequestResponse'
        '401':
          description: Invalid or missing API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiUnauthorizedResponse'
        '403':
          description: Insufficient scope
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiForbiddenResponse'
        '409':
          description: Resource conflict (e.g. editing a signed note)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiConflictResponse'
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiRateLimitResponse'
        '502':
          description: EHR sync failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiBadGatewayResponse'
        '503':
          description: EHR integration unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicApiServiceUnavailableResponse'
      security:
        - api-key: []
components:
  schemas:
    CreatePatientBody:
      type: object
      properties:
        firstName:
          type: string
          example: Jane
        middleName:
          type: string
          example: Marie
        lastName:
          type: string
          example: Doe
        dateOfBirth:
          type: string
          description: YYYY-MM-DD
          example: '1984-02-11'
        sex:
          type: string
          description: '`MALE` | `FEMALE` | vendor value; the adapter maps it'
          example: FEMALE
        email:
          type: string
          example: jane@example.com
        phones:
          type: array
          items:
            $ref: '#/components/schemas/PatientContactPointBody'
        address:
          $ref: '#/components/schemas/PatientAddressBody'
        primaryFacilityId:
          type: string
          description: Primary facility ID (fac_…)
        checkForDuplicates:
          type: boolean
          description: >-
            Ask the EHR to dedupe-check before committing. When candidates are
            found the write is WITHHELD and the response is 409
            `duplicate_candidates` — surfacing that is what stops a booking flow
            creating duplicate charts.
          example: true
        insurance:
          $ref: '#/components/schemas/PatientInsuranceBody'
        consents:
          $ref: '#/components/schemas/PatientConsentsBody'
      required:
        - firstName
        - lastName
        - dateOfBirth
    CreatePatientSuccessResponse:
      type: object
      properties:
        code:
          type: string
          description: Response code
          example: success
        data:
          $ref: '#/components/schemas/CreatePatientData'
      required:
        - code
        - data
    PublicApiBadRequestResponse:
      type: object
      properties:
        code:
          type: string
          description: Error code
          example: bad_request
        message:
          type: string
          description: Human-readable error message
          example: '''id'' must be a valid UUID'
        trace_id:
          type: string
          description: Trace ID for debugging
          example: 550e8400-e29b-41d4-a716-446655440000
      required:
        - code
        - message
        - trace_id
    PublicApiUnauthorizedResponse:
      type: object
      properties:
        code:
          type: string
          description: Error code
          example: unauthorized
        message:
          type: string
          description: Human-readable error message
          example: Invalid or missing API key
        trace_id:
          type: string
          description: Trace ID for debugging
          example: 550e8400-e29b-41d4-a716-446655440000
      required:
        - code
        - message
        - trace_id
    PublicApiForbiddenResponse:
      type: object
      properties:
        code:
          type: string
          description: Error code
          example: forbidden
        message:
          type: string
          description: Human-readable error message
          example: Insufficient scope
        trace_id:
          type: string
          description: Trace ID for debugging
          example: 550e8400-e29b-41d4-a716-446655440000
      required:
        - code
        - message
        - trace_id
    PublicApiConflictResponse:
      type: object
      properties:
        code:
          type: string
          description: Error code
          example: conflict
        message:
          type: string
          description: Human-readable error message
          example: Cannot edit a signed note
        trace_id:
          type: string
          description: Trace ID for debugging
          example: 550e8400-e29b-41d4-a716-446655440000
      required:
        - code
        - message
        - trace_id
    PublicApiRateLimitResponse:
      type: object
      properties:
        code:
          type: string
          description: Error code
          example: rate_limit_exceeded
        message:
          type: string
          description: Human-readable error message
          example: Rate limit exceeded. Maximum 1000 requests per 60 seconds.
        trace_id:
          type: string
          description: Trace ID for debugging
          example: 550e8400-e29b-41d4-a716-446655440000
      required:
        - code
        - message
        - trace_id
    PublicApiBadGatewayResponse:
      type: object
      properties:
        code:
          type: string
          description: Error code
          example: unexpected_integration_error
        message:
          type: string
          description: Human-readable error message
          example: EHR sync failed
        trace_id:
          type: string
          description: Trace ID for debugging
          example: 550e8400-e29b-41d4-a716-446655440000
      required:
        - code
        - message
        - trace_id
    PublicApiServiceUnavailableResponse:
      type: object
      properties:
        code:
          type: string
          description: Error code
          example: server_unresponsive
        message:
          type: string
          description: Human-readable error message
          example: EHR integration is not available for this note
        trace_id:
          type: string
          description: Trace ID for debugging
          example: 550e8400-e29b-41d4-a716-446655440000
      required:
        - code
        - message
        - trace_id
    PatientContactPointBody:
      type: object
      properties:
        type:
          type: string
          description: Contact point type — the same enum the EHR adapter layer uses
          enum:
            - CELL_PHONE
            - HOME_PHONE
            - WORK_PHONE
            - EMAIL_ADDRESS
          example: CELL_PHONE
        value:
          type: string
          example: '+13135550123'
        preferred:
          type: boolean
          description: >-
            Unsupported. Omit this field; preferred-contact updates are not
            available.
          deprecated: true
      required:
        - type
        - value
    PatientAddressBody:
      type: object
      properties:
        line1:
          type: string
          example: 1200 Miller Rd
        line2:
          type: string
          example: Apt 4
        city:
          type: string
          example: Flint
        state:
          type: string
          description: >-
            Two-letter state code. The adapters translate to each vendor's form
            (EZDerm `FLORIDA`, ModMed `FL`).
          example: MI
        zip:
          type: string
          example: '48507'
        country:
          type: string
          example: US
      required:
        - line1
        - city
        - state
        - zip
    PatientInsuranceBody:
      type: object
      properties:
        payerName:
          type: string
          example: BCBS of Michigan
        memberId:
          type: string
          example: XYZ123456
        groupNumber:
          type: string
          example: '0009'
        subscriberRelationship:
          type: string
          description: >-
            The policyholder's relationship to the patient. `SELF` (the default)
            means the patient is the policyholder. Anything else — `SPOUSE`,
            `CHILD`, … — REQUIRES the `subscriber*` fields below; without them
            the request is rejected with `subscriber_required` rather than
            writing a policy whose policyholder is unknown.
          example: SELF
        subscriberFirstName:
          type: string
          description: >-
            Policyholder's first name. Required when `subscriberRelationship` is
            not `SELF`.
          example: Robert
        subscriberLastName:
          type: string
          description: >-
            Policyholder's last name. Required when `subscriberRelationship` is
            not `SELF`.
          example: Doe
        subscriberDateOfBirth:
          type: string
          description: >-
            Policyholder's date of birth, YYYY-MM-DD. Required when
            `subscriberRelationship` is not `SELF` — a claim identifies the
            subscriber by name AND date of birth, so a name alone still sends
            the biller back to the patient.
          example: '1968-03-14'
        subscriberSex:
          type: string
          description: >-
            Policyholder's sex, as the payer knows it. A professional claim's
            2010BA loop carries the subscriber's `DMG` demographics — date of
            birth AND gender — so omitting it leaves a correctable rejection on
            the table. NOT required: unlike name and date of birth, a missing
            gender does not make the policyholder unidentifiable, so it is never
            a reason to refuse the write.
          enum:
            - M
            - F
            - U
          example: M
        subscriberAddress:
          description: >-
            Policyholder's address, for the claim's 2010BA `N3`/`N4` segments.
            Omit and set `subscriberAddressSameAsPatient` instead when the
            policyholder lives with the patient — the common case for a spouse
            or dependant, and the one ModMed models natively.
          allOf:
            - $ref: '#/components/schemas/PatientAddressBody'
        subscriberAddressSameAsPatient:
          type: boolean
          description: >-
            `true` when the policyholder lives at the patient's address. Maps to
            ModMed's own `policyHolderAddressSameAsPatients`, so the EHR
            resolves the address itself rather than us copying it and creating a
            second copy that can drift. Mutually exclusive with
            `subscriberAddress`; supplying both is rejected.
          example: true
        planName:
          type: string
          description: >-
            Plan name as printed on the card (e.g. `PPO Gold`). Previously
            always written as null; supply it when the card shows it.
          example: PPO Gold
      required:
        - payerName
        - memberId
    PatientConsentsBody:
      type: object
      properties:
        callTextConsent:
          type: boolean
          description: Patient consented to calls/texts
          example: true
        consentCapturedAt:
          type: string
          description: When consent was captured (ISO-8601)
          example: '2026-07-26T13:00:00Z'
      required:
        - callTextConsent
        - consentCapturedAt
    CreatePatientData:
      type: object
      properties:
        patient:
          $ref: '#/components/schemas/CreatedPatientResponse'
        duplicateCandidateIds:
          description: >-
            Existing charts the EHR flagged as possible duplicates. Empty on a
            clean create.
          example: []
          type: array
          items:
            type: string
      required:
        - patient
        - duplicateCandidateIds
    CreatedPatientResponse:
      type: object
      properties:
        id:
          type: string
          nullable: true
          description: >-
            Max AI patient ID. `null` when the chart exists in the EHR but has
            not been mirrored yet — use `externalId` until the next patient sync
            lands.
          example: pat_c56103bcd39c46d39f3138dd2b5e05f6
        externalId:
          type: string
          description: The EHR's own patient identifier
          example: '882731'
        mrn:
          type: string
          nullable: true
          example: MM0000123456
        created:
          type: boolean
          description: >-
            Always `true` on a 2xx: this endpoint either creates a chart or
            refuses. When the EHR flags possible duplicates the request fails
            with 409 `duplicate_candidates` and the candidate ids, rather than
            returning an existing chart with `created: false` — so do not branch
            on this expecting a match case.
          example: true
        insuranceAttached:
          type: boolean
          nullable: true
          description: >-
            Outcome of the optional `insurance` block. `null` when none was
            submitted, `true` when it reached the EHR, `false` when the chart
            was created but the coverage write failed — the chart is real and
            bookable either way, but on `false` the coverage is NOT on file and
            must be retried via POST /patients/{id}/insurance.
          example: null
      required:
        - id
        - externalId
        - mrn
        - created
        - insuranceAttached
  securitySchemes:
    api-key:
      scheme: bearer
      bearerFormat: JWT
      type: http
      description: Marketplace API key

````