---
title: "Create a prior authorization"
method: POST
path: "/v1/prior-authorizations"
tags: ["Prior Authorizations"]
---

# Create a prior authorization

`POST /v1/prior-authorizations`

Create a new prior authorization. Provide exactly one of `patient_id` (existing id) or `patient_data` (inline demographics; server find-or-creates). Optionally provide one of `payor_id` or `payor_data`. New authorizations start in `status=pending`.

## Request body

- PriorAuthorizationCreateRequest — Create a prior authorization. Provide exactly one of `patient_id` (existing patient id) or `patient_data` (inline demographics; server find-or-creates). Optionally provide one of `payor_id` (existing patient-payor id, validated to belong to the resolved patient) or `payor_data` (inline; server links to an existing payor row on the resolved patient that matches the catalog id). If neither is provided and no payor exists on the patient for that catalog id, the authorization is created without a linked payor.
  - `type` 'assessment' | 'treatment' | 'reassessment' | 'reassessment_and_treatment', required — Authorization type.
  - `patient_id` string, uuid, nullable — Existing patient id. When provided, the patient is looked up by id (must belong to your company and be active). Mutually exclusive with `patient_data`.
  - `patient_data` PatientInlineData — Inline patient demographics for find-or-create resolution. Submit this when the caller doesn't have a patient id. The server looks up an existing patient in this company by (first_name, last_name, date_of_birth); if found, the authorization is linked to that patient. If not found, a new patient row is created and side effects (webhook, workflow automation, activity log) fire as if the caller had called `POST /v1/patients` directly.
    - `first_name` string, required — Patient first name.
    - `last_name` string, required — Patient last name.
    - `date_of_birth` string, date, required — Patient date of birth (`YYYY-MM-DD`).
  - `payor_id` string, uuid, nullable — Existing patient-payor id (must belong to the resolved patient and be active). Mutually exclusive with `payor_data`. **Write-only resolution input** — this id is used to derive and freeze the member id + insurance id onto the authorization at create time. It is NOT returned on the resource. To read payor information, use `payor_member_id`, `payor_insurance_id`, and `payor_insurance` on the response.
  - `payor_data` PayorInlineData — Inline payor data for find-or-link resolution against the resolved patient. Submit this when the caller doesn't have a patient-payor id. The server looks up an active payor row on the resolved patient that points to the same `insurance_id`; the authorization records the resolved payor's `insured_member_id` + `insurance_id`. If no matching payor exists, the authorization still records the inline `insurance_id` and `member_id` exactly as submitted (no payor row is auto-created).
    - `insurance_id` string, uuid, required — UUID of the company-level insurance partner from the `insurances` catalog (e.g., Aetna, Anthem). This is distinct from `payor_id` above, which references a patient-specific payor row carrying a member id.
    - `member_id` string, nullable — The member ID printed on the patient's insurance card.
    - `insurance_display_name` string, nullable — Plan display name for this payor (e.g. a specific plan under a shared insurance partner). Must be one of the insurance's aliases. Frozen onto the authorization at create time.
  - `service` ServiceBlock — Service request details. Captures what the requester is asking the payor to authorize.
    - `specialty` 'aba' | 'speech_therapy' | 'occupational_therapy' | 'physical_therapy' | 'mental_behavioral_health' — Clinical specialty the authorization covers.
    - `service_type_codes` string[], nullable — Free-form service type codes as defined by the payor's coverage catalog (e.g. `AS`, `WK`). Pass-through identifiers — not validated against an internal enum.
    - `start_date` string, date, nullable — Requested service start date (`YYYY-MM-DD`).
    - `end_date` string, date, nullable — Requested service end date (`YYYY-MM-DD`). Send `null` for open-ended requests where the payor will set the end date in the approval.
    - `cpt_codes` ServiceCptCode[], nullable — Requested CPT/HCPCS codes paired with unit counts.
      - `code` string, required — CPT or HCPCS procedure code.
      - `units` string, required — Quantity for this code. Stored as a string because some payors permit non-integer quantities (e.g. `0.5` hours of evaluation).
      - `unit_type` 'units' | 'visits' | 'hours' — Quantity unit a CPT/HCPCS line is measured in. Lives inside the `service_cpt_codes` / `result_cpt_codes` JSON (not a dedicated column), so this is a plain str Enum with no `__pg_type__`. Old rows predate the field — readers default a missing value to `units`. Wire values mirror the Prisma `PriorAuthorizationUnitType` enum (`units` / `visits` / `hours`); keep them in sync by hand (the `...Enum` suffix here intentionally keeps this out of `verify-enum-sync`'s name-matched set, same as the other PA enums).
      - `modifiers` CptModifier[], nullable — CPT/HCPCS modifiers that apply to this code (e.g. `95`, `GT`). Optional — entries created before this field existed omit it and read back as `None`.
    - `requested_visits` integer, nullable — Requested number of visits. Optional — used by therapy disciplines (physical / occupational / speech therapy) whose authorizations are granted by visit count rather than a fixed coverage block. Decoupled from `cpt_codes` (a payor may authorize visits with no CPT code).
    - `requested_weeks` integer, nullable — Requested number of weeks the services span. Optional — captured alongside `requested_visits` for visit-based therapy authorizations. Does not drive the end date.
    - `locations` PlaceOfService[], nullable — Places of service requested for this authorization (CMS POS categories).
  - `requesting_provider_id` string, uuid, required — Credentialing record id for the provider requesting the authorization.
  - `servicing_provider_id` string, uuid, nullable — Credentialing record id for the servicing provider. Omit when the servicing provider is the same as the requesting provider.
  - `servicing_location_id` string, uuid, nullable — Company-location id where services will be rendered.
  - `organization_id` string, uuid, nullable — Business entity (organization) this authorization belongs to. Optional.
  - `notes` string, nullable — Free-text notes attached to the authorization. Editable post-creation.
  - `scheduled_submission_date` string, date, nullable — Date this authorization should be submitted (`YYYY-MM-DD`). When set in the future, the request is held out of the active review queue until that date. Omit or send `null` to submit whenever it is picked up.
  - `copy_files_from_prior_authorization_id` string, uuid, nullable — When set, the new authorization is seeded with copies of the attached documents from this existing authorization (which must belong to your company). Each document is re-linked as a new file record pointing at the same stored object — the source authorization keeps its own copies. Used to duplicate an authorization (e.g. an assessment into a treatment).

## Response `201`

Successful Response

- PriorAuthorizationResponse — Response schema for a prior authorization record.
  - `id` string, uuid, required
  - `company_id` string, uuid, required
  - `created_by_user_id` string, nullable
  - `type` 'assessment' | 'treatment' | 'reassessment' | 'reassessment_and_treatment', required — Authorization type.
  - `status` 'pending' | 'submitted' | 'information_needed' | 'decided' | 'cancelled', required — Lifecycle state of a prior authorization.
  - `decision` 'approved' | 'partially_approved' | 'denied' | 'no_authorization_required' — Payor outcome on a decided authorization.
  - `appeal_status` 'requested' | 'appealing' | 'appeal_approved' | 'appeal_denied' | 'not_appealing' — Appeal lifecycle. Applies only when decision is denied or partially_approved. NULL is meaningful: it means no appeal decision has been made yet — the caller hasn't yet asked for one. Setting any value below is an explicit commitment that someone is (or isn't) pursuing the appeal: requested — operator/patient asked for an appeal; team hasn't started. appealing — team is actively working the appeal. appeal_approved — terminal, won. appeal_denied — terminal, lost. not_appealing — terminal, operator decided not to pursue.
  - `appeal_notes` string, nullable — Rationale captured when an appeal was requested. Null when no appeal has been requested.
  - `appeal_number` string, nullable — Appeal case/reference number issued by the payor. Null until the payor assigns one.
  - `appeal_availability` AppealAvailabilitySlot[], nullable — Requester availability windows captured when an appeal was requested. Null when none provided.
    - `day` string, required — Lowercase weekday, e.g. `monday`.
    - `start` string, required — Window start time, 24-hour `HH:MM`.
    - `end` string, required — Window end time, 24-hour `HH:MM`.
  - `notes` string, nullable
  - `patient_id` string, uuid, required — Patient this authorization belongs to; use it to open the patient record. Demographics submitted on this PA are the frozen `patient_*` fields below.
  - `patient_first_name` string, required — Patient first name as submitted on this authorization. Frozen at create time — not updated when the patient record changes.
  - `patient_last_name` string, required — Patient last name as submitted on this authorization. Frozen at create time.
  - `patient_date_of_birth` string, date, required — Patient date of birth (`YYYY-MM-DD`) as submitted on this authorization. Frozen at create time.
  - `payor_member_id` string, nullable — Member id as submitted on this authorization. Frozen at create time.
  - `payor_insurance_id` string, uuid, nullable — Insurance partner id (from the `insurances` catalog) as submitted on this authorization. Frozen at create time.
  - `payor_insurance_display_name` string, nullable — Plan display name for this PA's payor, frozen at create time. Null ⇒ display the insurance's canonical name.
  - `payor_insurance` PriorAuthorizationInsurance — Nested insurance partner ({id, name}) for the FROZEN snapshot. Resolved from the `payor_insurance` relationship, which loads regardless of the insurance's `is_active` flag — so a PA submitted under a since- deactivated insurance still carries its name for display.
    - `id` string, uuid, required
    - `name` string, required
    - `trading_partner_service_id` string, nullable — Trading partner service ID for this insurance, when mapped. Lets the client resolve the payer logo from the payer directory. Null when the insurance has no trading partner mapping.
  - `requesting_provider_id` string, uuid, nullable — Credentialing-record id of the requesting provider. Always present unless the provider record was later removed (FK is ON DELETE SET NULL).
  - `servicing_provider_id` string, uuid, nullable — Credentialing-record id of the servicing provider. Null when the servicing provider is the same as the requesting provider or unset.
  - `servicing_location_id` string, uuid, nullable — Company-location id where services are rendered. Null when unset.
  - `organization_id` string, uuid, nullable — Business entity (organization) this authorization belongs to. Null when unset.
  - `requesting_provider` PriorAuthorizationProvider — Nested provider (credentialing record) in response.
    - `id` string, uuid, required
    - `name` string, required
    - `npi` string, required
    - `tax_id` string, nullable
    - `type` string, required
    - `is_active` boolean, required
    - `location` PriorAuthorizationProviderLocation — Nested location reference inside a credentialing record.
      - `id` string, uuid, required
      - `name` string, required
  - `servicing_provider` PriorAuthorizationProvider — Nested provider (credentialing record) in response.
    - `id` string, uuid, required
    - `name` string, required
    - `npi` string, required
    - `tax_id` string, nullable
    - `type` string, required
    - `is_active` boolean, required
    - `location` PriorAuthorizationProviderLocation — Nested location reference inside a credentialing record.
      - `id` string, uuid, required
      - `name` string, required
  - `servicing_location` PriorAuthorizationServicingLocation — Nested servicing location (full address) in response.
    - `id` string, uuid, required
    - `name` string, required
    - `address` string, required
    - `address_2` string, nullable
    - `city` string, required
    - `state` string, required
    - `zip_code` string, required
  - `created_by_user` PriorAuthorizationUser — Nested user (created_by) in response.
    - `id` string, required
    - `name` string, nullable
    - `email` string, nullable
    - `image` string, nullable
    - `user_type` string, nullable
  - `service` PriorAuthorizationServiceResponse — Service request details returned in the response. See `PriorAuthorizationResultResponse` for the rationale on `validation_alias`.
    - `specialty` 'aba' | 'speech_therapy' | 'occupational_therapy' | 'physical_therapy' | 'mental_behavioral_health' — Clinical specialty the authorization covers.
    - `service_type_codes` string[], nullable
    - `start_date` string, date, nullable
    - `end_date` string, date, nullable
    - `requested_visits` integer, nullable
    - `requested_weeks` integer, nullable
    - `cpt_codes` ServiceCptCode[], nullable
      - `code` string, required — CPT or HCPCS procedure code.
      - `units` string, required — Quantity for this code. Stored as a string because some payors permit non-integer quantities (e.g. `0.5` hours of evaluation).
      - `unit_type` 'units' | 'visits' | 'hours' — Quantity unit a CPT/HCPCS line is measured in. Lives inside the `service_cpt_codes` / `result_cpt_codes` JSON (not a dedicated column), so this is a plain str Enum with no `__pg_type__`. Old rows predate the field — readers default a missing value to `units`. Wire values mirror the Prisma `PriorAuthorizationUnitType` enum (`units` / `visits` / `hours`); keep them in sync by hand (the `...Enum` suffix here intentionally keeps this out of `verify-enum-sync`'s name-matched set, same as the other PA enums).
      - `modifiers` CptModifier[], nullable — CPT/HCPCS modifiers that apply to this code (e.g. `95`, `GT`). Optional — entries created before this field existed omit it and read back as `None`.
    - `locations` PlaceOfService[], nullable
  - `result` PriorAuthorizationResultResponse — Payor decision details. Populated only when `status` is `decided`. Uses `validation_alias` (not `alias`) so the alias only applies to input (reading the parent PA's `result_start_date` etc. columns via `from_attributes`). Output uses the field name; otherwise FastAPI's `response_model_by_alias=True` default would leak the column-prefixed name onto the wire and the frontend would see `resultStartDate` after `transformFromAPI` instead of the expected `startDate`.
    - `start_date` string, date, nullable
    - `end_date` string, date, nullable
    - `approved_visits` integer, nullable
    - `approved_weeks` integer, nullable
    - `cpt_codes` ServiceCptCode[], nullable
      - `code` string, required — CPT or HCPCS procedure code.
      - `units` string, required — Quantity for this code. Stored as a string because some payors permit non-integer quantities (e.g. `0.5` hours of evaluation).
      - `unit_type` 'units' | 'visits' | 'hours' — Quantity unit a CPT/HCPCS line is measured in. Lives inside the `service_cpt_codes` / `result_cpt_codes` JSON (not a dedicated column), so this is a plain str Enum with no `__pg_type__`. Old rows predate the field — readers default a missing value to `units`. Wire values mirror the Prisma `PriorAuthorizationUnitType` enum (`units` / `visits` / `hours`); keep them in sync by hand (the `...Enum` suffix here intentionally keeps this out of `verify-enum-sync`'s name-matched set, same as the other PA enums).
      - `modifiers` CptModifier[], nullable — CPT/HCPCS modifiers that apply to this code (e.g. `95`, `GT`). Optional — entries created before this field existed omit it and read back as `None`.
    - `locations` PlaceOfService[], nullable
    - `authorization_number` string, nullable
    - `cpt_authorization_numbers` object, nullable
    - `reference_number` string, nullable
    - `notes` string, nullable
    - `ai_summary` string, nullable
    - `ai_summary_generated_at` string, date-time, nullable
  - `files` PriorAuthorizationFile[], nullable — Attached files with signed download URLs. Present ONLY on `GET /{id}` with `expand[]=files`; always `null` on the list endpoint (use `file_count` there). Signed URLs are minted only when this is expanded.
    - `id` string, uuid, required
    - `name` string, required
    - `display_name` string, nullable
    - `path` string, required
    - `type` string, nullable
    - `size` integer, nullable
    - `document_type` 'referral' | 'authorization' | 'intake_documents' | 'legal_documents' | 'financial_documents' | 'insurance_card' | 'billing' | 'spam' | 'plan_of_care' | 'diagnosis' | 'medical_records' | 'other' — Document type enum matching Prisma @map values. Bound to PG enum `fax_type`.
    - `metadata` object, nullable
    - `created_at` string, date-time, required
    - `url` string, nullable
  - `file_count` integer, nullable — Number of attached files. Always present (a cheap aggregate); independent of `expand`.
  - `submitted_at` string, date-time, nullable
  - `decided_at` string, date-time, nullable
  - `appeal_submitted_at` string, date-time, nullable — When the appeal was submitted to the payor; set when the appeal first becomes active. Null when no appeal has been submitted.
  - `last_followed_up_at` string, date-time, nullable — Last time staff followed up with the payor on this authorization's status. Null until the first follow-up.
  - `scheduled_submission_date` string, date, nullable — Date this authorization should be submitted to the payor. When set in the future, the request is held out of the active review queue until that date. Null when no scheduled date is set.
  - `completed` boolean — True when the clinic has marked this authorization done (it leaves the default list). Derived from `completed_at`.
  - `completed_at` string, date-time, nullable — When the authorization was marked done. Null while outstanding.
  - `completed_by_user_id` string, nullable — Id of the user who marked it done. Null while outstanding.
  - `completed_by_user` PriorAuthorizationUser — Nested user (created_by) in response.
    - `id` string, required
    - `name` string, nullable
    - `email` string, nullable
    - `image` string, nullable
    - `user_type` string, nullable
  - `cancellation_reason` 'duplicate_already_submitted' | 'no_longer_needed' | 'submitted_directly_to_payor' | 'patient_no_longer_active' | 'entered_in_error' | 'other' — Why a prior authorization was cancelled — captured on every transition into `cancelled`. `other` is the escape hatch (the free-text detail then lives in `cancellation_note`). Keep the members in sync with the Prisma enum `PriorAuthorizationCancellationReason` (apps/frontend/prisma/schema/enums.prisma) and the frontend label map `PRIOR_AUTH_CANCELLATION_REASON_LABELS`. `verify-enum-sync` only compares UPPERCASE Python members, so — like `PriorAuthorizationStatusEnum` — this lowercase enum is NOT covered by that check; sync it by hand.
  - `cancellation_note` string, nullable — Free-text detail captured with the cancellation reason. Null when none was provided.
  - `cancelled_at` string, date-time, nullable — When the authorization was cancelled. Null unless the authorization is cancelled.
  - `active` boolean, required
  - `created_at` string, date-time, required
  - `updated_at` string, date-time, required

## Other responses

- `400` — Validation error
- `401` — Authentication required
- `409` — Conflict — resource already exists
- `422` — Validation Error

---

[API](https://skmtc.net/getsolum/apis/solum-health-api.md) · [All operations](https://skmtc.net/getsolum/apis/solum-health-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/getsolum/solum-health-api/versions/2bf886cdf729/schema)
