Skip to main content

Authorization workflow and 278 lifecycle UI

Outcome​

A type-aware authorization is created via the UI; a 278 round trip is driven from start to finish; renewals clone correctly; the workflow type (EDI_278 / PORTAL / MANUAL) routes the submit step appropriately.

Prerequisites​

Type-aware authorization form​

FieldUNITVISITDOLLARPER_DIEMEPISODEDATE_RANGE
approvedUnitsrequired—————
approvedVisits—required————
approvedAmountCents——required———
approvedDays———required——
episodeDays————required—

The matrix is enforced both client-side (zod superRefine) and inside AuthorizationService.createAuthorization. Sending a UNIT auth without approvedUnits returns 400 VALIDATION_ERROR.

Concurrent-pool linkage​

The form's Parent picker calls GET /authorizations for APPROVED candidates and GET /authorizations/concurrent-pool?parentId=:id for sibling preview. Inside scrubbing these chains drive findConcurrentPool — the parent is the umbrella auth and children share its quota pool by date.

278 lifecycle from the UI​

The "278 Requests" tab on the authorization detail page lists every auth request for the same (memberId, payerId) and lets the operator spawn a new one. Submit routes by the payer's config.program_config.auth_workflow:

WorkflowSubmit outcomeUI action
EDI_278Generate 278 X12, status → SUBMITTED"View X12 278 payload" preview
PORTALStatus → MANUAL_PENDING, no x12"Open Portal" deep-link + "Record Response"
MANUALStatus → MANUAL_PENDING, no x12"Record Response" only

The Record 278 Response dialog accepts a pasted 278 X12 payload. On a positive determination (A1/A4 HCR action codes), the backend materializes a service.service_authorization row with source = 'EDI_278', the HCR02 certification number as authorization_number, and the type derived from the HSD qualifier.

Renewal flow​

POST /authorizations/:id/renew clones the source row with the posted dates and a fresh authorizationNumber, copies type-specific approved counters and procedures, and stamps source = 'MANUAL' so renewal-origin auths are distinguishable from EDI_278-materialized ones.

Renewal is rejected (400) when:

  • Source status is not APPROVED.
  • effectiveFrom > effectiveTo.
  • The new range overlaps the source range (any day-overlap).

Steps — full lifecycle​

  1. Create the authorization via Eligibility → Authorizations → New. Pick the type; the form shows only the relevant approved-quantity field.

  2. Spawn a 278 request from the detail page's 278 Requests tab. Submit; the workflow routes appropriately.

  3. Record the response (PORTAL/MANUAL) or wait for AuthRequestConsumer to record it (EDI_278). Confirm service.service_authorization row appears with the right source.

  4. Renew via the action strip when the auth is approaching effectiveTo. Pick new dates and a new authorization number.

Quick reference​

# Inspect the resolved workflow for a payer
psql -c "SELECT auth_workflow, auth_portal_url
FROM config.program_config
WHERE payer_id = '<PAYER_UUID>'
ORDER BY effective_from DESC LIMIT 1;"

# List active 278 requests for a member
curl -H "Authorization: Bearer $TOKEN" \
"$API/api/v1/eligibility/auth-requests?memberId=<MEMBER>&status=SUBMITTED"

# Trigger a renewal
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H 'content-type: application/json' \
-d '{"authorizationNumber":"AUTH-NEW","effectiveFrom":"2026-07-01","effectiveTo":"2026-12-31"}' \
"$API/api/v1/eligibility/authorizations/<AUTH>/renew"

Validation​

CheckExpected
authorization rowcreated with the right type counter populated
authorization_request rowstatus reflects the workflow outcome
service_authorization rowcreated on positive determination, with source matching origin
Renewalnew row with source='MANUAL', no overlap with source

Pitfalls​

  • The submit route does not push to the clearinghouse. It generates the X12 and flips the request to SUBMITTED. Real production flow continues to enqueue auth.request_queued and let AuthRequestConsumer handle outbound routing via submission_routing_rule. The UI submit path is intended for stub-payer scenarios and operator-driven workflows (PORTAL / MANUAL).
  • parentAuthorizationId chains are limited to one level. Parent of parent is rejected by assertValidParent. The concurrent-pool route only shows top-level approved auths.
  • Renewal copies procedures verbatim. If the renewed date range crosses a fee-schedule effective-from boundary, CodeResolver picks the new tier — but the procedure list itself is not re-derived from the payer's current contract. Operators who need to re-discover the contract set should issue a new auth via the create form rather than a renewal.
  • Renewals use source='MANUAL'. Don't confuse them with EDI_278 rows that come out of recordResponse.

Cross-references​

Next​

3.1 — Diagnose a stuck claim