Public API
The contract repository owns public API schemas, generated clients, and handoff checks.
- Contract tests are colocated and use
*_testsuffix. - Generated clients are consumed through approved wrappers.
- Backend and frontend do not invent parallel API shapes.
- Source status codes must be named and mapped in contract types.
- Document contracts use lower_snake_case
definitionKey,templateKey, repeat section keys, and idempotentrenderRequestCode. - Promotion entitlement contracts expose lower_snake_case entitlement codes; source coupon product codes map only at the boundary.
- Customer engagement contracts expose Strapi only as the CMS provider and
collection names. App-facing vocabulary is
contentPublication,campaignPlacement,customerInquiry,memberNotification, andmotherLeadRequest. - Communication delivery contracts expose Novu only as the workflow provider.
App-facing vocabulary is
communicationWorkflowRule,communicationPreference,communicationDispatchRequest, and source notification names map only at the boundary. - Reservation birth-information contracts expose
ReservationBirthProfile,ReservationBirthChildRecord, andBirthInformationReminderTask. Child records are arrays with contiguous sequence values, not fixed child slots. The reminder workflow code isreservation:birth_information_requested. - Reservation booking workflow contracts expose
ReservationBookingWorkflowStartInput,ReservationBookingWorkflowStartResponse, workflow enginerestate, and lower-case workflow statuses.POST /reservation-booking-workflow-startsis implemented by the backend FastAPI boundary and returns202 Acceptedwhen Restate accepts the command. The stable key usesreservationBookingRequestIdfirst, thenmotherProfile.memberIdplusscheduleStartas the fallback. The input payload is a workflow context snapshot:motherProfile,branchContext,branchActor,caregiverCandidates,caregiverProfiles, andcareEnvironment. Matching candidate snapshots includeacceptsPetHouseholdandpetAllergySpeciesCodesso requested-caregiver and smart-matching paths use the same policy facts. Python Pydantic contracts keepBaseModelinheritance atSanmopiaContractModelonly; booking payloads derive through semantic intermediate models such asReservationBookingMotherIdentitySnapshot,ReservationBookingBranchSnapshot,ReservationBookingActorSnapshot,ReservationBookingCareEnvironmentSnapshot,ReservationBookingCaregiverMatchingSnapshot,ReservationBookingCaregiverProfessionalSnapshot,MotherBookingCatalogOption, andReservationBookingWorkflowEnvelope. It must not reintroduce flat source-era fields such asmemberId,branchId,actorRole,reservationStart, orcandidateCaregiverIdsat the top level. Frontend and backend must not create parallel workflow response shapes. Portal workflow progress reads usereservationBookingWorkflowStatusProjectionPath()and the shared auth-scopedWorkflowStatusProjection; the older/reservation-booking-workflow-requests/{reservationBookingRequestId}row reader requires the same Supabase bearer auth when exposed by the composed backend app, and must not drive actor command rendering.branchActor.actorUserIdis the single Supabase Auth-aligned authenticated user identity for request submission authorization, workflow projections, and domain actor models.branchActor.rolecarries the branch organization domain role label such as지점 운영자;branch_operatorremains only the technical actor kind or SpiceDB relation name. Raw workflow keys stay internal to Restate/Supabase ledger rows. Starting the workflow requires thesubmit_booking_requestcapability at draft stage and branchmanagepermission in SpiceDB. Permission failure returns403; missing workflow runtime wiring returns503instead of silently falling back to an in-process mock. - Mother booking frontend requires a backend-provided booking operational
context before it can build that workflow input. The context contains the
authenticated mother profile, branch context, branch actor, caregiver
candidates/profiles, care environment, service options with pricing
identifiers and frozen amount hints, and payment method options. Frontend
production code must fail closed when this context is absent; test fixtures
are the only place allowed to hold sample branch/caregiver/price/environment
values.
GET /mother-booking-operational-contextrequires a Supabase bearer token and reads the versioned Supabase read model for that mother. Missing bearer returns401, no current context returns404, and missing backend wiring returns503. The response is a frozen booking UX context, not a place to recalculate price or caregiver policy after the fact. - Service-calendar compatibility contracts expose
POST /service-calendar-compatibility-decisionsfor historical reservation calendar decisions. The request sends a frozenplannedServiceCalendarsnapshot, optionalbranchProfileId, optionalsourceServiceEndOn, and optionalsourceReference; backend derives the actor from Supabase Auth and checks branchviewpermission when a branch profile is scoped. The response uses named decisionsuse_current_policy,preserve_source_service_end, orrequire_operator_reviewwithpolicyFingerprint,plannedServiceEndOn, optionalsourceServiceEndOn,reasonCode, and optional source reference. Clients must useserviceCalendarCompatibilityDecisionsPath()andserviceCalendarCompatibilityDecisionRequestHeaders()and must not reimplement legacy 1-week/2-week/weekend/holiday drift logic in UI code. Stored impact projections are read throughGET /reservation-service-calendar-impacts/{reservationBookingId}with optionalplanCodeandimpactKindfilters. The response includes the persistedcompatibilityDecisionbeside impact facts, so pricing, report, caregiver scheduling, settlement, and refund consumers read the same frozen policy evidence instead of recalculating duration drift locally. Clients must usereservationServiceCalendarImpactsPath()andreservationServiceCalendarImpactRequestHeaders(). - Reservation financial lifecycle contracts expose
GET /reservation-financial-lifecycles/{reservationBookingId}/mother-visible-charge-summaryfor finalized mother-facing charge display. The response uses the frozenMotherVisibleChargeSummarysnapshot and never recalculates from later caregiver payout, branch settlement, or HQ settlement changes. Unfinalized charge summaries return404; missing read-model wiring returns503. - Operator reservation detail contracts expose
POST /operator-financial-mutation-lock-decisions/{reservationId}for branch/HQ financial edit previews. The request carriesbranchActor,reservationStatus,serviceEndOn,evaluatedAt, and optionalrequestedFields; it does not acceptactorKind. Backend derivesactorKindfrom the authenticated branch/HQ actor context, checks the Supabase bearer token againstbranchActor.actorUserId, and returns field-level lock payloads withpolicyVersionLabel,reasonCode,messageKey,requiredCapabilities, andsourceAnchor. Portal clients must render these lock facts and must not recreate sourcecantSaveor date/status branching in UI code. Mutation commands still need expected-revision re-checks before writing reservation or payment facts. - Branch operations contracts expose
BranchSettlementAccount,SnapshotBranchSettlementAccountForStatementCommand, andBranchSettlementAccountSnapshotshapes. Account purpose is business-specific (statement_remittance,branch_deposit,membership_fee,refund), raw account numbers are forbidden, and statement snapshot commands freeze account revision, actor, and idempotency key before settlement documents read the account. Backend persistence now stores current purpose-scoped branch accounts and profile revisions through Supabase service-role tables.POST /branch-settlement-account-statement-snapshotspersists immutable statement-account evidence, derives the actor from Supabase Auth, and rejects stale account revisions. The contract repo exposes the same API through OpenAPI, JSON Schema, and TS helpersbranchSettlementAccountStatementSnapshotsPath()andbranchSettlementAccountStatementSnapshotRequestHeaders().POST /branch-office-profile-updatesrevises editable profile facts with Supabase Auth-derived actor id, branchmanagepermission, expected revision, command id, revision id, reason, and server effective timestamp. Stale saves return409and clients must build the command endpoint throughbranchOfficeProfileUpdatesPath()andbranchOfficeProfileUpdateRequestHeaders().POST /branch-office-lifecycle-changesmoves branch office lifecycle throughonboarding,active,suspended, andclosedusing the same actor, branchmanagepermission, expected revision, command id, revision id, reason, and server effective timestamp. Clients must usebranchOfficeLifecycleChangesPath()andbranchOfficeLifecycleChangeRequestHeaders(), not source delete flags or inline status constants.POST /branch-settlement-account-replacementsreplaces one purpose-scoped settlement account with masked-only account facts, expected revision, command id, revision id, reason, and server recorded timestamp. Clients must usebranchSettlementAccountReplacementsPath()andbranchSettlementAccountReplacementRequestHeaders(); raw account numbers are not part of the public contract.POST /branch-service-area-policy-revisionspublishes the full revisioned branch coverage policy from backend-owned rule drafts. Rules carry semanticpolicyKindvalues (available,consultation_only,unavailable), address depth from populatedsido/sigungu/bname, effective windows, and the Supabase Auth actor captured through branchmanagepermission.POST /branch-service-area-policy-decisionsresolves one service date and address into a frozen coverage decision with Daum/Kakao/operator evidence, matched rule id, revision number, address depth, and decision code. Clients must usebranchServiceAreaPolicyRevisionsPath(),branchServiceAreaPolicyRevisionRequestHeaders(),branchServiceAreaPolicyDecisionsPath(), andbranchServiceAreaPolicyDecisionRequestHeaders()instead of UI-sideAREA_ACCEPT_TYPE_ID_PKor address-depth branching. Remaining branch profile mutation clients for membership fee, credentials, and assets stay explicit follow-up work. - Family-account authority contracts expose
POST /family-reservation-payment-authorizations, andPOST /family-reservation-care-history-access-decisions. The care-history decision request contains onlyfamilyAccountId,reservationBookingId, andscope; it accepts no mother or grantee identity. Backend derives the acting member from the Supabase profile and the account mother from persisted family authority, rejects withdrawn sessions, and returns the activeReservationCareHistoryAccessGrantsnapshot. Clients must usefamilyReservationPaymentAuthorizationsPath(),familyReservationCareHistoryAccessDecisionsPath(), andfamilyAccountAuthorityRequestHeaders(). UI contact fields such as emergency contact, relationship text, or payment-notice phone numbers are contact evidence only, not authority facts. - Reservation care-history lifecycle contracts expose
POST /family-accounts/{familyAccountId}/reservation-care-history-access-grantsandPOST /family-accounts/{familyAccountId}/reservation-care-history-access-grants/{reservationCareHistoryAccessGrantId}/revocations. Grant accepts grantee, booking, scopes, expiration, and idempotency; revoke accepts expected revision, reason, and idempotency. Both derive the mother actor from authentication. Clients must usereservationCareHistoryAccessGrantsPath()andreservationCareHistoryAccessGrantRevocationsPath(). A read grant never authorizes daily-report review or caregiver rating mutation. - Caregiver compensation contracts expose
CaregiverPayoutAcknowledgementCommandandCaregiverPayoutAcknowledgementReadModelso branch deposit state and caregiver receipt state are backend-owned facts with actor, expected revision, idempotency key, and replay guard. Public API routes now includePOST /caregiver-payout-acknowledgements/branch-deposits,GET /caregiver-payout-receipt-states/{reservationBookingId}/{caregiverPayoutInstructionId},POST /caregiver-payout-receipt-states/acknowledgements,POST /caregiver-payout-receipt-states/exceptions, andPOST /caregiver-payout-receipt-states/repairs. Frontend must not finish payout or reservation completion from editable UI amount fields. - Reservation payment workflow contracts expose
POST /reservation-payment-pre-registrationsfor Kill Bill REST amount pre-registration before payment UI entry. The request carriesreservationBookingId,paymentId,paymentMethod,paymentPurpose, andamountKrw; the response returnspreRegistrationStatus, optional gateway code/message, and the frozen payment facts. A reusedpaymentIdis accepted only when the waiting local payment record matches the same reservation, method, purpose, and amount. Reservation payment records persistpayment_purposefrom the ubiquitous purpose enum and setdeposited_atwhen Kill Bill verification or a direct booking write moves the local record into a paid status. - Payment product-plan catalog contracts expose
GET /payment-product-plansandGET /payment-product-plans/{planCode}behind Supabase bearer auth. The catalog is derived from active/effective Supabasesanmopia_payment_product_plan_catalog_itemsrows and returns stable plan codes, product family, allowed payment methods, ledger obligation purposes, provider routing key, settlement participation, realization timing, fee basis, refund policy, conversion policy, and virtual-account expiration policy. Frontend payment flows must select and display these backend facts; they must not derive product meaning from source payment type ids, payment purpose alone, or hardcoded UI amounts. - Operator manual reservation payment receipt contracts expose
POST /reservation-payment-receiptsfor protected service-balance and customer-share-balance receipt recording. The request carriesreservationBookingId,paymentId,paymentMethod,paymentPurpose,amountKrw,depositedAt,expectedPaymentRevision, andidempotencyKey; the response returns those same frozen payment facts pluspaymentFactRevisionandrecordedAt. This command creates a new manual receipt fact at revision0only. Existing payment fact changes must use the operator payment-fact edit command so stale screens cannot overwrite paid, refunded, or settlement-bound rows. - Reservation payment workflow contracts expose
POST /reservation-payment-workflow-startsandGET /reservation-payment-workflow-requests/{paymentWorkflowRequestId}. Progress responses include gateway result, approved charge finalization status, finalized charge snapshot id, and settlement continuation status.settlementContinuationStatus = waiting_for_financial_factsmeans payment closeout is done but the next financial lifecycle workflow is waiting for service-delivery, payout, branch, or HQ ledger facts; clients must poll the workflow status projection instead of calling Restate directly. - Reservation service-offering availability contracts expose
POST /reservation-service-offering-availability-decisionsbehind Supabase bearer auth. The request carries candidate offering, evaluation context, optional shutdown windows, and policy revision; the response returns backend availability state, handoff kind, unavailable reason codes, message keys, and source evidence keys. Real reservation screens should callPOST /reservation-service-offering-availability-decision-sets, which reads effective service-offering candidates and shutdown windows from Supabase care service catalog offerings and policy attachments before returning the decision set. Astro reservation cards may render these decisions, but must not decide pre-reservation windows, voucher direct-service blocking, in-home exclusion, continuation routing, or year-boundary shutdown copy from PHP/JS constants. - Reservation cancellation refund contracts expose
POST /reservation-cancellation-refunds. The request carriespaymentChangeAdjustmentIdonly as a durable link to a paid change-payment adjustment; the backend still derives refundable balance from the payment ledger, quotes refund deductions from the active adjustment catalog, and returns frozen refund lines plus the linked adjustment id. Clients must not send UI-calculated paid/refund totals. - Internal provider refund repair contracts expose
POST /internal/payment-refund-repairs/provider-refund-plansfor provider-success/local-write-failure repair planning andPOST /internal/payment-refund-repairs/provider-refund-executionsfor audited Kill Bill refund execution attempts. Both routes areSANMOPIA_INTERNAL_JOB_TOKENgated. Planning accepts backend-ownedPaymentLedger,PaymentRefundIntent, adjustment catalog, approved repair case, provider lookup, and SpiceDB-derivedProviderRefundRepairPermission, then persistsPaymentRefundRepairPlan. Execution accepts the persisted plan identity, refund amount, settlement invalidation key, idempotency key, and evidence keys. The handler first looks up an existing execution attempt by idempotency key; a matching attempt is replayed into the ledger-backed provider-result recorder without calling the billing gateway again, while a mismatched replay is rejected. New attempts call the configured billing gateway and persist the execution result before recording accepted or rejected repair results. Refund amount and paid-row revision still come from backend ledgers. Public clients must not call these routes or send raw providerordr_idxx/tnorefund commands. External webhook E2E proof, retry backoff and operator result-history projection, and downstream reporting/artifact invalidation proof still belong to backend workers and provider-result handlers. - Payment-change adjustment contracts expose
POST /reservation-payment-change-adjustments,POST /reservation-payment-change-adjustments/{reservationBookingId}/mother-payment-pre-registrations,POST /reservation-payment-change-adjustments/{reservationBookingId}/mother-payment-verifications,POST /reservation-payment-change-adjustments/{reservationBookingId}/mother-payments,POST /reservation-payment-change-adjustments/{reservationBookingId}/zero-payable-closeouts,GET /reservation-payment-change-operator-board,GET /reservation-payment-change-adjustments/{paymentChangeAdjustmentId}/settlement-continuation-workflow-status,POST /reservation-payment-change-adjustments/{paymentChangeAdjustmentId}/operator-completions, andPOST /reservation-payment-change-adjustments/{paymentChangeAdjustmentId}/operator-amount-corrections. These endpoints requireAuthorization: Bearer <Supabase access token>. Operators need booking-scoped SpiceDB permission to request, complete, or audit-correct an adjustment; mother payment/pre-registration/verification and zero-payable closeout require the authenticated Supabase user id to matchmotherUserId. Zero-payable closeout usesPaymentChangeAdjustmentZeroPayableCloseoutPayloadwith a client idempotency key, but amount/payment receipt authority stays backend-owned aszero_payable_closeout. Completion and amount-correction commands write append-onlyPaymentChangeOperatorAuditfacts instead of rewriting paid totals. Amount-correction requests must carryexpectedAdjustmentUpdatedAtcopied from the operator-board row; stale submissions return conflict instead of appending audit (f9ce5dc,05059a5). Operator-board rows now enrich paid/completed adjustments withreservationId,branchProfileId,motherDisplayName, andreservationChargeAmountKrwfrom Supabase reservation/member profile read tables while preserving technical ids for authorization and durable links. Rows also expose nullable payment milestone factscustomerShareDepositPaidAt,customerShareBalancePaidAt,serviceBalancePaidAt, andpreReservationDepositPaidAtfromsanmopia_payment_records.payment_purposeplusdeposited_atwhen those facts exist. Each operator-board row also exposesmanualPaymentReceiptCommandDraftwith backend-owned command availability, disabled reason, command draft id, booking id, payment id, canonical payment method, payment purpose, amount, deposited-at time, and idempotency key so clients do not infer receipt defaults from labels, row status, or UI-side amount/date arithmetic. Backend proof:4bd81e1,455f74a; TypeScript contract proof:858fa24,87a6e61. Adjustment and operator-board responses include nullablesettlementContinuationStatus,settlementContinuationWorkflowRequestId,settlementContinuationReason, andsettlementContinuationRecordedAtfields after paid adjustment settlement continuation is requested. The adjustment-id workflow-status endpoint maps a paid adjustment to its sharedreservation_financial_lifecycleprojection, so operator screens can poll progress without calling Restate or guessing a workflow key. Clients must build paths and the bearer header with the exported TypeScript helpers, includingpaymentChangeAdjustmentRequestHeaders(), and must not readsanmopia_payment_change_adjustmentsorsanmopia_payment_change_operator_auditsdirectly from the Supabase Data API. - Reservation financial lifecycle workflow contracts expose
POST /reservation-financial-lifecycle-workflow-startsfor Restate-backed downstream finance closeout. The request carriesfinancialLifecycleWorkflowRequestId,reservationBookingId, optional service-delivery facts, optional caregiver/branch/HQ ledger-line groups, andcompleteSettlement. The response returns workflow nameReservationFinancialLifecycleWorkflow, workflow enginerestate, stable workflow key, invocation id, and accepted status. - Caregiver compensation contracts represent each caregiver through a
contractAssignmentKey, separate from handoff order. Quote lines must carryrateRuleId,policyVersionLabel,rateEffectiveFrom, and optionalrateEffectiveUntilso frontend, backend, and Supabase read the frozen payout basis instead of recalculating against later grade-rate policies. Quote inputs userateEffectiveOnwhen more than one grade/role rate line exists; the backend rejects ambiguous versioned rates instead of guessing current policy. - Daily care report contracts separate caregiver-authored
DailyCareReportSubmissionfrom customer-authored review facts.CustomerDailyReportReviewcarries the reviewed source report code, optionalCaregiverServiceRating, and optionalCustomerDailyReportReviewRewardGrant, so final-day rating and reward-point issuance do not hide inside printable document rendering. Authenticated customer routes expose readiness and submission, and the backend records aDailyReportCompletionRewardLedgerInstructionfor reward fulfillment instead of leaving coupon/point side effects to frontend state. Reward lines now move through a Supabase PGMQ worker contract with dispatch status on each line; the worker records idempotent service-role-only fulfillment facts, while the authenticated customer projectionGET /customer-daily-report-reviews/{reservation_booking_id}/reward-statusexposes applied and missing reward components from those facts. The external shopping-mall/coupon/point connector remains a separate contract. - Reservation document delivery contracts separate rendered document artifacts
from recipient access and notification attempts.
ReservationDocumentDeliveryownsDocumentAccessGrant,DocumentRecipientNotification, andDocumentDeliveryAttemptfacts with explicit grant state, trigger, channel, retry timestamp, and message template. Clients must not infer access from a render artifact alone. - Reservation change-request contracts expose
ReservationChangeRequest,ReservationChangeApplicationPlan,ReservationChangeEffect, andReservationChangeOperatorAudit. Change intake describes requested facts; accepted application plans describe effects on schedule, payment, caregiver assignment, compensation, mother-visible summary, and branch settlement. Clients must not directly mutate assignment or settlement rows from a request payload. - Reservation authorization contracts expose
ReservationCapabilityAuthorizationSnapshot. Backend snapshots combine reservation-stage capability policy with SpiceDB relationship checks and return allowed/denied capabilities with stage and relationship decision reasons. Frontend may usereservationStageCapabilityDecisiononly as a stage-only pre-render helper; relationship authorization remains backend-owned. - Reservation operation command contracts expose backend-decided command boards
and applied operation plans. Accepted command responses may include
followUpWorkflowRequestIdwhen the plan starts asynchronous follow-up work. Clients must display the operation plan and pollWorkflowStatusProjectionkindreservation_operation_follow_up; they must not call Restate or service-role Supabase workflow tables directly. - Reservation collaboration contracts expose
POST /reservation-collaboration-workspaces/{reservationId},POST /reservation-collaboration-workspace-events/{reservationId},POST /reservation-collaboration-journal/{reservationId}, andPOST /reservation-collaboration-commits/{reservationId}. Workspace open returnscurrentRevision,realtimeTopic,currentValuesByField,latestJournalEntry,coordinationPolicy, anddraftSession. ThedraftSessionincludesbaseRevision,latestKnownRevision,status,openedAt,lastSeenAt, anddirtySinceso clients can separate local draft state from newer server revisions. Workspace-event requests recordnavigation_blocked,draft_marked_dirty,draft_recovered,draft_discarded,commit_conflicted, andworkspace_closedwithout pretending those UX events are reservation fact mutations. Commit requests requirebranchContext,branchActor,actorKind,actorProfileId,expectedRevision,idempotencyKey,sourceWorkspaceId,mutationKinds, and lower_snake dot-separatedchangeSetfield paths.branchActor.roleis the organization role label such as지점 운영자;branch_operatorremains the technicalactorKind. Accepted commits return201with committed revision, audit event id, realtime projection event, and navigation intent. Stale saves return409withcurrentRevision,conflictingFields, andrefreshRequired; this includes races where the revision changes between the workspace read and the Supabase RPC commit. Frontend clients must use the exported TypeScript helpers for paths, bearer headers, idempotency keys, realtime event name, and validation; handwritten collaboration fetch shapes are not allowed. - Workflow status projection contracts expose
GET /workflow-status-projections/{workflowKind}/{workflowRequestId}for portal polling across reservation booking, reservation operation follow-up, payment, financial lifecycle, member privacy, and branch settlement reconciliation export workflows. The endpoint requires a Supabase bearer token and returns401for missing tokens,403for denied SpiceDB or ownership checks,404for unknown projections, and503for missing backend wiring. Reservation booking projections includereservationStatusand, when the authenticated actor can be mapped tomother,caregiver,branch_operator, orhq_admin, areservationCapabilityAuthorizationsnapshot. Frontend clients must prefer that backend snapshot over local stage-only helpers for rendered actions. Clients build the header throughworkflowStatusProjectionRequestHeadersand must not call Restate APIs directly. - Branch settlement reconciliation exports expose backend-owned
settlementDataRoomReadinessinsideGET /branch-settlement-reconciliation-exports/{branchProfileId}. The projection carriescollectionCode,collection,readinessStatus, nullablesettlementPeriodStartandsettlementPeriodEnd, branch/external recipient scope, source/projection/expected revisions,rowCount,sourceEvidenceKeys,blockingFacts, andupdatedAt. Empty exports must report null period coverage instead of fake dates. Frontend clients must use that projection and the shared contract validator;contract_gapis allowed only during staged rollout when the field is absent. - Settlement data-room contracts expose
POST /settlement-data-room-export-requests,GET /settlement-data-room-requests/{settlementDataRoomRequestId},POST /settlement-data-room-requests/{settlementDataRoomRequestId}/repair-requests, andPOST /settlement-data-room-requests/{settlementDataRoomRequestId}/download-handoffs. Internal workflow contracts exposePOST /settlement-data-room-requests/{settlementDataRoomRequestId}/buildsandPOST /settlement-data-room-requests/{settlementDataRoomRequestId}/ready-artifacts.SettlementDataRoomCollectionseparatesexternal_counterparty_settlement,branch_to_headquarters_settlement,headquarters_settlement, andinter_office_settlement; external-counterparty requests requireexternalRecipientCode. Request payloads carryscope,sourceDatasetRevision,sourceEvidenceKeys,revision, immutable artifacts, and append-onlyactionJournal. Ready requests require an active artifact; repair creates a new request action and supersedes old artifacts instead of mutating or deleting files. Download handoff responses return a short-lived signed URL and committed revision without exposing storage bucket or object key. Clients must usesettlementDataRoomRequestPath,settlementDataRoomBuildsPath,settlementDataRoomReadyArtifactsPath,settlementDataRoomRepairRequestsPath,settlementDataRoomDownloadHandoffsPath,settlementDataRoomExportRequestsPath, andsettlementDataRoomRequestHeaders; hidden iframe download flows are not part of the modern contract. Operator workspace contracts additionally exposeGET /settlement-data-room-workspaces/{workspaceCode}?collection=...,POST /settlement-data-room-workspaces/{workspaceCode}/artifact-requests,POST /settlement-data-room-workspaces/{workspaceCode}/repair-requests,POST /settlement-data-room-workspaces/{workspaceCode}/grant-handoffs, andPOST /settlement-data-room-workspaces/{workspaceCode}/return-state. These endpoints returnSettlementWorkspacePayloadplus the activeBulkExportTemplatePolicyPayload, require Supabase bearer auth, derive the settlement data-room actor profile from backend-owned member profiles, and authorize branch/HQ/workflow scope through SpiceDB. Workspace grant revocation is backend-owned: artifact grants exposerevokedAt,revokedByRepairRequestCode, andrevokedReason; repair requests exposerevokedGrantIdsandreplacementArtifactRequestCodeso clients can show stale download refusal and reissue lineage without recalculating it in UI. Workspace collections areexternal_counterparty_settlement,branch_to_headquarters_settlement,headquarters_settlement, andinter_office_settlement; clients must not render or mutate sourcedataType, board id, or numeric status ids. Runtime persistence lives in service-role-owned Supabase tablessanmopia_settlement_data_room_workspacesandsanmopia_settlement_data_room_template_policieswith explicit grants, RLS, JSONB aggregate snapshots, and queryable scope/revision columns. - Settlement statement contracts expose
GET /settlement-statements/{settlementStatementId},POST /settlement-deposit-requests,POST /settlement-branch-deposit-acknowledgements,POST /settlement-headquarters-settlement-approvals, andPOST /settlement-arrears-deposit-requests. The statement contract separatesmessageToBranchfromheadOfficePrivateMemo, freezesSettlementRemittanceAccountSnapshot, and recordsSettlementTransitionAuditwith before/after status, expected revision, committed revision, actor, and idempotency key. Branch manager acknowledgement includesSettlementStatementLineAcknowledgement[]so each settlement line can be accepted or disputed without hiding missing fees in one boolean; each acknowledgement can carrysourceEvidenceKeyso legacy form evidence remains traceable without leaking source-era booleans into domain commands. Headquarters administrator approval is a separateApproveHeadquartersSettlementcommand that moves the statement tosettledorarrears. Branch clients must treatheadOfficePrivateMemoas forbidden data; generated-client validators flag branch-visible statements that include it. - Reservation external-counterparty settlement status contracts expose
GET /reservation-external-counterparty-settlement-statuses/{reservationId}withbranchProfileIdquery scope. The response isReservationExternalCounterpartySettlementStatus, a reservation-scoped projection that replaces sourceDANBEE_STATUS_FLwithcompletionState,settlementStatementId,settlementStatus,datasetRevision,lineageEvidenceKeys, andupdatedAt. The route requires a Supabase bearer token and branchsettlepermission through SpiceDB; clients build path, header, and validation throughreservationExternalCounterpartySettlementStatusPath,reservationExternalCounterpartySettlementStatusRequestHeaders, andfindReservationExternalCounterpartySettlementStatusProblems. Internal settlement workflows update that projection throughPOST /internal/reservation-external-counterparty-settlement-status-updatesusingAuthorization: Bearer ${SANMOPIA_INTERNAL_JOB_TOKEN}. Payloads include reservation id, branch id, settlement statement id, settlement status, dataset revision, lineage evidence keys, and update timestamp. The backend rejects stale dataset revisions so a finished external-counterparty status is not overwritten by an older statement event. Portal clients must not call the internal updater. - Customer action availability contracts expose
GET /customer-reservation-action-availabilities/{reservationId}andGET /customer-new-reservation-eligibility. Both require a Supabase bearer token and derivecustomerIdfrom the authenticated user, not from request body fields. The backend readssanmopia_customer_reservation_action_source_states,sanmopia_customer_reservation_state_mapping_catalogs, andsanmopia_customer_action_policy_rule_catalogsto project legacy source status into current lifecycle language, action availability, command target, disabled reason, idempotency scope, and new-reservation blocking. Portal clients must render these results and must not branch on raw status numbers. - Internal scheduled-job contracts expose
POST /internal/member-privacy-purge-workflow-triggersfor trusted runtime jobs that hand due privacy purge tasks to Restate. The route requiresAuthorization: Bearer ${SANMOPIA_INTERNAL_JOB_TOKEN}and is not a portal client API. Supabase Cron calls this route throughpg_net; stage setup runspnpm supabase:cron:configureso backend URL and token stay in env-derived database settings instead of SQL literals. - Already-issued Supabase access tokens after member withdrawal are not treated
as active Sanmopia sessions. Backend APIs reject current Auth users whose
app metadata has
sanmopia_privacy_status=withdrawn, and Supabase RLS adds a restrictiveprivate.sanmopia_current_member_session_is_active()guard across Sanmopia Data API tables. - Branch settlement reconciliation export workflow repair contracts expose
POST /branch-settlement-reconciliation-export-workflow-retries/{workflowRequestId}andPOST /branch-settlement-reconciliation-export-workflow-cancellations/{workflowRequestId}. Retry is allowed only afterfailedorcancelled, reuses the frozen snapshot/workflow key, and returns202; cancellation rejects completed workflows and returns the cancelled repair result. Both endpoints require Supabase bearer auth and branch repair visibility through the backend. - Branch settlement operator board contracts expose
GET /branch-settlement-operator-boards/{branchSettlementId}for branch/HQ settlement review screens. The endpoint requires a Supabase bearer token, reads Supabase settlement rows through the backend service-role adapter, and checks branchsettlepermission through SpiceDB before returning data. The response isBranchSettlementOperatorBoard: settlement period, stored net balance, line-derived receivable/payable totals, calculated net balance, reconciliation delta, and ordered directional line items withpolicyVersionLabel. Clients build the path and header through contract helpers and must not read Supabase settlement tables directly. - Kill Bill payment webhook contracts expose
POST /killbill-payment-events. The request body is the Kill Bill payment event callbacks JSON envelope withtype,timestamp, anddata, while unknown provider-added fields remain allowed. The202response returnsprocessingStatus = queued, webhook message id, event type, nullable payment id, workload kindpayment_webhook_processing, and queue namesanmopia_payment_webhook_processing. The backend worker then recordssanmopia_killbill_payment_eventsand startsReservationPaymentWorkflowforverify_paid_paymentwhen the event can be mapped to a payment. Paid webhooks classifyvirtual_account_depositwhen the local payment record method isvcnt; other paid records useinstant_payment. Cancelled, partially cancelled, failed, and virtual-account-issued webhooks synchronize payment record status from the queue worker after local payment lookup. - Kill Bill payment administrator contracts expose
POST /killbill-payment-admin-operations. The request carries an action, reason, idempotency key, expected revision, and action-specific payment/search facts; it never accepts client-suppliedactorUserId. The backend derives the actor from Supabase Auth, gates branch managers through SpiceDBfinalize_charge, records append-onlysanmopia_killbill_admin_operation_audits, and returns the audit id, action, status, provider status/result, fingerprints, and replay source when the same idempotency key is reused. - Reservation financial lifecycle commands expose
POST /reservation-financial-lifecycles/{reservationBookingId}/service-deliveries,.../caregiver-payout-preparations,.../branch-settlement-preparations,.../hq-settlement-preparations, and.../settlement-completions. The response isReservationFinancialLifecycle: current stage, frozen mother-visible payable total, caregiver payout total, branch settlement total, HQ settlement total, delivered-day facts, and ledger line count. Commands return404for missing lifecycle,409for wrong stage or bucket, and503when the command handler is not configured. - Reservation booking command intake must receive mother profile, branch context, actor context, caregiver candidates, and caregiver profile facts from the caller or repository adapter. API mappers must not synthesize placeholder emails, branch ids, actor user ids, caregiver ids, or matching candidates.
- Booking service-term side-effect assembly contracts expose
GET /booking-service-term-side-effect-assemblies/{assemblyKey}for immutable readback andPOST /booking-service-term-side-effect-assemblies/{assemblyKey}/projection-invalidation-repairsfor operator requeue of failed report/settlement invalidations. The repair command is idempotent, path-scoped to the assembly, authorized through the booking workflow projection, and returns requested/requeued/skipped invalidation keys so frontend does not infer projection state locally. - Daily care report contracts expose
DailyCareReportDefinitionandDailyCareReportSubmission. Form sections and fields are Strapi-authored lower_snake_case keys, submitted answers are keyed values, and source-era view fields such asincisionSiteorotherServicedo not appear in public contracts. - Document reporting contracts expose
DailyCareReportPrintPayloadfor A4 report-series rendering. The payload carries ordereddailyCareReportsand flatteneddailyCareReportAnswerRowswith logical answer row keys, section keys, answer keys, display values, caregiver role, handoff order, and policy version so HTML print templates do not rebuild source Excel coordinate or nested-loop logic. - Mother lead intake contracts expose modern program codes. Source codes such
as
MILK,LOVEBOX, andCLEAN_TBare import-boundary mappings only. - Caregiver performance recognition contracts expose seasons, metric rules,
scorecards, contribution facts, manual adjustments, branch scorecards, and
grade thresholds. Source award fields such as
JOIN_GRADE,SCORE,INTRODUCE_GRADE, andGRADE_SCOREmap only at import boundaries; total fields are never accepted as contribution metrics.