Outcome
Your integration temporarily gates delegated writes for every access event, reconciles the current company projection, applies unavailable cleanup only when current access is unavailable, and resumes future authorized work when current access is available.Prerequisites
- A verified Partner webhook receiver with durable deduplication by event UUID.
- A company-indexed command queue and an access gate that can block work before
any
/v2/request. - Durable storage for company UUID, last observed
case_access, access-event UUIDs and authorization-version provenance, and finalized Case UUIDs. - A Partner key for state reconciliation.
- Python 3.11+ with
requestsand your integration’saccess_controlmodule. ItsAccessControlStore.accept_eventmethod must be idempotent and durable; its state methods must atomically control queue admission and cleanup for one company.
Lifecycle context
API-only onboarding starts provisionally; first setup/login confirms the named Partner once for the current authorization version. Hosted onboarding confirms terms and delegation in its flow. A revocation is the final event whose creation and signature are permitted by the preceding authorized state. That does not make it the last delivery chronologically: Partner deliveries are unordered and at least once. An active company admin can reconnect through the client-authorized connection flow. The company keeps its UUID.authorization_version identifies consent
text; it is not a sequence number or ordering clock. Reconnection does not
replay missed events or restore discarded drafts.
1. Reconcile every access event against current state
After signature verification, validate all three access-event types. This sandbox reference flow proves its environment with an authenticated safe read, durably accepts/deduplicates the event, gates writes, and only then fetches the authoritative company projection:Python access handler
accept_event must return success for an already stored event so duplicates
still trigger reconciliation. gate_company temporarily prevents queue
admission and dispatch. apply_current_state with unavailable commits that
state, cancels or quarantines not-yet-sent commands, and removes local
projections of inaccessible Partner drafts. Applying available commits the
current state; only the separate successful release_company call removes the
temporary gate, without replaying old work. Each state application binds the
accepted event UUID, company UUID, authorization version, exact event bytes,
exact Company request URL, exact response bytes and HTTP status, and the
fetched access/readiness projection in one durable record.
The environment proof uses the authenticated Partner-wide token-info read. It
requires no company selection and fails closed unless one
case-insensitively named response header has the exact lowercase value
sandbox. Exceptions from validation, exact identifier/body capture, durable
acceptance, gating, state application, or release remain terminal; the fetch
branches handle expected HTTP outcomes explicitly without releasing the gate
accidentally.
If a delayed revocation arrives after restoration, the fresh company response
is available, so the available branch preserves or restores traffic. If the
current response is unavailable, cleanup applies regardless of which access
event triggered the fetch. Never branch on event arrival order or compare
authorization_version values to decide access.
Company detail 404 is a legitimate hidden-resource outcome after final
revocation. It is handled only after durable acceptance and gating: record
unavailable access with reconciliation still pending and keep the gate. A
transport failure, malformed 200, or other HTTP status also records pending
reconciliation, keeps the gate, and exits for retry. Only a verified 200
whose exact id matches and whose current case_access is available can
apply available state and release the gate. Never interpret hidden access as
deletion of the company’s legal records.
2. Interpret the current company projection
The response below shows a connected company whose Case Management API access is unavailable, for example because paywise suspended Case Management API use. A disconnected company is hidden with404. Readiness can remain green while access is
unavailable, so the reconciliation worker takes the unavailable branch; a
schema-valid response with case_access: available would take the available
branch instead.
Representative response
Company and demonstrates why readiness cannot
stand in for delegation: the data is ready while Partner access is unavailable.
3. Preserve finalized knowledge and discard draft work
paywise deletes Partner-created drafts that become inaccessible. Remove them from retry queues and mark local draft projections unavailable; do not attempt to recreate them under a new key. Keep finalized order and mandate UUIDs in the audit trail. Finalized cases remain available to company and staff channels, even when the Partner can no longer retrieve them. Do not infer finalization from a lost404. Only a previously stored successful
finalize response or authoritative pre-revocation read establishes that state.
4. Repair missed events with scheduled reconciliation
Run the same gate, exact Company GET, andcase_access branch periodically for
every company your integration already knows, even without a new event. This
repairs a missed restoration so traffic cannot remain stranded behind a stale
local block. It also repairs a delayed or missed revocation from current state.
Restoration resumes future Partner events, but events missed while access was
unavailable are not replayed. Reconcile every still-relevant finalized resource
your Partner can currently access. Treat any new draft or command as a new
business decision with a new idempotency key—never replay the revoked queue.
If rebuilding an all-company projection from
GET /partner/v2/companies/, use overlapping updated_since scans, follow
every exact next URL, reconcile by (id, updated_at), and periodically repeat
a full scan. Mutable offset pagination has no snapshot, so one pass cannot
prove completeness under concurrent changes.
Failure and recovery
- Duplicate access event: deduplicate by event UUID, then refetch the company; do not skip current-state reconciliation.
- Out-of-order delivery: temporarily gate and fetch current state. Do not use
authorization_versionto order confirmation, revocation, or restoration. - Company
404after revocation: record unavailable/pending reconciliation and keep traffic gated. The Company may legitimately be hidden; an inaccessible Partner draft may also have been deleted. - Missing events during revocation: expected. Restoration has no replay; run
current-state reconciliation. Deliveries that were still queued when access
ended are closed as
failedwitherror_message: partner_access_unavailablewithout an HTTP call; they cannot be redelivered (404). - Membership commands after a release:
404, like every other request for a company outside your access. An offboarded company answers409 company_offboardedto every membership command instead. - Company detail still unavailable after restoration: do not unblock. Verify entitlement with the authorized portal/support path.
Verify
Exercise revocation, restoration, and delayed-revocation delivery with queued work. Confirm the event is durably accepted before2xx, every delivery first
gates writes, unavailable cleanup follows only current case_access: unavailable, and a delayed revocation cannot override current available state.
Confirm finalized IDs remain, drafts are not recreated, and a periodic run
repairs a deliberately missed restoration without replaying commands.
