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
approvedVisitsrequired
approvedAmountCentsrequired
approvedDaysrequired
episodeDaysrequired

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.payer_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.payer_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