Endpoints — Appeals

← Back to Platform Architecture

Endpoints — Appeals

Appeal lifecycle management endpoints for creating, validating, and submitting appeals.

POST /api/appeals

Create a new appeal (Draft status). Authentication: Required Authorization: Any authenticated user PHI Validation: Request body scanned for PHI; rejected with 422 if found

Request Body

{
  "denial_id": "denial-uuid",
  "payer_id": "tenant-uuid",
  "denial_code": "FREQ_LIMIT",
  "narrative": "Patient with GAF score 35 demonstrates significant functional impairment requiring continued IOP-level care. Clinical deterioration imminent without intensive monitoring.",
  "evidence_elements": {
    "clinical_notes": true,
    "psychiatric_evaluation": true,
    "gaf_assessment": true,
    "functional_impact_statement": false
  },
  "selected_precedent_ids": ["prec-uuid-1", "prec-uuid-2"],
  "notes": "Internal notes about appeal strategy"
}

Response (201 Created)

{
  "id": "appeal-uuid",
  "tenant_id": "tenant-uuid",
  "denial_id": "denial-uuid",
  "payer_id": "tenant-uuid",
  "denial_code": "FREQ_LIMIT",
  "status": "Draft",
  "narrative": "...",
  "evidence_elements": { ... },
  "selected_precedent_ids": [ ... ],
  "validation_status": "pending",
  "created_by": "user-uuid",
  "created_at": "2024-04-14T10:30:00Z",
  "updated_at": "2024-04-14T10:30:00Z"
}

Errors

400 Bad Request — Invalid request schema 422 Unprocessable Entity — PHI detected

GET /api/appeals

List appeals with pagination and filtering. Authentication: Required Authorization: Any authenticated user

Query Parameters

ParameterTypeDefaultExample
limitinteger2050
offsetinteger0100
statusstring(none)Draft, Submitted, Under Review, Approved, Denied, Withdrawn
payer_idstring(none)tenant-uuid
denial_codestring(none)FREQ_LIMIT
created_afterdate(none)2024-04-01
created_beforedate(none)2024-12-31

Response (200 OK)

{
  "data": [
    {
      "id": "appeal-uuid",
      "status": "Draft",
      "denial_code": "FREQ_LIMIT",
      "payer_id": "tenant-uuid",
      "narrative_preview": "Patient with GAF score 35...",
      "created_at": "2024-04-14T10:30:00Z",
      "updated_at": "2024-04-14T10:30:00Z"
    }
  ],
  "total": 45,
  "limit": 20,
  "offset": 0,
  "has_more": true
}

GET /api/appeals/:id

Retrieve a single appeal. Authentication: Required Authorization: Any authenticated user (tenant-filtered)

Response (200 OK)

Full appeal object with all fields (same structure as POST response).

Errors

404 Not Found — Appeal doesn't exist

PUT /api/appeals/:id/save

Save appeal draft (creates version snapshot without submitting). Authentication: Required Authorization: Any authenticated user PHI Validation: Request body scanned

Request Body

Partial or full appeal update:
{
  "narrative": "Updated narrative with more clinical detail...",
  "evidence_elements": { ... },
  "selected_precedent_ids": [ ... ]
}

Response (200 OK)

Returns updated appeal with version_number incremented.

Behavior

  • Version Snapshot — Current state saved to appeal_versions table
  • Updateappeals row updated
  • Status Unchanged — Remains "Draft"
  • Audit Log — Event logged as "saved_draft"

  • POST /api/appeals/:id/validate

    Run quality gate validation without submitting. Authentication: Required Authorization: Any authenticated user

    Request Body

    (Optional) Full appeal object to validate, if not using saved version:

    {
      "narrative": "...",
      "evidence_elements": { ... },
      "selected_precedent_ids": [ ... ]
    }

    Response (200 OK)

    Validation result:
    {
      "status": "warnings",
      "checks_passed": [
        "has_narrative",
        "has_precedents",
        "valid_precedents"
      ],
      "warnings": [
        {
          "check": "narrative_length",
          "message": "Narrative seems short (50+ words recommended)",
          "guidance": "Expand with clinical detail: GAF score, functional impact, evidence integration"
        },
        {
          "check": "precedent_relevance",
          "message": "Some precedents are for different denials (Cigna vs. UHC). Verify relevance.",
          "guidance": "Appeals are strongest when precedents are for same payer/denial type"
        }
      ],
      "errors": []
    }

    Possible Validation Statuses