Skip to content

Developers

Kreto API reference

The compliance intelligence API — classify notices, cross-check payroll, drive resolutions and more. Every operation below is generated from the same OpenAPI specification that powers the Kreto SDK, CLI and MCP server.

OpenAPI 3.1.0v1.0.0386 operations56 resource groupsDownload openapi.json ↓

Authentication

UI clients authenticate with a Supabase cookie session and need no setup. Partner and machine-to-machine integrations use a tenant-scoped Bearer token. Create and manage keys through POST /api/api-keys. Every request is isolated to the key’s tenant via row-level security, and each key carries an explicit scope array — an operation only succeeds if the key holds every scope it lists.

curl https://app.kreto.ai/api/notices \ -H "Authorization: Bearer krto_live_your_key_here"

Available scopes (8) — grant a key only the scopes its integration needs:

admin.readaudit.reademployers.reademployers.writenotices.readnotices.writepayroll.readpayroll.write

Analytics1

GET/api/analytics/predictionsEntity risk predictions

Risk predictions for an entity: SUI rate-change forecast, ACA penalty risk (when FTE >= 40), and overall risk profile aggregating open/overdue notices + active state count. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidrequired

Responses

  • 200Risk predictionsAnalyticsPredictionsResponse
    FieldTypeRequiredDescription
    entityobjectrequired
    riskProfileobjectrequired
    suiPredictionobjectrequired
    acaRiskobjectrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 404Entity not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

API Keys4

GET/api/api-keysList API keys for the caller's tenant

Returns all API keys (active + revoked) for the authenticated CPA's tenant. Response NEVER includes plaintext or key_hash — only the publicly safe key_prefix + metadata.

Cookie session or Bearer token

Responses

  • 200List of API keysListApiKeysResponse
    FieldTypeRequiredDescription
    keysarray<PublicApiKey>required
  • 401UnauthorizedApiKeysNotFoundResponse
POST/api/api-keysIssue a new API key

Create a new API key for the authenticated CPA's tenant. Plaintext is returned ONCE in the response (`plaintext` field) — store it securely; subsequent GET calls return only the masked metadata. Optional `scopes` array narrows the key's authority; NULL/omitted = full tenant scope.

Cookie session or Bearer token

Request body CreateApiKeyBodyrequired

FieldTypeRequiredDescription
namestringrequired
scopesarray<enum: "notices.read" | "employers.read" | "payroll.read" | "audit.read" | …>optionalOptional scope array. NULL or omitted = full tenant scope (v1 default).
expires_atstring · date-timeoptionalOptional expiry. NULL = never expires (operator-revocation only).

Responses

  • 201Key issued. Plaintext returned ONCE; store it now — it cannot be retrieved again.IssuedApiKey
    FieldTypeRequiredDescription
    idstring · uuidrequired
    tenant_idstring · uuidrequired
    key_prefixstringrequired
    namestringrequired
    scopesarray<enum: "notices.read" | "employers.read" | "payroll.read" | "audit.read" | …>required
    created_by_user_idstring · uuidrequired
    created_atstring · date-timerequired
    last_used_atstring · date-timerequired
    revoked_atstring · date-timerequired
    expires_atstring · date-timerequired
    plaintextstringrequired
    warningenum: "This is the ONLY time the plaintext is shown. Store it securely now."required
  • 400Validation error (Zod issues array in body)ApiKeysValidationErrorResponse
  • 401Unauthorized — caller is not authenticated as a CPAApiKeysNotFoundResponse
GET/api/api-keys/{id}Fetch a single API key's metadata
Cookie session or Bearer token

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequired

Responses

  • 200Key metadataobject
    FieldTypeRequiredDescription
    keyPublicApiKeyrequired
  • 404Key not found in your tenantApiKeysNotFoundResponse
DELETE/api/api-keys/{id}Revoke an API key

Soft-delete via `revoked_at`. Idempotent — re-revoking returns the existing revocation timestamp. Optional body { reason: string } for audit context.

Cookie session or Bearer token

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequired

Request body object

FieldTypeRequiredDescription
reasonstringoptional

Responses

  • 200Key revoked (or already revoked — idempotent)RevokeApiKeyResponse
    FieldTypeRequiredDescription
    revokedbooleanrequired
    already_revokedbooleanrequired
    revoked_atstring · date-timeoptional
    keyPublicApiKeyoptional
  • 404Key not found in your tenantApiKeysNotFoundResponse

Audit1

GET/api/auditList audit events

Fetch tenant audit events, optionally filtered by entity_id. CPA-class roles only on cookie sessions; Bearer keys gate via `audit.read`.

Bearer scopesaudit.read

Parameters

NameInTypeRequiredDescription
limitqueryintegeroptional
entity_idquerystring · uuidoptional

Responses

  • 200Audit eventsAuditEventsResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    eventsarray<AuditEvent>required
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

Compliance17

POST/api/compliance/digestTrigger compliance digest

Manually trigger a weekly compliance digest email. CPA-class roles only on cookie sessions; Bearer keys gate via `admin.read` scope.

Bearer scopesadmin.read

Responses

  • 200Digest dispatchedComplianceDigestResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    sentintegeroptional
    skippedintegeroptional
    digest_idstringoptional
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — CPA access required / missing scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse
GET/api/compliance/score-historyGet compliance score history

Returns the most recent 12 score-history entries for the caller's tenant (or for a specific entity when entity_id is supplied).

Bearer scopesaudit.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidoptional

Responses

  • 200Score historyComplianceScoreHistoryResponse
    FieldTypeRequiredDescription
    historyarray<ComplianceScoreHistoryEntry>required
  • 400Validation errorComplianceValidationErrorResponse
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
GET/api/compliance/roi-summaryGet YTD ROI summary

Returns YTD savings, penalties avoided, time saved, and notice count derived from `roi_events` for the caller's tenant.

Bearer scopesaudit.read

Responses

  • 200YTD ROI summaryComplianceRoiSummaryResponse
    FieldTypeRequiredDescription
    ytd_savingsintegerrequired
    ytd_penalties_avoidedintegerrequired
    ytd_time_saved_hoursintegerrequired
    ytd_notices_processedintegerrequired
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
GET/api/compliance/intelligence-scoreGet compliance intelligence score

Returns the Compliance Intelligence Score either for a single entity (when entity_id is supplied) or aggregated across all of the caller's tenant's entities.

Bearer scopesaudit.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidoptional

Responses

  • 200Score (single or aggregate)one of (ComplianceSingleEntityScoreResponse · ComplianceIntelligenceScore)
  • 400Validation errorComplianceValidationErrorResponse
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse
GET/api/compliance-score/{entityId}Get single-entity score (legacy)

Legacy path: returns the Compliance Intelligence Score for a given entity. Tenant-scoped on the entity verification (KRT-1479 P4e.1 Senior-Dev-Override fix).

Bearer scopesaudit.read

Parameters

NameInTypeRequiredDescription
entityIdpathstring · uuidrequiredEmployer entity UUID

Responses

  • 200Compliance intelligence scoreobject
  • 400Validation errorComplianceValidationErrorResponse
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 404Entity not found in caller's tenantComplianceNotFoundResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse
GET/api/compliance/aca-summaryGet ACA summary

Returns ACA (Applicable Large Employer) status + penalty exposure per entity. Primary FTE source: payroll_pay_periods; fallback chain through payroll_records → onboarding range → entity.employee_count.

Bearer scopesaudit.read

Responses

  • 200ACA summary by entityComplianceAcaSummaryResponse
    FieldTypeRequiredDescription
    employeesintegerrequired
    aleStatusenum: "applicable" | "not_applicable"required
    dataQualityenum: "payroll" | "estimate"required
    entitiesarray<ComplianceAcaEntity>required
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse
GET/api/compliance/benefitsList benefits compliance

List benefits compliance records for all tenant entities for a given plan year (defaults to current year).

Bearer scopesaudit.read

Parameters

NameInTypeRequiredDescription
yearquerystringoptionalPlan year

Responses

  • 200Benefits listComplianceBenefitsListResponse
    FieldTypeRequiredDescription
    recordsarray<object>required
    yearintegerrequired
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
POST/api/compliance/benefitsUpsert benefits compliance record

Upsert a benefits compliance record for an entity + plan year. Tenant-scoped on the entity verification (already correct pre-Phase-4).

Bearer scopesnotices.write

Request body ComplianceBenefitsPostBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
plan_yearintegerrequired
plan_typestringoptional
carrier_namestringoptional
plan_participantsintegeroptional
rxdc_completedbooleanoptional
rxdc_completed_datestring · dateoptional
gag_clause_filedbooleanoptional
gag_clause_filed_datestring · dateoptional
gag_clause_confirmationstringoptional
medicare_part_d_sentbooleanoptional
medicare_part_d_sent_datestring · dateoptional
chip_notice_sentbooleanoptional
chip_notice_sent_datestring · dateoptional
form_5500_requiredbooleanoptional
form_5500_filedbooleanoptional
form_5500_filed_datestring · dateoptional
cobra_documentedbooleanoptional

Responses

  • 200Record upsertedobject
    FieldTypeRequiredDescription
    recordBenefitsRecordrequired
  • 400Validation errorComplianceValidationErrorResponse
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 404Entity not found in caller's tenantComplianceNotFoundResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse
GET/api/compliance/pfml-checkCheck PFML compliance gaps

PFML enrollment gap analysis for tenant entities. client_user role (cookie session) scoped to assigned entities; CPA-class + Bearer keys see all tenant entities.

Bearer scopesaudit.read

Responses

  • 200PFML gap analysisCompliancePfmlResponse
    FieldTypeRequiredDescription
    entitiesarray<CompliancePfmlResult>required
    summaryobjectrequired
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse
GET/api/compliance/wage-hour-riskGet wage & hour risk scores

Returns wage & hour risk scores per entity (state minimum wage check, overtime policy gaps, exempt-employee threshold, contractor risk).

Bearer scopesaudit.read

Responses

  • 200Risk scores per entityComplianceWageHourResponse
    FieldTypeRequiredDescription
    entitiesarray<ComplianceWageHourEntity>required
    federalMinimumWagenumberrequired
    overtimeSalaryThresholdnumberrequired
    errorstringoptional
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
GET/api/compliance-monitorGet compliance monitor profiles

Returns compliance profiles for all employers (sorted worst-first). client_user role scoped to assigned entities; CPA-class + Bearer keys see all tenant entities.

Bearer scopesaudit.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidoptionalFilter to a single entity (must be authorized)

Responses

  • 200Compliance profilesComplianceMonitorResponse
    FieldTypeRequiredDescription
    profilesarray<object>required
  • 400Validation errorComplianceValidationErrorResponse
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — entity access denied / missing scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse
PATCH/api/compliance/credential-alerts/{id}/acknowledgeAcknowledge credential-refresh alert

Dismiss a credential_refresh_alerts row (KRT-1288). 404 covers not-found / already-acknowledged / auto-resolved equally.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredAlert UUID

Responses

  • 200AcknowledgedComplianceCredentialAlertsAcknowledgeResponse
    FieldTypeRequiredDescription
    alertobjectrequired
  • 400Validation errorComplianceValidationErrorResponse
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — CPA access required / missing scopeComplianceUnauthorizedResponse
  • 404Alert not found or already handledComplianceNotFoundResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse
PATCH/api/compliance/recommendations/{id}/acknowledgeAcknowledge state-registration recommendation

Dismiss a state_registration_recommendations row (KRT-1216 PR-D).

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredRecommendation UUID

Responses

  • 200AcknowledgedComplianceRecommendationsAcknowledgeResponse
    FieldTypeRequiredDescription
    recommendationobjectrequired
  • 400Validation errorComplianceValidationErrorResponse
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — CPA access required / missing scopeComplianceUnauthorizedResponse
  • 404Recommendation not found or already acknowledgedComplianceNotFoundResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse
GET/api/compliance/payroll-tax-analysisGet payroll-tax analysis

Calculate expected federal payroll taxes (SS, Medicare, FUTA, 941, 940) per entity from Finch / payroll_records / employee-count fallback chain. Per-employee detail is stripped from response (PII).

Bearer scopesaudit.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidoptional

Responses

  • 200Payroll-tax analysisCompliancePayrollTaxAnalysisResponse
    FieldTypeRequiredDescription
    entitiesarray<CompliancePayrollTaxEntity>required
    summaryobjectrequired
  • 400Validation errorComplianceValidationErrorResponse
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse
POST/api/compliance/payroll-tax-analysisAnalyze payroll-tax compliance

Compare expected payroll-tax liability against quarterly deposit input. Returns expected + compliance comparison + dataSource.

Bearer scopesaudit.read

Request body CompliancePayrollTaxAnalysisPostBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
depositsarray<object>required

Responses

  • 200Comparison resultCompliancePayrollTaxAnalysisPostResponse
    FieldTypeRequiredDescription
    expectedobjectrequired
    complianceobjectrequired
    dataSourceenum: "finch" | "payroll" | "estimate"required
  • 400Validation errorComplianceValidationErrorResponse
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 404Entity not found in caller's tenantComplianceNotFoundResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse
GET/api/compliance/alertsGet unified compliance alerts

Returns a unified compliance-alerts list across 5 sources (compliance_checks, urgent + overdue + needs-review notices, state_registration_recommendations, credential_refresh_alerts).

Bearer scopesaudit.read

Responses

  • 200Compliance alertsComplianceAlertsResponse
    FieldTypeRequiredDescription
    alertsarray<ComplianceAlert>required
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
GET/api/compliance-calendarGet compliance calendar

Returns notices + work_items with deadlines, grouped into overdue / thisWeek / thisMonth / future buckets. Tenant-scoped (P4e.3 Senior-Dev-Override fix).

Bearer scopesaudit.read

Responses

  • 200Grouped deadline calendarComplianceCalendarResponse
    FieldTypeRequiredDescription
    overduearray<ComplianceCalendarItem>required
    thisWeekarray<ComplianceCalendarItem>required
    thisMontharray<ComplianceCalendarItem>required
    futurearray<ComplianceCalendarItem>required
    summaryobjectrequired
  • 401UnauthorizedComplianceUnauthorizedResponse
  • 403Forbidden — missing required scopeComplianceUnauthorizedResponse
  • 429Rate limit exceededComplianceRateLimitResponse
  • 500Server errorComplianceUnauthorizedResponse

Connections10

GET/api/connectionsList connections

Returns the unified connection list (data_connections + finch_connections) scoped to the caller's tenant. Sensitive config fields (encrypted refresh tokens, token expiries) are stripped.

Bearer scopespayroll.read

Responses

  • 200Connections listConnectionListResponse
  • 401UnauthorizedConnectionsUnauthorizedResponse
  • 403Forbidden — missing required scopeConnectionsUnauthorizedResponse
  • 429Rate limit exceededConnectionsRateLimitResponse
  • 500Server errorConnectionsUnauthorizedResponse
POST/api/connections/{id}Trigger connection sync

Trigger a manual sync. Body: `{ action: "sync" }`. Enqueues a connection_sync job; the worker picks it up.

Bearer scopespayroll.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredConnection UUID

Request body ConnectionPostBodyrequired

FieldTypeRequiredDescription
actionenum: "sync"required

Responses

  • 200Sync enqueuedConnectionSyncResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    messageenum: "Sync enqueued"required
  • 400Validation error / wrong status / missing tokenConnectionsValidationErrorResponse
  • 401UnauthorizedConnectionsUnauthorizedResponse
  • 403Forbidden — missing required scopeConnectionsUnauthorizedResponse
  • 404Connection not found in caller's tenantConnectionsNotFoundResponse
  • 429Rate limit exceededConnectionsRateLimitResponse
  • 500Server errorConnectionsUnauthorizedResponse
DELETE/api/connections/{id}Disconnect connection

Disconnect a connection: revoke the Google OAuth token (best-effort) and mark the row as `revoked`. Sensitive config fields are cleared.

Bearer scopespayroll.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredConnection UUID

Responses

  • 200DisconnectedConnectionDisconnectResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    messageenum: "Disconnected"required
  • 400Validation errorConnectionsValidationErrorResponse
  • 401UnauthorizedConnectionsUnauthorizedResponse
  • 403Forbidden — missing required scopeConnectionsUnauthorizedResponse
  • 404Connection not found in caller's tenantConnectionsNotFoundResponse
  • 429Rate limit exceededConnectionsRateLimitResponse
  • 500Server errorConnectionsUnauthorizedResponse
GET/api/connections/finch/statusGet Finch connection status

Returns the Finch connection status + recent sync logs for an entity.

Bearer scopespayroll.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidrequiredEntity UUID (required)

Responses

  • 200Status + sync logsFinchStatusResponse
    FieldTypeRequiredDescription
    connectedbooleanrequired
    statusstringrequired
    connectionobjectrequired
    recent_syncsarray<FinchSyncLog>optional
  • 400Validation errorConnectionsValidationErrorResponse
  • 401UnauthorizedConnectionsUnauthorizedResponse
  • 403Forbidden — missing required scopeConnectionsUnauthorizedResponse
  • 429Rate limit exceededConnectionsRateLimitResponse
GET/api/connections/{id}/foldersList provider folders

List folders from the connected provider (Google Drive or Dropbox). Returns selectedFolderIds from current config so the UI can render the checkbox state.

Bearer scopespayroll.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredConnection UUID

Responses

  • 200Folder list + selected IDsConnectionFoldersGetResponse
    FieldTypeRequiredDescription
    foldersarray<ConnectionFolderEntry>required
    selectedFolderIdsarray<string>required
  • 400Validation errorConnectionsValidationErrorResponse
  • 401UnauthorizedConnectionsUnauthorizedResponse
  • 403Forbidden — missing required scopeConnectionsUnauthorizedResponse
  • 404Connection not found in caller's tenantConnectionsNotFoundResponse
  • 429Rate limit exceededConnectionsRateLimitResponse
  • 500Server errorConnectionsUnauthorizedResponse
PUT/api/connections/{id}/foldersSave selected folders

Save selected watched-folder IDs to the connection config.

Bearer scopespayroll.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredConnection UUID

Request body ConnectionFoldersPutBodyrequired

FieldTypeRequiredDescription
folderIdsarray<string>required

Responses

  • 200SavedConnectionFoldersPutResponse
    FieldTypeRequiredDescription
    savedenum: truerequired
    folderIdsarray<string>required
  • 400Validation errorConnectionsValidationErrorResponse
  • 401UnauthorizedConnectionsUnauthorizedResponse
  • 403Forbidden — missing required scopeConnectionsUnauthorizedResponse
  • 404Connection not found in caller's tenantConnectionsNotFoundResponse
  • 429Rate limit exceededConnectionsRateLimitResponse
  • 500Server errorConnectionsUnauthorizedResponse
GET/api/connections/{id}/watchList watched folders

List active watched folders for a connection.

Bearer scopespayroll.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredConnection UUID

Responses

  • 200Watched foldersConnectionWatchListResponse
    FieldTypeRequiredDescription
    foldersarray<object>required
  • 400Validation errorConnectionsValidationErrorResponse
  • 401UnauthorizedConnectionsUnauthorizedResponse
  • 403Forbidden — missing required scopeConnectionsUnauthorizedResponse
  • 429Rate limit exceededConnectionsRateLimitResponse
POST/api/connections/{id}/watchStart watching folder

Start watching a folder for inbound notice intake. Verifies that both the connection and target entity belong to the caller's tenant.

Bearer scopespayroll.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredConnection UUID

Request body ConnectionWatchPostBodyrequired

FieldTypeRequiredDescription
folder_idstringrequired
folder_namestringrequired
folder_pathstringoptional
entity_idstring · uuidrequired

Responses

  • 200Now watchingConnectionWatchPostResponse
    FieldTypeRequiredDescription
    watched_folderobjectrequired
    entity_namestringrequired
    messagestringrequired
  • 400Validation errorConnectionsValidationErrorResponse
  • 401UnauthorizedConnectionsUnauthorizedResponse
  • 403Forbidden — missing required scopeConnectionsUnauthorizedResponse
  • 404Connection or entity not foundConnectionsNotFoundResponse
  • 429Rate limit exceededConnectionsRateLimitResponse
  • 500Server errorConnectionsUnauthorizedResponse
DELETE/api/connections/{id}/watchStop watching folder

Stop watching a folder (soft-delete via is_active=false).

Bearer scopespayroll.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredConnection UUID

Request body ConnectionWatchDeleteBodyrequired

FieldTypeRequiredDescription
watched_folder_idstring · uuidrequired

Responses

  • 200Stoppedobject
    FieldTypeRequiredDescription
    successenum: truerequired
  • 400Validation errorConnectionsValidationErrorResponse
  • 401UnauthorizedConnectionsUnauthorizedResponse
  • 403Forbidden — missing required scopeConnectionsUnauthorizedResponse
  • 429Rate limit exceededConnectionsRateLimitResponse
  • 500Server errorConnectionsUnauthorizedResponse
POST/api/connections/finch/syncTrigger Finch sync

Trigger a manual Finch sync. Enqueues a finch_sync job; skips if another sync is already pending/running. Cookie sessions go through the Stripe subscription gate; Bearer keys bypass.

Bearer scopespayroll.write

Request body FinchSyncPostBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired

Responses

  • 200Sync enqueued or already in progressFinchSyncResponse
    FieldTypeRequiredDescription
    messagestringrequired
    job_idstring · uuidoptional
  • 400Validation error / connection inactiveConnectionsValidationErrorResponse
  • 401UnauthorizedConnectionsUnauthorizedResponse
  • 402Subscription required (cookie sessions only)ConnectionsUnauthorizedResponse
  • 403Forbidden — missing required scopeConnectionsUnauthorizedResponse
  • 404No Finch connection for entityConnectionsNotFoundResponse
  • 429Rate limit exceededConnectionsRateLimitResponse
  • 500Server errorConnectionsUnauthorizedResponse

Dashboard2

GET/api/dashboard/summaryDashboard summary

Aggregated dashboard metrics (KRT-473): notice counts, task counts, fine amounts, and configured deadline window.

Bearer scopesnotices.read

Responses

  • 200Summary metricsDashboardSummaryResponse
    FieldTypeRequiredDescription
    noticesobjectrequired
    tasksobjectrequired
    finesobjectrequired
    deadline_window_daysintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

Documents15

GET/api/documents/{id}/auditGet document audit trail

Returns the document's audit trail — signature events, sends, voids, and view events with actor + timestamp + IP/user-agent context.

Bearer scopesaudit.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredDocument UUID

Responses

  • 200Audit trailDocumentAuditResponse
    FieldTypeRequiredDescription
    audit_trailarray<DocumentAuditEntry>required
  • 400Validation errorDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
GET/api/documents/{id}/signaturesList document signatures

Returns all recorded signatures for a document.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredDocument UUID

Responses

  • 200Signatures listDocumentSignaturesResponse
    FieldTypeRequiredDescription
    signaturesarray<DocumentSignatureRecord>required
  • 400Validation errorDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
POST/api/documents/{id}/sendSend document to recipient

Send a document to a recipient via email. RLS enforces document ownership; sender_id is recorded for the audit trail.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredDocument UUID

Request body DocumentSendBodyrequired

FieldTypeRequiredDescription
recipient_emailstring · emailrequired
recipient_namestringrequired
messagestringoptional

Responses

  • 200SentDocumentSendResponse
    FieldTypeRequiredDescription
    documentobjectrequired
  • 400Validation errorDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
POST/api/documents/{id}/voidVoid document

Void a document with a reason. Voided documents cannot be re-sent or re-signed; the audit trail records the void event.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredDocument UUID

Request body DocumentVoidBodyrequired

FieldTypeRequiredDescription
reasonstringrequired

Responses

  • 200VoidedDocumentSendResponse
    FieldTypeRequiredDescription
    documentobjectrequired
  • 400Validation errorDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
POST/api/documents/{id}/signSign document

Record a signature on a document. Captures signer name + email + IP + user-agent for the audit trail. 4 signature methods supported.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredDocument UUID

Request body DocumentSignBodyrequired

FieldTypeRequiredDescription
signer_namestringrequired
signer_emailstring · emailrequired
signer_rolestringoptional
signature_datastringoptional
signature_methodenum: "drawn" | "typed" | "uploaded" | "click_to_sign" | …optional

Responses

  • 201Signature recordedDocumentSignResponse
    FieldTypeRequiredDescription
    signatureDocumentSignatureRecordrequired
  • 400Validation errorDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
GET/api/documents/statsGet document counts

Returns document counts by status (total / pending / signed / expired) for the caller's tenant. Falls back to count-only when the documents.status column is missing.

Bearer scopesnotices.read

Responses

  • 200Stats by statusDocumentStatsResponse
    FieldTypeRequiredDescription
    totalintegerrequired
    pendingintegerrequired
    signedintegerrequired
    expiredintegerrequired
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
GET/api/documents/collectionGet document-collection progress by entity

Returns document_requests grouped by entity, with progress counts (items_total / items_complete) and derived status (complete / overdue / in_progress).

Bearer scopesnotices.read

Responses

  • 200Grouped collection requestsDocumentCollectionResponse
    FieldTypeRequiredDescription
    requestsarray<DocumentCollectionGroup>required
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
GET/api/documentsList documents

List documents with optional filters (requestId, entityId, date range, includeDeleted) and pagination.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
requestIdquerystring · uuidoptional
entityIdquerystring · uuidoptional
startDatequerystring · date-timeoptional
endDatequerystring · date-timeoptional
limitquerystringoptional
offsetquerystringoptional
includeDeletedqueryenum: "true" | "false"optional

Responses

  • 200Documents listDocumentListResponse
    FieldTypeRequiredDescription
    documentsarray<DocumentRecord>required
    countintegerrequired
    limitintegerrequired
    offsetintegerrequired
  • 400Validation errorDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
GET/api/documents/{id}Get document detail

Get document metadata by id. document-engine internally scopes by RLS on the caller's session.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredDocument UUID

Responses

  • 200Document metadataDocumentDetailResponse
    FieldTypeRequiredDescription
    documentDocumentRecordrequired
  • 400Validation errorDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 404Document not foundDocumentNotFoundResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
DELETE/api/documents/{id}Soft-delete document

Soft-delete a document with an optional reason. Returns 204 No Content on success. Already-deleted documents return 409 Conflict.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredDocument UUID

Request body DocumentDeleteBody

FieldTypeRequiredDescription
reasonstringoptional

Responses

  • 204Soft-deleted
  • 400Validation errorDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 404Document not found / not accessibleDocumentNotFoundResponse
  • 409Document already deletedDocumentValidationErrorResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
POST/api/documents/request-emailSend document-request email

Send a document-request email to an employer contact via Resend. Sender is the caller's display_name + tenant name.

Bearer scopesnotices.write

Request body DocumentRequestEmailBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
recipient_emailstring · emailrequired
recipient_namestringoptional

Responses

  • 200Email sentDocumentRequestEmailResponse
    FieldTypeRequiredDescription
    sentenum: truerequired
    tostringrequired
  • 400Validation errorDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 404Entity not found in caller's tenantDocumentNotFoundResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server error / Resend API failureDocumentUnauthorizedResponse
  • 503Email service not configuredDocumentUnauthorizedResponse
POST/api/documents/uploadUpload document

Upload a document (multipart/form-data) for an entity, optionally tied to a document_request. Idempotency-aware (x-idempotency-key header). Tags accept JSON array or comma-separated form.

Bearer scopesnotices.write

Request body DocumentUploadMultipartBodyrequired

FieldTypeRequiredDescription
filestringrequiredDocument binary
entityIdstring · uuidoptional
requestIdstring · uuidoptional
tagsstringoptionalJSON array or comma-separated tags

Responses

  • 200UploadedDocumentUploadResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    documentDocumentRecordrequired
  • 400Validation errorDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 404Entity or request not foundDocumentNotFoundResponse
  • 409Document already existsDocumentValidationErrorResponse
  • 429Rate limit exceeded (uploads use the 10/min ceiling)DocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
POST/api/documents/create-signing-requestCreate signing request link

Create a token-based signature request for a document and return a secure signing link suitable for email delivery. Token expires after 1-30 days.

Bearer scopesnotices.write

Request body DocumentCreateSigningRequestBodyrequired

FieldTypeRequiredDescription
document_idstring · uuidrequired
entity_idstring · uuidoptional
signer_namestringrequired
signer_emailstring · emailrequired
signer_titlestringoptional
expires_daysintegeroptional

Responses

  • 201Signing request createdDocumentCreateSigningRequestResponse
    FieldTypeRequiredDescription
    request_idstring · uuidrequired
    secure_tokenstring · uuidrequired
    signing_linkstringrequired
    expires_atstring · date-timerequired
  • 400Validation errorDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 404Document not found in caller's tenantDocumentNotFoundResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server errorDocumentUnauthorizedResponse
POST/api/documents/verifyVerify document via AI

Run AI-based document verification on an uploaded file (PDF/PNG/JPG/DOCX, ≤10 MB). Two audit events recorded (requested + completed). Returns documentType + confidence + verified + flags.

Bearer scopesnotices.write

Request body DocumentVerifyMultipartBodyrequired

FieldTypeRequiredDescription
filestringrequiredPDF/PNG/JPG/DOCX binary (max 10 MB)
expectedTypestringoptional

Responses

  • 200Verification resultDocumentVerifyResult
    FieldTypeRequiredDescription
    okenum: truerequired
    resultobjectrequired
  • 400Validation error / unsupported MIME / unreadable fileDocumentValidationErrorResponse
  • 401UnauthorizedDocumentUnauthorizedResponse
  • 403Forbidden — missing required scopeDocumentUnauthorizedResponse
  • 413File too large (>10 MB)DocumentValidationErrorResponse
  • 429Rate limit exceededDocumentRateLimitResponse
  • 500Server error / verification pipeline failureDocumentUnauthorizedResponse
POST/api/check-duplicateCheck upload duplicate

Check if an uploaded file with the given SHA-256 content hash already exists in the caller's tenant (KRT-203). Returns the original upload ID + filename if found. Cookie sessions go through rate-limit middleware.

Bearer scopesnotices.read

Request body CheckDuplicateBodyrequired

FieldTypeRequiredDescription
contentHashstringrequired

Responses

  • 200Duplicate check resultCheckDuplicateResponse
    FieldTypeRequiredDescription
    isDuplicatebooleanrequired
    originalUploadIdstring · uuidoptional
    originalFileNamestringoptional
    uploadedAtstring · date-timeoptional
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

Employer2

GET/api/employer/complianceEmployer compliance items

Employer-portal compliance items (per-state requirements + status). Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Responses

  • 200Compliance itemsEmployerComplianceListResponse
    FieldTypeRequiredDescription
    itemsarray<EmployerComplianceItem>required
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/employer/poaEmployer POA authorizations

Employer-portal POA authorizations per state. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Responses

  • 200POA itemsEmployerPOAListResponse
    FieldTypeRequiredDescription
    itemsarray<EmployerPOAItem>required
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

Employers8

POST/api/employersCreate employer

Create a new employer entity for the authenticated CPA's tenant. Validates the body against the multi-axis Zod schema (legal_form, engagement_type, payroll_provider). Returns 201 Created with the new entity ID + legal_name.

Cookie session or Bearer token

Request body CreateEmployerBodyrequired

FieldTypeRequiredDescription
legal_namestringrequired
ein_last4stringoptional
primary_statestringoptional
addressstringoptional
citystringoptional
statestringoptional
zipstringoptional
contact_namestringoptional
contact_emailstring · emailoptional
contact_phonestringoptional
employee_countintegeroptional
legal_formenum: "llc" | "s_corp" | "sole_prop" | "partnership" | …optional
engagement_typeenum: "full_managed" | "selective" | "employer_direct"optional
payroll_providerenum: "adp" | "gusto" | "paychex" | "manual" | …optional

Responses

  • 201Employer createdCreateEmployerResponse
    FieldTypeRequiredDescription
    entityEntitySummaryrequired
  • 400Validation errorValidationErrorResponse
  • 401UnauthorizedUnauthorizedResponse
PATCH/api/employersUpdate employer

Update an entity's contact info or core identifiers. Tenant-scoped via explicit tenant_id filter (KRT-1191 audit fix).

Cookie session or Bearer token

Request body PatchEmployerBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
contact_namestringoptional
contact_emailstring · emailoptional
contact_phonestringoptional
legal_namestringoptional
ein_last4stringoptional
primary_statestringoptional

Responses

  • 200Employer updatedPatchEmployerResponse
    FieldTypeRequiredDescription
    entityobjectrequired
  • 400Validation error / no fields to updateValidationErrorResponse
  • 401UnauthorizedUnauthorizedResponse
  • 404Entity not found in caller's tenantNotFoundResponse
GET/api/employers/listList employers

List employers visible to the caller (RLS + explicit tenant filter). Each row carries notice_count, active_notices_count, overdue_notices_count, states_operated, and POA progress. Bearer-key callers need the `employers.read` scope (or NULL for full tenant scope).

Bearer scopesemployers.read

Parameters

NameInTypeRequiredDescription
include_deletedqueryenum: "true" | "false"optionalWhen `true`, include soft-deleted entities (CPA-class roles only).

Responses

  • 200Employer listEmployerListResponse
    FieldTypeRequiredDescription
    entitiesarray<EmployerListItem>required
  • 401UnauthorizedUnauthorizedResponse
  • 403Forbidden — missing required scopeUnauthorizedResponse
  • 429Rate limit exceededRateLimitResponse
GET/api/employers/{id}/detailGet employer detail

Return the full entity row with associated notices, POA records, and a derived I-9 compliance summary. All Supabase queries filter by tenant_id explicitly (KRT-1479 P4a Senior-Dev-Override fix).

Bearer scopesemployers.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredEmployer entity UUID

Responses

  • 200Employer detailEmployerDetailResponse
    FieldTypeRequiredDescription
    idstring · uuidrequired
    tenant_idstring · uuidrequired
    legal_namestringrequired
    ein_last4stringrequired
    primary_statestringrequired
    compliance_scorenumberrequired
    entity_typestringrequired
    contact_namestringrequired
    contact_emailstringrequired
    contact_phonestringrequired
    created_atstring · date-timerequired
    is_deletedbooleanoptional
    deletion_datestring · date-timeoptional
    noticesarray<NoticeSummary>required
    poa_recordsarray<PoaRecord>required
    i9_compliancearray<I9ComplianceEntry>required
    penalties_ytdnumberrequired
  • 400Validation errorValidationErrorResponse
  • 401UnauthorizedUnauthorizedResponse
  • 403Forbidden — missing required scopeUnauthorizedResponse
  • 404Entity not found in caller's tenantNotFoundResponse
  • 429Rate limit exceededRateLimitResponse
POST/api/employers/update-einUpdate employer EIN

Set the last 4 digits of an entity's EIN, optionally update legal_name, and clear `needs_ein` flag on a referenced notice. Tenant-scoped.

Bearer scopesemployers.write

Request body UpdateEinBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
ein_last4stringoptional
legal_namestringoptional
notice_idstring · uuidoptional

Responses

  • 200UpdatedSuccessResponse
    FieldTypeRequiredDescription
    successenum: truerequired
  • 400Validation errorValidationErrorResponse
  • 401UnauthorizedUnauthorizedResponse
  • 404Entity not found in caller's tenantNotFoundResponse
PATCH/api/employers/{id}/email-slugCustomize employer notice email

One-time customization of an entity's notice email slug. Once set, the slug is locked (`email_slug_customized=true`) and further changes require operator intervention.

Bearer scopesemployers.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredEmployer entity UUID

Request body EmailSlugBodyrequired

FieldTypeRequiredDescription
slugstringrequired

Responses

  • 200Slug setEmailSlugResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    emailstringrequired
  • 400Invalid slug format / already customizedValidationErrorResponse
  • 401UnauthorizedUnauthorizedResponse
  • 404Entity not found in caller's tenantNotFoundResponse
  • 409Slug taken by another entityValidationErrorResponse
POST/api/employers/{id}/deleteUndo employer soft-delete

Undo a soft-delete. Clears `deleted_at` + `deletion_scheduled_at`. Must be called within the 30-day grace window before /api/employers/cleanup permanently removes the entity row + cascade dependents.

Bearer scopesemployers.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredEmployer entity UUID

Responses

  • 200Deletion cancelledUndoDeleteResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    entity_idstring · uuidrequired
  • 400Entity is not deletedValidationErrorResponse
  • 401UnauthorizedUnauthorizedResponse
  • 404Entity not found in caller's tenantNotFoundResponse
DELETE/api/employers/{id}/deleteSoft-delete employer

Soft-delete an entity. Sets `deleted_at` + `deletion_scheduled_at` (now + 30 days). Permanent deletion is run by /api/employers/cleanup (internal cron). Reversible via POST to the same endpoint within the grace window.

Bearer scopesemployers.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredEmployer entity UUID

Responses

  • 200Deletion scheduledDeleteEmployerResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    scheduled_permanent_deletionstring · date-timerequired
  • 401UnauthorizedUnauthorizedResponse
  • 404Entity not found in caller's tenantNotFoundResponse
  • 409Entity already scheduled for deletionValidationErrorResponse

Garnishments2

GET/api/garnishmentsList garnishment orders

List garnishment orders for the caller's tenant (compliance category #6 — wage garnishments). client_user is entity-scoped on cookie sessions; Bearer keys see full tenant scope.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidoptional
statusquerystringoptional
order_typequerystringoptional
limitqueryintegeroptional
offsetqueryintegeroptional

Responses

  • 200GarnishmentsGarnishmentsListResponse
    FieldTypeRequiredDescription
    garnishmentsarray<GarnishmentOrder>required
    totalintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — entity access denied (client_user scope)MiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/garnishmentsCreate garnishment order

Create a garnishment order. Bearer keys gate via `notices.write`. client_user is entity-scoped on cookie sessions.

Bearer scopesnotices.write

Request body GarnishmentCreateBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
notice_idstring · uuidoptional
order_typestringoptional
court_order_numberstringoptional
case_numberstringoptional
issuing_authoritystringoptional
employee_identifierstringoptional
employee_countintegeroptional
garnishment_amountnumberoptional
withholding_percentagenumberoptional
max_cumulativenumberoptional
priority_orderintegeroptional
effective_datestringoptional
expiration_datestringoptional
response_deadlinestringoptional

Responses

  • 201Garnishment createdGarnishmentCreateResponse
    FieldTypeRequiredDescription
    garnishmentGarnishmentOrderrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — entity access deniedMiscUnauthorizedResponse
  • 404Entity not found in caller's tenantMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

I-911

POST/api/i9-compliance/uploadUpload I-9 document

Upload an I-9 document for an employee. Employer-only on cookie sessions; Bearer keys gate via `notices.write`. Multipart body with `file` and `employee_id` fields.

Bearer scopesnotices.write

Request body objectrequired

FieldTypeRequiredDescription
filestring · binaryrequired
employee_idstringrequired

Responses

  • 200UploadedI9UploadResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    storage_pathstringrequired
    employee_idstringrequired
    filenamestringrequired
  • 400Validation errorI9ValidationErrorResponse
  • 401UnauthorizedI9UnauthorizedResponse
  • 403Forbidden — employer access required / missing scopeI9UnauthorizedResponse
  • 429Rate limit exceededI9RateLimitResponse
  • 500Server errorI9UnauthorizedResponse
POST/api/i9-compliance/forms/{id}/documentsUpload Section 2 supporting document

Upload a Section 2 supporting document for an I-9 record. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`. Multipart body with `file`, `list` (a|b|c), and `index` (0..10).

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredI-9 record UUID

Request body objectrequired

FieldTypeRequiredDescription
filestring · binaryrequired
listenum: "a" | "b" | "c"required
indexintegerrequired

Responses

  • 201Document uploadedI9RecordResponse
    FieldTypeRequiredDescription
    recordI9Recordrequired
  • 400Validation errorI9ValidationErrorResponse
  • 401UnauthorizedI9UnauthorizedResponse
  • 403Forbidden — CPA access requiredI9UnauthorizedResponse
  • 404I-9 record not foundI9NotFoundResponse
  • 429Rate limit exceededI9RateLimitResponse
  • 500Server errorI9UnauthorizedResponse
GET/api/i9-compliance/forms/{id}/pdfDownload I-9 PDF

Render the I-9 record as a flattened PDF. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredI-9 record UUID

Responses

  • 200PDF binaryI9PdfBinaryResponse
  • 401UnauthorizedI9UnauthorizedResponse
  • 403Forbidden — CPA access requiredI9UnauthorizedResponse
  • 404I-9 record not foundI9NotFoundResponse
  • 429Rate limit exceededI9RateLimitResponse
  • 500Server errorI9UnauthorizedResponse
GET/api/i9-compliance/forms/{id}Get I-9 record

Get a single I-9 record. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredI-9 record UUID

Responses

  • 200I-9 recordI9RecordResponse
    FieldTypeRequiredDescription
    recordI9Recordrequired
  • 400Validation errorI9ValidationErrorResponse
  • 401UnauthorizedI9UnauthorizedResponse
  • 403Forbidden — CPA access requiredI9UnauthorizedResponse
  • 404I-9 record not foundI9NotFoundResponse
  • 429Rate limit exceededI9RateLimitResponse
  • 500Server errorI9UnauthorizedResponse
PATCH/api/i9-compliance/forms/{id}Update I-9 Section 2

Update an I-9 record's Section 2 data (employer review). Validates List A is mutually exclusive with List B/C. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredI-9 record UUID

Request body I9Section2Bodyrequired

FieldTypeRequiredDescription
list_a_docsarray<I9DocumentEntry>optional
list_b_docsarray<I9DocumentEntry>optional
list_c_docsarray<I9DocumentEntry>optional
reviewer_namestringrequired
reviewer_titlestringrequired
date_of_hirestringrequired
date_of_completionstringrequired

Responses

  • 200I-9 record updatedI9RecordResponse
    FieldTypeRequiredDescription
    recordI9Recordrequired
  • 400Validation error / invalid document combinationI9ValidationErrorResponse
  • 401UnauthorizedI9UnauthorizedResponse
  • 403Forbidden — CPA access requiredI9UnauthorizedResponse
  • 404I-9 record not foundI9NotFoundResponse
  • 409Section 1 must be completed firstI9ValidationErrorResponse
  • 429Rate limit exceededI9RateLimitResponse
  • 500Server errorI9UnauthorizedResponse
GET/api/i9-compliance/formsList I-9 records by employee

List I-9 records for a given employee. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
employee_idquerystring · uuidrequired

Responses

  • 200I-9 recordsI9RecordsListResponse
    FieldTypeRequiredDescription
    recordsarray<I9Record>required
  • 400Validation errorI9ValidationErrorResponse
  • 401UnauthorizedI9UnauthorizedResponse
  • 403Forbidden — CPA access requiredI9UnauthorizedResponse
  • 429Rate limit exceededI9RateLimitResponse
  • 500Server errorI9UnauthorizedResponse
POST/api/i9-compliance/formsCreate I-9 record (Section 1)

Create an I-9 record (Section 1). Cross-field validation: LPR requires alien_registration_number; authorized_alien requires at least one of A-Number / I-94 / passport+country. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Request body I9Section1CreateBodyrequired

FieldTypeRequiredDescription
employee_idstring · uuidrequired
citizenship_statusI9CitizenshipStatusrequired
section1_dataI9Section1Datarequired
ssnstringoptional

Responses

  • 201I-9 record createdI9RecordResponse
    FieldTypeRequiredDescription
    recordI9Recordrequired
  • 400Validation errorI9ValidationErrorResponse
  • 401UnauthorizedI9UnauthorizedResponse
  • 403Forbidden — CPA access requiredI9UnauthorizedResponse
  • 429Rate limit exceededI9RateLimitResponse
  • 500Server errorI9UnauthorizedResponse
GET/api/i9-compliance/{employeeId}Get employee I-9 detail

Get a single employee's I-9 details + uploaded documents. Falls back to payroll_pay_periods when employeeId is an SSN hash. cookie sessions: client_user is entity-scoped; CPA roles see all. Bearer keys gate via `notices.read` (full tenant access).

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
employeeIdpathstringrequiredEmployee UUID or SSN hash

Responses

  • 200Employee + documentsI9EmployeeDetailResponse
    FieldTypeRequiredDescription
    employeeI9EmployeeI9required
    documentsarray<I9DocumentRow>required
    sourceenum: "employees" | "payroll_pay_periods"required
  • 401UnauthorizedI9UnauthorizedResponse
  • 403Not authorized for this employee (entity-scope check)I9UnauthorizedResponse
  • 404Employee not foundI9NotFoundResponse
  • 429Rate limit exceededI9RateLimitResponse
  • 500Server errorI9UnauthorizedResponse
POST/api/i9-compliance/bulk-uploadBulk upload + match I-9 documents

Bulk upload up to 50 I-9 documents. Extracts employee names from filenames and fuzzy-matches against the active roster (entity-scoped for client_user; full tenant for CPA / Bearer keys with `notices.write`). Returns matched + unmatched results — does not persist files.

Bearer scopesnotices.write

Request body objectrequired

FieldTypeRequiredDescription
filesarray<string · binary>required

Responses

  • 200Match resultsI9BulkUploadResponse
    FieldTypeRequiredDescription
    totalintegerrequired
    matchedarray<I9BulkMatch>required
    unmatchedarray<I9BulkUnmatched>required
  • 400Validation errorI9ValidationErrorResponse
  • 401UnauthorizedI9UnauthorizedResponse
  • 429Rate limit exceededI9RateLimitResponse
  • 500Server errorI9UnauthorizedResponse
GET/api/i9-complianceList I-9 employees

List I-9 employee records for the caller's tenant + expiry stats. Falls back to payroll_pay_periods when no employees rows exist. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Responses

  • 200Employee list + expiry statsI9EmployeesListResponse
    FieldTypeRequiredDescription
    employeesarray<I9EmployeeListItem>required
    expiry_statsobjectoptional
    sourcestringoptional
    messagestringoptional
  • 401UnauthorizedI9UnauthorizedResponse
  • 429Rate limit exceededI9RateLimitResponse
  • 500Server errorI9UnauthorizedResponse
POST/api/i9-complianceCreate I-9 employee

Create a new I-9 employee record. Employer-only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Request body I9EmployeeCreateBodyrequired

FieldTypeRequiredDescription
employee_namestringrequired
hire_datestringrequired
entity_idstring · uuidrequired
emailstring · emailoptional
departmentstringoptional

Responses

  • 201Employee createdI9EmployeeCreateResponse
    FieldTypeRequiredDescription
    employeeI9EmployeeListItemrequired
  • 400Validation errorI9ValidationErrorResponse
  • 401UnauthorizedI9UnauthorizedResponse
  • 403Forbidden — employer access requiredI9UnauthorizedResponse
  • 404Entity not found in caller's tenantI9NotFoundResponse
  • 429Rate limit exceededI9RateLimitResponse
  • 500Server errorI9UnauthorizedResponse
  • 501Employees table not provisioned yetI9UnauthorizedResponse

KnowledgeBase1

GET/api/knowledge-baseQuery state compliance knowledge

Query the global state_compliance_knowledge table — Kreto-wide reference data covering state-by-state compliance rules, notice types, and deadlines. No tenant filter (read-only reference data). Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
statequerystringoptional
typequerystringoptional
qquerystringoptional
min_confidencequerynumberoptional
limitqueryintegeroptional
offsetqueryintegeroptional

Responses

  • 200Knowledge entries + summaryKnowledgeBaseResponse
    FieldTypeRequiredDescription
    entriesarray<KnowledgeBaseEntry>required
    totalintegerrequired
    summaryobjectrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

l2:annual-reports12

POST/v1/annual-reports.listAnnualReportRulesList the state annual-report catalog (global config): per-(state, entity_kind) SOS annual/biennial report rules with the verification ladder status of every cell and honest per-status counts. Cells below the display gate (human_reviewed) must never be rendered as authoritative to customers.

List the state annual-report catalog (global config): per-(state, entity_kind) SOS annual/biennial report rules with the verification ladder status of every cell and honest per-status counts. Cells below the display gate (human_reviewed) must never be rendered as authoritative to customers.

Cookie session or Bearer token

Request body AnnualReportsListAnnualReportRulesInputrequired

FieldTypeRequiredDescription
stateCodestringoptional
entityKindenum: "corporation" | "llc" | "nonprofit" | "lp" | …optional
verificationStatusenum: "unverified" | "human_reviewed" | "verified"optional

Responses

  • 200Successful invocationAnnualReportsListAnnualReportRulesOutput
    FieldTypeRequiredDescription
    rulesarray<object>required
    countsobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/annual-reports.getAnnualReportRuleFetch one annual-report catalog cell with the (state, entity_kind) → (state, 'default') fallback. Returns the human-readable due-rule narrative alongside the raw rule. Null rule = no catalog coverage yet.

Fetch one annual-report catalog cell with the (state, entity_kind) → (state, 'default') fallback. Returns the human-readable due-rule narrative alongside the raw rule. Null rule = no catalog coverage yet.

Cookie session or Bearer token

Request body AnnualReportsGetAnnualReportRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
entityKindenum: "corporation" | "llc" | "nonprofit" | "lp" | …optional

Responses

  • 200Successful invocationAnnualReportsGetAnnualReportRuleOutput
    FieldTypeRequiredDescription
    ruleobjectrequired
    usedDefaultFallbackbooleanrequired
    dueNarrativestringrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/annual-reports.proposeAnnualReportRuleResearch-agent write path for the annual-report catalog. Upserts one (state, entity_kind) cell as verification_status='unverified' with mandatory provenance (source_url + retrieved_at). REFUSES to touch a cell already at human_reviewed/verified — verified cells are never downgraded (AC-22 clone); corrections go through the review queue.

Research-agent write path for the annual-report catalog. Upserts one (state, entity_kind) cell as verification_status='unverified' with mandatory provenance (source_url + retrieved_at). REFUSES to touch a cell already at human_reviewed/verified — verified cells are never downgraded (AC-22 clone); corrections go through the review queue.

Cookie session or Bearer token

Request body AnnualReportsProposeAnnualReportRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
entityKindenum: "corporation" | "llc" | "nonprofit" | "lp" | …optional
agencyCodestringrequired
agencyNamestringrequired
portalUrlstring · urioptional
formNamestringoptional
filingFeeUsdnumberoptional
frequencyenum: "annual" | "biennial" | "decennial" | "none"required
dueRuleone of (object · object · object · object · object)required
parityenum: "odd" | "even" | "formation_year"optional
gracePeriodDaysintegeroptional
lateFeeNotesstringoptional
sourceUrlstring · urirequired
retrievedAtstring · date-timerequired
notesstringoptional

Responses

  • 200Successful invocationAnnualReportsProposeAnnualReportRuleOutput
    FieldTypeRequiredDescription
    ruleobjectrequired
    createdbooleanrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/annual-reports.promoteAnnualReportRulePromote an annual-report catalog cell along the verification ladder (unverified → human_reviewed → verified). APPROVAL_REQUIRED and UI-only: the handler rejects any non-human principal (AC-20 clone) and refuses cells with no source_url provenance (CWE-345).

Promote an annual-report catalog cell along the verification ladder (unverified → human_reviewed → verified). APPROVAL_REQUIRED and UI-only: the handler rejects any non-human principal (AC-20 clone) and refuses cells with no source_url provenance (CWE-345).

Cookie session or Bearer token

Request body AnnualReportsPromoteAnnualReportRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
entityKindenum: "corporation" | "llc" | "nonprofit" | "lp" | …optional
targetStatusenum: "human_reviewed" | "verified"required
reviewerEmailstring · emailrequired
reasonstringrequired

Responses

  • 200Successful invocationAnnualReportsPromoteAnnualReportRuleOutput
    FieldTypeRequiredDescription
    ruleobjectrequired
    fromStatusenum: "unverified" | "human_reviewed" | "verified"required
    toStatusenum: "unverified" | "human_reviewed" | "verified"required
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/annual-reports.listAnnualReportsList the tenant's annual-report tracker rows (per entity × state × filing period), filterable by entity, state, status and period. Paginated (default 25). Tenant-scoped via the invocation context.

List the tenant's annual-report tracker rows (per entity × state × filing period), filterable by entity, state, status and period. Paginated (default 25). Tenant-scoped via the invocation context.

Cookie session or Bearer token

Request body AnnualReportsListAnnualReportsInputrequired

FieldTypeRequiredDescription
entityIdstringoptional
stateCodestringoptional
statusenum: "pending" | "prepared" | "submitted" | "approved" | …optional
periodLabelstringoptional
limitintegeroptional
offsetintegeroptional

Responses

  • 200Successful invocationAnnualReportsListAnnualReportsOutput
    FieldTypeRequiredDescription
    reportsarray<object>required
    totalnumberrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/annual-reports.getAnnualReportByEntityFetch every annual-report tracker row for one entity (optionally one state), all periods — history plus in-flight. Tenant-scoped.

Fetch every annual-report tracker row for one entity (optionally one state), all periods — history plus in-flight. Tenant-scoped.

Cookie session or Bearer token

Request body AnnualReportsGetAnnualReportByEntityInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
stateCodestringoptional

Responses

  • 200Successful invocationAnnualReportsGetAnnualReportByEntityOutput
    FieldTypeRequiredDescription
    reportsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/annual-reports.computeAnnualReportScheduleDry-run compute of an entity's annual-report schedule for one period year (default: current year): per candidate state, the computed due date OR an explicit non-computed disposition (needs_input / needs_research / below_display_gate / not_required / not_due_this_period). Writes nothing — the sweep's cycle roller persists rows; this method answers 'what would be due?'.

Dry-run compute of an entity's annual-report schedule for one period year (default: current year): per candidate state, the computed due date OR an explicit non-computed disposition (needs_input / needs_research / below_display_gate / not_required / not_due_this_period). Writes nothing — the sweep's cycle roller persists rows; this method answers 'what would be due?'.

Cookie session or Bearer token

Request body AnnualReportsComputeAnnualReportScheduleInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
periodYearintegeroptional

Responses

  • 200Successful invocationAnnualReportsComputeAnnualReportScheduleOutput
    FieldTypeRequiredDescription
    entityIdstringrequired
    periodYearnumberrequired
    itemsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/annual-reports.createAnnualReportCreate one manual annual-report tracker row (source='manual') for an entity × state × period. Computes the due date from the display-gated catalog when possible; otherwise the row starts manual_required with a NULL due date ('Kreto needs your input'). Duplicate periods are rejected by the per-period UNIQUE.

Create one manual annual-report tracker row (source='manual') for an entity × state × period. Computes the due date from the display-gated catalog when possible; otherwise the row starts manual_required with a NULL due date ('Kreto needs your input'). Duplicate periods are rejected by the per-period UNIQUE.

Cookie session or Bearer token

Request body AnnualReportsCreateAnnualReportInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
stateCodestringrequired
periodLabelstringrequired
anchorKindenum: "formation" | "foreign_qualification" | "manual"optional
anchorDatestringoptional
notesstringoptional

Responses

  • 200Successful invocationAnnualReportsCreateAnnualReportOutput
    FieldTypeRequiredDescription
    reportobjectrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/annual-reports.updateAnnualReportMetadataEdit tracker metadata on one annual-report row: anchor date/kind (recomputes the due date from the display-gated catalog and flips manual_required → pending when a date becomes computable), assignee and notes. Writes a structured audit event capturing before/after.

Edit tracker metadata on one annual-report row: anchor date/kind (recomputes the due date from the display-gated catalog and flips manual_required → pending when a date becomes computable), assignee and notes. Writes a structured audit event capturing before/after.

Cookie session or Bearer token

Request body AnnualReportsUpdateAnnualReportMetadataInputrequired

FieldTypeRequiredDescription
annualReportIdstringrequired
anchorDatestringoptional
anchorKindenum: "formation" | "foreign_qualification" | "manual"optional
assigneestringoptional
notesstringoptional
reasonstringrequired

Responses

  • 200Successful invocationAnnualReportsUpdateAnnualReportMetadataOutput
    FieldTypeRequiredDescription
    reportobjectrequired
    changedFieldsarray<string>required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/annual-reports.prepareAnnualReportPopulate an annual report's prepared form payload (officers, principal address, the customer's OWN registered agent — Kreto is not the RA) and transition pending/manual_required → prepared. APPROVAL_REQUIRED: symmetric with prepareRegistrationForm; a human reviews before any filing. PII in form_payload is scrubbed from audit rows.

Populate an annual report's prepared form payload (officers, principal address, the customer's OWN registered agent — Kreto is not the RA) and transition pending/manual_required → prepared. APPROVAL_REQUIRED: symmetric with prepareRegistrationForm; a human reviews before any filing. PII in form_payload is scrubbed from audit rows.

Cookie session or Bearer token

Request body AnnualReportsPrepareAnnualReportInputrequired

FieldTypeRequiredDescription
annualReportIdstringrequired
formPayloadobjectrequired

Responses

  • 200Successful invocationAnnualReportsPrepareAnnualReportOutput
    FieldTypeRequiredDescription
    reportobjectrequired
    fromStatusenum: "pending" | "prepared" | "submitted" | "approved" | …required
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/annual-reports.requestConciergeFilingRecord the '$149 File it for me' concierge request on a prepared annual report: stamps filing_requested_at/by (design D3 — an annotation on 'prepared', not a status) and charges the $149 as a standalone Stripe invoice (created + finalized, so it bills every customer; owner 2026-07-10; fail-closed when STRIPE_SECRET_KEY is unset; double-bill safe). APPROVAL_REQUIRED: this moves money, so the v1 dispatcher blocks non-interactive API-key / MCP callers (KRT-1657) — it requires an interactive human session. The click by an authenticated CPA/owner IS the recorded filing authorization. The state filing fee is separate and paid to the state.

Record the '$149 File it for me' concierge request on a prepared annual report: stamps filing_requested_at/by (design D3 — an annotation on 'prepared', not a status) and charges the $149 as a standalone Stripe invoice (created + finalized, so it bills every customer; owner 2026-07-10; fail-closed when STRIPE_SECRET_KEY is unset; double-bill safe). APPROVAL_REQUIRED: this moves money, so the v1 dispatcher blocks non-interactive API-key / MCP callers (KRT-1657) — it requires an interactive human session. The click by an authenticated CPA/owner IS the recorded filing authorization. The state filing fee is separate and paid to the state.

Cookie session or Bearer token

Request body AnnualReportsRequestConciergeFilingInputrequired

FieldTypeRequiredDescription
annualReportIdstringrequired

Responses

  • 200Successful invocationAnnualReportsRequestConciergeFilingOutput
    FieldTypeRequiredDescription
    reportobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/annual-reports.transitionAnnualReportStatusApply a matrix-gated status transition to an annual-report tracker row (exact esr 7-status machine). Supports the mark-filed extras (confirmationNumber + filedAt on → submitted) and the confirmedImmediately chain (submitted → approved in one audited call for instant-confirm states). Every hop writes a hash-chained audit_events row.

Apply a matrix-gated status transition to an annual-report tracker row (exact esr 7-status machine). Supports the mark-filed extras (confirmationNumber + filedAt on → submitted) and the confirmedImmediately chain (submitted → approved in one audited call for instant-confirm states). Every hop writes a hash-chained audit_events row.

Cookie session or Bearer token

Request body AnnualReportsTransitionAnnualReportStatusInputrequired

FieldTypeRequiredDescription
annualReportIdstringrequired
newStatusenum: "pending" | "prepared" | "submitted" | "approved" | …required
reasonstringrequired
confirmationNumberstringoptional
filedAtstring · date-timeoptional
confirmedImmediatelybooleanoptional
lastErrorstringoptional

Responses

  • 200Successful invocationAnnualReportsTransitionAnnualReportStatusOutput
    FieldTypeRequiredDescription
    reportobjectrequired
    fromStatusenum: "pending" | "prepared" | "submitted" | "approved" | …required
    toStatusenum: "pending" | "prepared" | "submitted" | "approved" | …required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:audit1

POST/v1/audit.getRecentForRegistrationReturn recent service_audit_log rows linked to a specific state_registration row (via linked_resource_ids.registrationId). Tenant-scoped. AUTONOMOUS: append-only audit-table reads have no side effects.

Return recent service_audit_log rows linked to a specific state_registration row (via linked_resource_ids.registrationId). Tenant-scoped. AUTONOMOUS: append-only audit-table reads have no side effects.

Cookie session or Bearer token

Request body AuditGetRecentForRegistrationInputrequired

FieldTypeRequiredDescription
registrationIdstringrequired
limitintegeroptional

Responses

  • 200Successful invocationAuditGetRecentForRegistrationOutput
    FieldTypeRequiredDescription
    eventsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:business-license5

POST/v1/business-license.listLicensesList the business licenses and local permits tracked for the tenant (optionally filtered to one entity), soft-deleted rows excluded, ordered by soonest expiration. Read-only. Kreto tracks licenses the employer already holds — it does not discover, obtain, or renew them.

List the business licenses and local permits tracked for the tenant (optionally filtered to one entity), soft-deleted rows excluded, ordered by soonest expiration. Read-only. Kreto tracks licenses the employer already holds — it does not discover, obtain, or renew them.

Cookie session or Bearer token

Request body BusinessLicenseListLicensesInputrequired

FieldTypeRequiredDescription
entityIdstring · uuidoptional

Responses

  • 200Successful invocationBusinessLicenseListLicensesOutput
    FieldTypeRequiredDescription
    licensesarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/business-license.createLicenseRecord a business license or local permit the employer already holds (manual tracker entry). Verifies the target entity belongs to the caller's tenant, inserts the row, and appends a hash-chained business_license.created audit event. NOTIFY classification: agents can call but the action is logged for human review.

Record a business license or local permit the employer already holds (manual tracker entry). Verifies the target entity belongs to the caller's tenant, inserts the row, and appends a hash-chained business_license.created audit event. NOTIFY classification: agents can call but the action is logged for human review.

Cookie session or Bearer token

Request body BusinessLicenseCreateLicenseInputrequired

FieldTypeRequiredDescription
entityIdstring · uuidrequired
licenseNamestringrequired
licenseTypeenum: "state_business" | "city_business" | "county_business" | "professional" | …required
licenseNumberstringoptional
issuingAuthoritystringrequired
statestringoptional
jurisdictionstringoptional
statusenum: "active" | "expired" | "pending" | "suspended" | …optional
issuedDatestringoptional
expirationDatestringoptional
renewalDatestringoptional
renewalFeenumberoptional
autoRenewbooleanoptional
notesstringoptional

Responses

  • 200Successful invocationBusinessLicenseCreateLicenseOutput
    FieldTypeRequiredDescription
    licenseobjectrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/business-license.updateLicenseEdit a tracked business license. Absent key = unchanged, null = clear (where the column is nullable). Appends a hash-chained business_license.updated audit event carrying per-field old → new. No-op submits write nothing. NOTIFY classification: agents can call but the action is logged for human review.

Edit a tracked business license. Absent key = unchanged, null = clear (where the column is nullable). Appends a hash-chained business_license.updated audit event carrying per-field old → new. No-op submits write nothing. NOTIFY classification: agents can call but the action is logged for human review.

Cookie session or Bearer token

Request body BusinessLicenseUpdateLicenseInputrequired

FieldTypeRequiredDescription
licenseIdstring · uuidrequired
licenseNamestringoptional
licenseTypeenum: "state_business" | "city_business" | "county_business" | "professional" | …optional
licenseNumberstringoptional
issuingAuthoritystringoptional
statestringoptional
jurisdictionstringoptional
statusenum: "active" | "expired" | "pending" | "suspended" | …optional
issuedDatestringoptional
expirationDatestringoptional
renewalDatestringoptional
renewalFeenumberoptional
autoRenewbooleanoptional
notesstringoptional

Responses

  • 200Successful invocationBusinessLicenseUpdateLicenseOutput
    FieldTypeRequiredDescription
    licenseobjectrequired
    changedFieldsarray<string>required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/business-license.recordRenewalRecord a license renewal the employer/CPA already completed with the issuing authority: moves the license's expiration date, recomputes status, and appends a license_renewal_history row plus a hash-chained business_license.renewed audit event. Kreto never performs the renewal itself. NOTIFY classification: agents can call but the action is logged for human review.

Record a license renewal the employer/CPA already completed with the issuing authority: moves the license's expiration date, recomputes status, and appends a license_renewal_history row plus a hash-chained business_license.renewed audit event. Kreto never performs the renewal itself. NOTIFY classification: agents can call but the action is logged for human review.

Cookie session or Bearer token

Request body BusinessLicenseRecordRenewalInputrequired

FieldTypeRequiredDescription
licenseIdstring · uuidrequired
newExpirationDatestringrequired
renewalCostnumberoptional
confirmationNumberstringoptional
notesstringoptional

Responses

  • 200Successful invocationBusinessLicenseRecordRenewalOutput
    FieldTypeRequiredDescription
    licenseobjectrequired
    historyRecordedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/business-license.deleteLicenseSoft-delete a tracked business license (sets deleted_at; the row stays for audit). Pending renewal-alert idempotency rows CASCADE on hard delete only — soft-deleted rows simply stop matching the reminder scan. Appends a hash-chained business_license.deleted audit event. NOTIFY classification: agents can call but the action is logged for human review.

Soft-delete a tracked business license (sets deleted_at; the row stays for audit). Pending renewal-alert idempotency rows CASCADE on hard delete only — soft-deleted rows simply stop matching the reminder scan. Appends a hash-chained business_license.deleted audit event. NOTIFY classification: agents can call but the action is logged for human review.

Cookie session or Bearer token

Request body BusinessLicenseDeleteLicenseInputrequired

FieldTypeRequiredDescription
licenseIdstring · uuidrequired

Responses

  • 200Successful invocationBusinessLicenseDeleteLicenseOutput
    FieldTypeRequiredDescription
    licenseIdstringrequired
    deletedAtstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:cpa4

POST/v1/cpa.listEmployersList the CPA's linked employers (entities) with per-employer notice counts. Paginated via `limit` (1-100, default 25) and zero-indexed `offset`. Optional case-insensitive `search` filters on legal_name. Tenant-scoped. Returns aggregates only — no PII (no signer info, no employee names, no notice subjects).

List the CPA's linked employers (entities) with per-employer notice counts. Paginated via `limit` (1-100, default 25) and zero-indexed `offset`. Optional case-insensitive `search` filters on legal_name. Tenant-scoped. Returns aggregates only — no PII (no signer info, no employee names, no notice subjects).

Cookie session or Bearer token

Request body CpaListEmployersInputrequired

FieldTypeRequiredDescription
limitintegeroptional
offsetintegeroptional
searchstringoptional

Responses

  • 200Successful invocationCpaListEmployersOutput
    FieldTypeRequiredDescription
    employersarray<object>required
    totalintegerrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/cpa.summarizeComplianceAggregate the CPA tenant's compliance posture: notice counts by status, per-employer rollup, fines (total/paid/outstanding cents), and response-time average. Tenant-scoped. Returns aggregates only — no PII.

Aggregate the CPA tenant's compliance posture: notice counts by status, per-employer rollup, fines (total/paid/outstanding cents), and response-time average. Tenant-scoped. Returns aggregates only — no PII.

Cookie session or Bearer token

Request body CpaSummarizeComplianceInputrequired

application/json

Responses

  • 200Successful invocationCpaSummarizeComplianceOutput
    FieldTypeRequiredDescription
    generated_atstringrequired
    tenant_idstringrequired
    noticesobjectrequired
    per_entityarray<object>required
    finesobjectrequired
    response_timeobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/cpa.queryAuditEventsQuery the tenant's audit event timeline. Paginated via `limit` (1-100, default 25) and zero-indexed `offset`. Optional filters: `entity_id` (UUID), `notice_id` (UUID), `event_type` (exact match e.g. 'notice_created'), `since`/`until` (ISO datetimes). Tenant-scoped. `detail` is PII-redacted (SSN/EIN/bank patterns replaced) and capped at 500 chars. Metadata + integrity-chain columns are NOT returned.

Query the tenant's audit event timeline. Paginated via `limit` (1-100, default 25) and zero-indexed `offset`. Optional filters: `entity_id` (UUID), `notice_id` (UUID), `event_type` (exact match e.g. 'notice_created'), `since`/`until` (ISO datetimes). Tenant-scoped. `detail` is PII-redacted (SSN/EIN/bank patterns replaced) and capped at 500 chars. Metadata + integrity-chain columns are NOT returned.

Cookie session or Bearer token

Request body CpaQueryAuditEventsInputrequired

FieldTypeRequiredDescription
limitintegeroptional
offsetintegeroptional
entity_idstring · uuidoptional
notice_idstring · uuidoptional
event_typestringoptional
sincestring · date-timeoptional
untilstring · date-timeoptional

Responses

  • 200Successful invocationCpaQueryAuditEventsOutput
    FieldTypeRequiredDescription
    eventsarray<object>required
    totalintegerrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/cpa.summarizeObligationsAggregate compliance-obligations rollup across the CPA's employer book. Paginated via `limit` (1-100, default 25) and zero-indexed `offset`; optional case-insensitive `search` on legal_name. For each employer: applicable / low-confidence / pending-data obligation counts plus the earliest computable due date; firm-wide totals included. Tenant-scoped. Returns aggregates only — no PII (no employee data, no wages, no notice subjects).

Aggregate compliance-obligations rollup across the CPA's employer book. Paginated via `limit` (1-100, default 25) and zero-indexed `offset`; optional case-insensitive `search` on legal_name. For each employer: applicable / low-confidence / pending-data obligation counts plus the earliest computable due date; firm-wide totals included. Tenant-scoped. Returns aggregates only — no PII (no employee data, no wages, no notice subjects).

Cookie session or Bearer token

Request body CpaSummarizeObligationsInputrequired

FieldTypeRequiredDescription
limitintegeroptional
offsetintegeroptional
searchstringoptional

Responses

  • 200Successful invocationCpaSummarizeObligationsOutput
    FieldTypeRequiredDescription
    per_entityarray<object>required
    totalsobjectrequired
    totalintegerrequired
    generated_atstringrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:cpa-team-invitations5

POST/v1/cpa-team-invitations.createInvitationCreate a firm team-invitation row, generate a single-use accept token, and send the invite email. Returns plaintext accept_url ONCE. Only firm_admin/system_admin may call.

Create a firm team-invitation row, generate a single-use accept token, and send the invite email. Returns plaintext accept_url ONCE. Only firm_admin/system_admin may call.

Cookie session or Bearer token

Request body CpaTeamInvitationsCreateInvitationInputrequired

FieldTypeRequiredDescription
emailstring · emailrequired
invited_roleenum: "cpa_member" | "staff"required

Responses

  • 200Successful invocationCpaTeamInvitationsCreateInvitationOutput
    FieldTypeRequiredDescription
    invitationobjectrequired
    accept_urlstring · urirequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/cpa-team-invitations.listInvitationsList firm team invitations for the caller's tenant. Never returns plaintext tokens or token hashes.

List firm team invitations for the caller's tenant. Never returns plaintext tokens or token hashes.

Cookie session or Bearer token

Request body CpaTeamInvitationsListInvitationsInputrequired

FieldTypeRequiredDescription
statusenum: "pending" | "accepted" | "revoked" | "expired"optional

Responses

  • 200Successful invocationCpaTeamInvitationsListInvitationsOutput
    FieldTypeRequiredDescription
    invitationsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/cpa-team-invitations.revokeInvitationRevoke a pending firm invitation. Idempotent for already-revoked/accepted rows (returns current status). Only firm_admin/system_admin may revoke.

Revoke a pending firm invitation. Idempotent for already-revoked/accepted rows (returns current status). Only firm_admin/system_admin may revoke.

Cookie session or Bearer token

Request body CpaTeamInvitationsRevokeInvitationInputrequired

FieldTypeRequiredDescription
invitation_idstring · uuidrequired

Responses

  • 200Successful invocationCpaTeamInvitationsRevokeInvitationOutput
    FieldTypeRequiredDescription
    idstring · uuidrequired
    statusstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/cpa-team-invitations.acceptInvitationAccept a firm team invitation. Verifies token, expiry, self-acceptance and email-mismatch guards. Grants user_profiles.role + a portal_roles row on success. The caller MUST be signed in as the invited email.

Accept a firm team invitation. Verifies token, expiry, self-acceptance and email-mismatch guards. Grants user_profiles.role + a portal_roles row on success. The caller MUST be signed in as the invited email.

Cookie session or Bearer token

Request body CpaTeamInvitationsAcceptInvitationInputrequired

FieldTypeRequiredDescription
tokenstringrequired

Responses

  • 200Successful invocationCpaTeamInvitationsAcceptInvitationOutput
    FieldTypeRequiredDescription
    invitation_idstring · uuidrequired
    invited_rolestringrequired
    role_grantedbooleanrequired
    existing_role_preservedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/cpa-team-invitations.getInvitationByTokenPublic lookup by plaintext token (hashes on read; never returns hash or plaintext). Used by /accept-cpa-invite/[token] for render.

Public lookup by plaintext token (hashes on read; never returns hash or plaintext). Used by /accept-cpa-invite/[token] for render.

Cookie session or Bearer token

Request body CpaTeamInvitationsGetInvitationByTokenInputrequired

FieldTypeRequiredDescription
tokenstringrequired

Responses

  • 200Successful invocationCpaTeamInvitationsGetInvitationByTokenOutput
    FieldTypeRequiredDescription
    invitationobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:credential-vault15

POST/v1/credential-vault.createCredentialCreate a tax account credential. Plaintext password / mfaSecret fields are written to Supabase Vault (vault.secrets) and the returned secret IDs are stored on tax_account_credentials. APPROVAL_REQUIRED — agents must not invoke this without HITL.

Create a tax account credential. Plaintext password / mfaSecret fields are written to Supabase Vault (vault.secrets) and the returned secret IDs are stored on tax_account_credentials. APPROVAL_REQUIRED — agents must not invoke this without HITL.

Cookie session or Bearer token

Request body CredentialVaultCreateCredentialInputrequired

FieldTypeRequiredDescription
employerEntityIdstringrequired
agencyIdstringrequired
accountNumberstringoptional
loginUsernamestringoptional
passwordstringoptional
mfaSecretstringoptional
backupCodesstringoptional
notesstringoptional
otpChannelenum: "none" | "totp" | "email" | "sms"optional

Responses

  • 200Successful invocationCredentialVaultCreateCredentialOutput
    FieldTypeRequiredDescription
    idstringrequired
    tenant_idstringrequired
    employer_entity_idstringrequired
    agency_idstringrequired
    account_numberstringrequired
    login_usernamestringrequired
    has_passwordbooleanrequired
    has_mfa_secretbooleanrequired
    has_backup_codesbooleanrequired
    last_login_atstringrequired
    last_password_change_atstringrequired
    refresh_required_bystringrequired
    statusenum: "active" | "revoked" | "refresh_required" | "locked"required
    notesstringrequired
    created_atstringrequired
    updated_atstringrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.getCredentialFetch a credential by id, including plaintext password and mfaSecret decrypted from Supabase Vault. APPROVAL_REQUIRED. The returned plaintext fields are named `password` / `mfaSecret` (camelCase, matching framework SENSITIVE_KEYS) so the audit row's outputs JSONB shows them as [redacted] while the live caller receives the actual plaintext (R13 mitigation).

Fetch a credential by id, including plaintext password and mfaSecret decrypted from Supabase Vault. APPROVAL_REQUIRED. The returned plaintext fields are named `password` / `mfaSecret` (camelCase, matching framework SENSITIVE_KEYS) so the audit row's outputs JSONB shows them as [redacted] while the live caller receives the actual plaintext (R13 mitigation).

Cookie session or Bearer token

Request body CredentialVaultGetCredentialInputrequired

FieldTypeRequiredDescription
credentialIdstringrequired
purposestringrequired

Responses

  • 200Successful invocationCredentialVaultGetCredentialOutput
    FieldTypeRequiredDescription
    idstringrequired
    tenant_idstringrequired
    employer_entity_idstringrequired
    agency_idstringrequired
    account_numberstringrequired
    login_usernamestringrequired
    has_passwordbooleanrequired
    has_mfa_secretbooleanrequired
    has_backup_codesbooleanrequired
    last_login_atstringrequired
    last_password_change_atstringrequired
    refresh_required_bystringrequired
    statusenum: "active" | "revoked" | "refresh_required" | "locked"required
    notesstringrequired
    created_atstringrequired
    updated_atstringrequired
    passwordstringrequired
    mfaSecretstringrequired
    backupCodesstringrequired
    health_check_auto_flipbooleanoptional
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.getCredentialByEntityResolve and fetch a credential by (tenantId, entityId, agencyId) lookup, returning plaintext password and mfaSecret. The 3-tuple is index-served by tac_unique_active_per_agency. Throws if no active credential matches. APPROVAL_REQUIRED. Plaintext fields are camelCase-named (`password`, `mfaSecret`) so the audit row's outputs JSONB shows them as [redacted] (R13 mitigation).

Resolve and fetch a credential by (tenantId, entityId, agencyId) lookup, returning plaintext password and mfaSecret. The 3-tuple is index-served by tac_unique_active_per_agency. Throws if no active credential matches. APPROVAL_REQUIRED. Plaintext fields are camelCase-named (`password`, `mfaSecret`) so the audit row's outputs JSONB shows them as [redacted] (R13 mitigation).

Cookie session or Bearer token

Request body CredentialVaultGetCredentialByEntityInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
agencyIdstringrequired
purposestringrequired

Responses

  • 200Successful invocationCredentialVaultGetCredentialByEntityOutput
    FieldTypeRequiredDescription
    idstringrequired
    tenant_idstringrequired
    employer_entity_idstringrequired
    agency_idstringrequired
    account_numberstringrequired
    login_usernamestringrequired
    has_passwordbooleanrequired
    has_mfa_secretbooleanrequired
    has_backup_codesbooleanrequired
    last_login_atstringrequired
    last_password_change_atstringrequired
    refresh_required_bystringrequired
    statusenum: "active" | "revoked" | "refresh_required" | "locked"required
    notesstringrequired
    created_atstringrequired
    updated_atstringrequired
    passwordstringrequired
    mfaSecretstringrequired
    backupCodesstringrequired
    health_check_auto_flipbooleanoptional
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.listCredentialsList credentials in the caller's tenant. Returns metadata only (no plaintext, no vault secret_ids). AUTONOMOUS — agents may call freely. Pass `entityId` to scope to a single employer; pass `statuses` to widen beyond the default `active` filter.

List credentials in the caller's tenant. Returns metadata only (no plaintext, no vault secret_ids). AUTONOMOUS — agents may call freely. Pass `entityId` to scope to a single employer; pass `statuses` to widen beyond the default `active` filter.

Cookie session or Bearer token

Request body CredentialVaultListCredentialsInputrequired

FieldTypeRequiredDescription
entityIdstringoptional
statusesarray<enum: "active" | "revoked" | "refresh_required" | "locked">optional

Responses

  • 200Successful invocationCredentialVaultListCredentialsOutput
    FieldTypeRequiredDescription
    credentialsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.listCredentialsExpiringSoonList active credentials whose refresh_required_by falls within the next `daysAhead` days. Used by the auto-refresh job (plan §6 D4). AUTONOMOUS.

List active credentials whose refresh_required_by falls within the next `daysAhead` days. Used by the auto-refresh job (plan §6 D4). AUTONOMOUS.

Cookie session or Bearer token

Request body CredentialVaultListCredentialsExpiringSoonInputrequired

FieldTypeRequiredDescription
daysAheadintegerrequired

Responses

  • 200Successful invocationCredentialVaultListCredentialsExpiringSoonOutput
    FieldTypeRequiredDescription
    credentialsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.updateCredentialUpdate credential metadata and/or rotate plaintext password / mfaSecret. APPROVAL_REQUIRED. Plaintext rotations go through vault.update_secret; the secret_id on the credential row is preserved so audit trails remain stable.

Update credential metadata and/or rotate plaintext password / mfaSecret. APPROVAL_REQUIRED. Plaintext rotations go through vault.update_secret; the secret_id on the credential row is preserved so audit trails remain stable.

Cookie session or Bearer token

Request body CredentialVaultUpdateCredentialInputrequired

FieldTypeRequiredDescription
credentialIdstringrequired
patchobjectrequired

Responses

  • 200Successful invocationCredentialVaultUpdateCredentialOutput
    FieldTypeRequiredDescription
    idstringrequired
    tenant_idstringrequired
    employer_entity_idstringrequired
    agency_idstringrequired
    account_numberstringrequired
    login_usernamestringrequired
    has_passwordbooleanrequired
    has_mfa_secretbooleanrequired
    has_backup_codesbooleanrequired
    last_login_atstringrequired
    last_password_change_atstringrequired
    refresh_required_bystringrequired
    statusenum: "active" | "revoked" | "refresh_required" | "locked"required
    notesstringrequired
    created_atstringrequired
    updated_atstringrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.revokeCredentialSet status='revoked' on a credential AND overwrite the plaintext in Supabase Vault with a tombstone marker. The vault secret_ids stay on the credential row so the audit trail can resolve which credential a historical event referenced, but the actual plaintext is unrecoverable after revoke. Aligns with GDPR Art. 17 / CCPA right-to-erasure. APPROVAL_REQUIRED. PR #466 review Bug 4.

Set status='revoked' on a credential AND overwrite the plaintext in Supabase Vault with a tombstone marker. The vault secret_ids stay on the credential row so the audit trail can resolve which credential a historical event referenced, but the actual plaintext is unrecoverable after revoke. Aligns with GDPR Art. 17 / CCPA right-to-erasure. APPROVAL_REQUIRED. PR #466 review Bug 4.

Cookie session or Bearer token

Request body CredentialVaultRevokeCredentialInputrequired

FieldTypeRequiredDescription
credentialIdstringrequired

Responses

  • 200Successful invocationCredentialVaultRevokeCredentialOutput
    FieldTypeRequiredDescription
    idstringrequired
    tenant_idstringrequired
    employer_entity_idstringrequired
    agency_idstringrequired
    account_numberstringrequired
    login_usernamestringrequired
    has_passwordbooleanrequired
    has_mfa_secretbooleanrequired
    has_backup_codesbooleanrequired
    last_login_atstringrequired
    last_password_change_atstringrequired
    refresh_required_bystringrequired
    statusenum: "active" | "revoked" | "refresh_required" | "locked"required
    notesstringrequired
    created_atstringrequired
    updated_atstringrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.markRefreshRequiredFlip a credential to status='refresh_required' and set refresh_required_by=now(). Lighter-risk than other write methods because no plaintext is touched — just state. NOTIFY.

Flip a credential to status='refresh_required' and set refresh_required_by=now(). Lighter-risk than other write methods because no plaintext is touched — just state. NOTIFY.

Cookie session or Bearer token

Request body CredentialVaultMarkRefreshRequiredInputrequired

FieldTypeRequiredDescription
credentialIdstringrequired

Responses

  • 200Successful invocationCredentialVaultMarkRefreshRequiredOutput
    FieldTypeRequiredDescription
    idstringrequired
    tenant_idstringrequired
    employer_entity_idstringrequired
    agency_idstringrequired
    account_numberstringrequired
    login_usernamestringrequired
    has_passwordbooleanrequired
    has_mfa_secretbooleanrequired
    has_backup_codesbooleanrequired
    last_login_atstringrequired
    last_password_change_atstringrequired
    refresh_required_bystringrequired
    statusenum: "active" | "revoked" | "refresh_required" | "locked"required
    notesstringrequired
    created_atstringrequired
    updated_atstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.getCurrentOtpReturn the current RFC-6238 TOTP code for a credential's stored authenticator (MFA) seed, plus seconds remaining in the period. Returns { code: null, secondsRemaining: 0 } when the credential has no stored MFA seed. APPROVAL_REQUIRED — it reads decrypted credential auth material from the vault.

Return the current RFC-6238 TOTP code for a credential's stored authenticator (MFA) seed, plus seconds remaining in the period. Returns { code: null, secondsRemaining: 0 } when the credential has no stored MFA seed. APPROVAL_REQUIRED — it reads decrypted credential auth material from the vault.

Cookie session or Bearer token

Request body CredentialVaultGetCurrentOtpInputrequired

FieldTypeRequiredDescription
credentialIdstringrequired

Responses

  • 200Successful invocationCredentialVaultGetCurrentOtpOutput
    FieldTypeRequiredDescription
    codestringrequired
    secondsRemainingintegerrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.getHealthCheckPolicyRead the per-agency health-check status-mutation policy for the caller's tenant. AUTONOMOUS — read-only config. Returns statusMutationEnabled=false (record-only, the safe default) when no policy row exists for the agency.

Read the per-agency health-check status-mutation policy for the caller's tenant. AUTONOMOUS — read-only config. Returns statusMutationEnabled=false (record-only, the safe default) when no policy row exists for the agency.

Cookie session or Bearer token

Request body CredentialVaultGetHealthCheckPolicyInputrequired

FieldTypeRequiredDescription
agencyIdstringrequired

Responses

  • 200Successful invocationCredentialVaultGetHealthCheckPolicyOutput
    FieldTypeRequiredDescription
    agencyIdstringrequired
    statusMutationEnabledbooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.setHealthCheckPolicyEnable/disable health-check status auto-flip for one agency in the caller's tenant. NOTIFY — a config write that should be human-visible. Enable only for portals whose invalidSignal coverage is proven (un-hardened portals stay record-only). Upserts the per-(tenant, agency) policy row.

Enable/disable health-check status auto-flip for one agency in the caller's tenant. NOTIFY — a config write that should be human-visible. Enable only for portals whose invalidSignal coverage is proven (un-hardened portals stay record-only). Upserts the per-(tenant, agency) policy row.

Cookie session or Bearer token

Request body CredentialVaultSetHealthCheckPolicyInputrequired

FieldTypeRequiredDescription
agencyIdstringrequired
statusMutationEnabledbooleanrequired

Responses

  • 200Successful invocationCredentialVaultSetHealthCheckPolicyOutput
    FieldTypeRequiredDescription
    agencyIdstringrequired
    statusMutationEnabledbooleanrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.useUse a stored credential BY REFERENCE to drive an authenticated portal login: dispatches the portal-execution job and returns the job id only. The plaintext secret is decrypted exclusively inside the portal worker and never appears in this method's output. Use when a filing or protest flow needs an authenticated portal session.

Use a stored credential BY REFERENCE to drive an authenticated portal login: dispatches the portal-execution job and returns the job id only. The plaintext secret is decrypted exclusively inside the portal worker and never appears in this method's output. Use when a filing or protest flow needs an authenticated portal session.

Cookie session or Bearer token

Request body CredentialVaultUseInputrequired

FieldTypeRequiredDescription
credentialIdstringrequired
purposestringrequired
dedupeTokenstringrequired

Responses

  • 200Successful invocationCredentialVaultUseOutput
    FieldTypeRequiredDescription
    jobIdstringrequired
    deduplicatedbooleanrequired
    credentialIdstringrequired
    agencyIdstringrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.rotateRotate a stored portal password BY REFERENCE: dispatches the transactional rotation job (login, change-password, verify-login in one governed session) and returns the job id only. The new secret is generated inside the worker and never appears anywhere outside the vault and the portal DOM. Use when a credential is suspected compromised or a portal's password-age policy requires a change.

Rotate a stored portal password BY REFERENCE: dispatches the transactional rotation job (login, change-password, verify-login in one governed session) and returns the job id only. The new secret is generated inside the worker and never appears anywhere outside the vault and the portal DOM. Use when a credential is suspected compromised or a portal's password-age policy requires a change.

Cookie session or Bearer token

Request body CredentialVaultRotateInputrequired

FieldTypeRequiredDescription
credentialIdstringrequired
reasonstringoptional

Responses

  • 200Successful invocationCredentialVaultRotateOutput
    FieldTypeRequiredDescription
    jobIdstringrequired
    deduplicatedbooleanrequired
    credentialIdstringrequired
    agencyIdstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.healthReport a credential's login health from the latest lockout-aware scheduled probe (the hourly health cron is the only thing that actually logs in — this read never touches the portal, so it can never contribute to a lockout). Use to surface which credentials need attention before relying on one for a filing. 'uncertain' means no probe evidence — never treat it as healthy.

Report a credential's login health from the latest lockout-aware scheduled probe (the hourly health cron is the only thing that actually logs in — this read never touches the portal, so it can never contribute to a lockout). Use to surface which credentials need attention before relying on one for a filing. 'uncertain' means no probe evidence — never treat it as healthy.

Cookie session or Bearer token

Request body CredentialVaultHealthInputrequired

FieldTypeRequiredDescription
credentialIdstringrequired

Responses

  • 200Successful invocationCredentialVaultHealthOutput
    FieldTypeRequiredDescription
    credentialIdstringrequired
    statusstringrequired
    healthenum: "pass" | "fail" | "uncertain"required
    lastHealthCheckAtstringrequired
    lastHealthCheckOutcomestringrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/credential-vault.revealReveal a credential's plaintext to an authorized human screen. Requires a typed reason and passes the account's reveal-visibility policy for VAULT_V1 tenants; the hash-chained evidence row is written BEFORE decryption and the reveal is refused if it cannot be. APPROVAL_REQUIRED — UI-only, never exposed via MCP or CLI.

Reveal a credential's plaintext to an authorized human screen. Requires a typed reason and passes the account's reveal-visibility policy for VAULT_V1 tenants; the hash-chained evidence row is written BEFORE decryption and the reveal is refused if it cannot be. APPROVAL_REQUIRED — UI-only, never exposed via MCP or CLI.

Cookie session or Bearer token

Request body CredentialVaultRevealInputrequired

FieldTypeRequiredDescription
credentialIdstringrequired
reasonstringoptional
ipAddressstringoptional
userAgentstringoptional

Responses

  • 200Successful invocationCredentialVaultRevealOutput
    FieldTypeRequiredDescription
    idstringrequired
    tenant_idstringrequired
    employer_entity_idstringrequired
    agency_idstringrequired
    account_numberstringrequired
    login_usernamestringrequired
    has_passwordbooleanrequired
    has_mfa_secretbooleanrequired
    has_backup_codesbooleanrequired
    last_login_atstringrequired
    last_password_change_atstringrequired
    refresh_required_bystringrequired
    statusenum: "active" | "revoked" | "refresh_required" | "locked"required
    notesstringrequired
    created_atstringrequired
    updated_atstringrequired
    passwordstringrequired
    mfaSecretstringrequired
    backupCodesstringrequired
    health_check_auto_flipbooleanoptional
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:edelivery10

POST/v1/edelivery.listEdeliveryRulesBrowse the e-delivery catalog (state_edelivery_rules, global config — NO tenant filter). Optional filters: stateCode, requirementType, verificationStatus. Returns matching rows plus HONEST per-status counts ({unverified, human_reviewed, verified}) — never a 'done/complete' claim. AUTONOMOUS, read-only.

Browse the e-delivery catalog (state_edelivery_rules, global config — NO tenant filter). Optional filters: stateCode, requirementType, verificationStatus. Returns matching rows plus HONEST per-status counts ({unverified, human_reviewed, verified}) — never a 'done/complete' claim. AUTONOMOUS, read-only.

Cookie session or Bearer token

Request body EdeliveryListEdeliveryRulesInputrequired

FieldTypeRequiredDescription
stateCodestringoptional
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …optional
verificationStatusenum: "unverified" | "human_reviewed" | "verified"optional

Responses

  • 200Successful invocationEdeliveryListEdeliveryRulesOutput
    FieldTypeRequiredDescription
    rowsarray<object>required
    countsobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/edelivery.getEdeliveryRuleRead one e-delivery catalog cell (state_edelivery_rules, global config — NO tenant filter): the rule row plus its typed ordered enrollment steps. Cell absent → honest null + [] (never invented data). AUTONOMOUS, read-only.

Read one e-delivery catalog cell (state_edelivery_rules, global config — NO tenant filter): the rule row plus its typed ordered enrollment steps. Cell absent → honest null + [] (never invented data). AUTONOMOUS, read-only.

Cookie session or Bearer token

Request body EdeliveryGetEdeliveryRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required

Responses

  • 200Successful invocationEdeliveryGetEdeliveryRuleOutput
    FieldTypeRequiredDescription
    ruleobjectrequired
    stepsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/edelivery.proposeEdeliveryRuleResearch one (state, requirement) cell's PAPERLESS/e-delivery facts via the Claude + web_search agent and upsert an UNVERIFIED proposal onto state_edelivery_rules BY PK (global config — NO tenant filter). The write ALWAYS leaves verification_status='unverified' and NEVER sets verified/human_reviewed (agents may never verify); writes provenance (source_url + retrieved_at); idempotent-by-PK. MUST NOT downgrade a human-verified cell: returns the existing row + the fresh proposal so a human can compare. PII-free. NOTIFY: agents may call; a human reviews before promotion.

Research one (state, requirement) cell's PAPERLESS/e-delivery facts via the Claude + web_search agent and upsert an UNVERIFIED proposal onto state_edelivery_rules BY PK (global config — NO tenant filter). The write ALWAYS leaves verification_status='unverified' and NEVER sets verified/human_reviewed (agents may never verify); writes provenance (source_url + retrieved_at); idempotent-by-PK. MUST NOT downgrade a human-verified cell: returns the existing row + the fresh proposal so a human can compare. PII-free. NOTIFY: agents may call; a human reviews before promotion.

Cookie session or Bearer token

Request body EdeliveryProposeEdeliveryRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required

Responses

  • 200Successful invocationEdeliveryProposeEdeliveryRuleOutput
    FieldTypeRequiredDescription
    rowobjectrequired
    proposalobjectrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/edelivery.promoteEdeliveryRuleHuman gate: promote an e-delivery cell along the verification ladder (unverified → human_reviewed → verified). APPROVAL_REQUIRED, UI-only — excluded from MCP/CLI, and the handler REJECTS any non-human principal before any write. Verifying requires provenance (source_url + retrieved_at). Stamps reviewed_by / last_reviewed_at, and on verify also verified_at / verified_by.

Human gate: promote an e-delivery cell along the verification ladder (unverified → human_reviewed → verified). APPROVAL_REQUIRED, UI-only — excluded from MCP/CLI, and the handler REJECTS any non-human principal before any write. Verifying requires provenance (source_url + retrieved_at). Stamps reviewed_by / last_reviewed_at, and on verify also verified_at / verified_by.

Cookie session or Bearer token

Request body EdeliveryPromoteEdeliveryRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required
toStatusenum: "human_reviewed" | "verified"required
reasonstringoptional

Responses

  • 200Successful invocationEdeliveryPromoteEdeliveryRuleOutput
    FieldTypeRequiredDescription
    stateCodestringrequired
    requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required
    fromStatusenum: "unverified" | "human_reviewed" | "verified"required
    toStatusenum: "unverified" | "human_reviewed" | "verified"required
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/edelivery.listEdeliveryEnrollmentsList the per-entity e-delivery enrollment checklist (tenant+entity scoped), idempotently seeding missing (state, requirement) items from the employer's footprint (employer_state_registrations + states_operated; v1 scope = SUI + withholding). Each item carries its catalog cell's facts FAIL-CLOSED: enrollment steps are attached ONLY when the cell is verified — unverified facts never render as authoritative. AUTONOMOUS, read-mostly.

List the per-entity e-delivery enrollment checklist (tenant+entity scoped), idempotently seeding missing (state, requirement) items from the employer's footprint (employer_state_registrations + states_operated; v1 scope = SUI + withholding). Each item carries its catalog cell's facts FAIL-CLOSED: enrollment steps are attached ONLY when the cell is verified — unverified facts never render as authoritative. AUTONOMOUS, read-mostly.

Cookie session or Bearer token

Request body EdeliveryListEdeliveryEnrollmentsInputrequired

FieldTypeRequiredDescription
entityIdstringrequired

Responses

  • 200Successful invocationEdeliveryListEdeliveryEnrollmentsOutput
    FieldTypeRequiredDescription
    entityIdstringrequired
    intakeEmailstringrequired
    itemsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/edelivery.listEdeliveryEnrollmentsReadonlyRead an entity's e-delivery enrollment checklist WITHOUT seeding (the employer-portal spectator view). Returns the persisted items the CPA/Kreto-ops maintains, each with its catalog facts FAIL-CLOSED: authoritative steps only on verified cells, unverified steps under `draftSteps` for the 'unverified draft' banner. AUTONOMOUS, read-only.

Read an entity's e-delivery enrollment checklist WITHOUT seeding (the employer-portal spectator view). Returns the persisted items the CPA/Kreto-ops maintains, each with its catalog facts FAIL-CLOSED: authoritative steps only on verified cells, unverified steps under `draftSteps` for the 'unverified draft' banner. AUTONOMOUS, read-only.

Cookie session or Bearer token

Request body EdeliveryListEdeliveryEnrollmentsReadonlyInputrequired

FieldTypeRequiredDescription
entityIdstringrequired

Responses

  • 200Successful invocationEdeliveryListEdeliveryEnrollmentsReadonlyOutput
    FieldTypeRequiredDescription
    entityIdstringrequired
    intakeEmailstringrequired
    itemsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/edelivery.setEnrollmentStatusSet one e-delivery checklist item's status (not_started | enrolled) with human attribution (completed_by = the session user on enroll). Tenant+entity scoped. Appends a hash-chained audit_events row — enrollment status is a compliance-posture claim. NOTIFY. The customer performed the enrollment in the agency portal; Kreto only records it.

Set one e-delivery checklist item's status (not_started | enrolled) with human attribution (completed_by = the session user on enroll). Tenant+entity scoped. Appends a hash-chained audit_events row — enrollment status is a compliance-posture claim. NOTIFY. The customer performed the enrollment in the agency portal; Kreto only records it.

Cookie session or Bearer token

Request body EdeliverySetEnrollmentStatusInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
itemIdstringrequired
statusenum: "not_started" | "enrolled"required

Responses

  • 200Successful invocationEdeliverySetEnrollmentStatusOutput
    FieldTypeRequiredDescription
    itemIdstringrequired
    stateCodestringrequired
    requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required
    statusenum: "not_started" | "enrolled"required
    completedAtstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/edelivery.listFetchQueueList the tenant's OPEN Portal-pickup tasks: inbound agency notification emails ('you have new correspondence — log in') that carried no document (inbound_emails processing_status='notification_only', unresolved). Optional entityId filter. The row IS the task — a notice is only ever created when the fetched document arrives. AUTONOMOUS, read-only.

List the tenant's OPEN Portal-pickup tasks: inbound agency notification emails ('you have new correspondence — log in') that carried no document (inbound_emails processing_status='notification_only', unresolved). Optional entityId filter. The row IS the task — a notice is only ever created when the fetched document arrives. AUTONOMOUS, read-only.

Cookie session or Bearer token

Request body EdeliveryListFetchQueueInputrequired

FieldTypeRequiredDescription
entityIdstringoptional

Responses

  • 200Successful invocationEdeliveryListFetchQueueOutput
    FieldTypeRequiredDescription
    tasksarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/edelivery.resolveFetchTaskResolve one Portal-pickup task (inbound_emails processing_status='notification_only'): stamps resolved_at/resolved_by and optionally back-links the notice created when the customer fetched the document (the noticeId must belong to the caller's tenant). Tenant-scoped. NOTIFY.

Resolve one Portal-pickup task (inbound_emails processing_status='notification_only'): stamps resolved_at/resolved_by and optionally back-links the notice created when the customer fetched the document (the noticeId must belong to the caller's tenant). Tenant-scoped. NOTIFY.

Cookie session or Bearer token

Request body EdeliveryResolveFetchTaskInputrequired

FieldTypeRequiredDescription
taskIdstringrequired
noticeIdstringoptional

Responses

  • 200Successful invocationEdeliveryResolveFetchTaskOutput
    FieldTypeRequiredDescription
    taskIdstringrequired
    resolvedAtstringrequired
    noticeIdstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/edelivery.enrollViaKretoOpsKreto ops performs an agency-portal paperless enrollment ON THE CUSTOMER'S BEHALF under an explicit consent artifact + stored portal credentials. APPROVAL_REQUIRED, UI-only — excluded from MCP/CLI, and the handler REJECTS any non-human principal before any write. Records an IMMUTABLE per-enrollment consent (who consented, when, IP/UA, scope) and flips the checklist item to enrolled, attributed to ops. HONESTY: customer-facing copy stays 'the customer performs' until this flow is enabled + verified.

Kreto ops performs an agency-portal paperless enrollment ON THE CUSTOMER'S BEHALF under an explicit consent artifact + stored portal credentials. APPROVAL_REQUIRED, UI-only — excluded from MCP/CLI, and the handler REJECTS any non-human principal before any write. Records an IMMUTABLE per-enrollment consent (who consented, when, IP/UA, scope) and flips the checklist item to enrolled, attributed to ops. HONESTY: customer-facing copy stays 'the customer performs' until this flow is enabled + verified.

Cookie session or Bearer token

Request body EdeliveryEnrollViaKretoOpsInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
stateCodestringrequired
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required
consentedByUserIdstringrequired
consentIpstringoptional
consentUserAgentstringoptional

Responses

  • 200Successful invocationEdeliveryEnrollViaKretoOpsOutput
    FieldTypeRequiredDescription
    consentIdstringrequired
    itemIdstringrequired
    stateCodestringrequired
    requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required
    statusenum: "not_started" | "enrolled"required
    enrolledViaOpsbooleanrequired
    reusedExistingConsentbooleanrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:employee-roster6

POST/v1/employee-roster.getActiveRosterList employees on the active roster for the caller's tenant. Defaults to employment_status='active'; pass `statuses` to widen (e.g. ['active','terminated','leave'] for the I-9 list). Pass `entityIds` to narrow to a subset of entities the caller has access to. If `asOf` is supplied, joins payroll_pay_periods to detect employees who had a paycheck within 60 days of asOf and weren't terminated before it.

List employees on the active roster for the caller's tenant. Defaults to employment_status='active'; pass `statuses` to widen (e.g. ['active','terminated','leave'] for the I-9 list). Pass `entityIds` to narrow to a subset of entities the caller has access to. If `asOf` is supplied, joins payroll_pay_periods to detect employees who had a paycheck within 60 days of asOf and weren't terminated before it.

Cookie session or Bearer token

Request body EmployeeRosterGetActiveRosterInputrequired

FieldTypeRequiredDescription
asOfstring · date-timeoptional
entityIdsarray<string · uuid>optional
statusesarray<enum: "active" | "terminated" | "leave">optional

Responses

  • 200Successful invocationEmployeeRosterGetActiveRosterOutput
    FieldTypeRequiredDescription
    employeesarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/employee-roster.getEmployeeFetch a single employee by id, scoped to the caller's tenant. Returns null if no row matches. Per README §6 Q5, no asOf is supported on this method; per-employee historical context comes from payroll_pay_periods joins, not effective-dating columns.

Fetch a single employee by id, scoped to the caller's tenant. Returns null if no row matches. Per README §6 Q5, no asOf is supported on this method; per-employee historical context comes from payroll_pay_periods joins, not effective-dating columns.

Cookie session or Bearer token

Request body EmployeeRosterGetEmployeeInputrequired

FieldTypeRequiredDescription
employeeIdstring · uuidrequired

Responses

  • 200Successful invocationEmployeeRosterGetEmployeeOutput
    FieldTypeRequiredDescription
    idstring · uuidrequired
    entity_idstring · uuidrequired
    ssn_last4stringrequired
    full_namestringrequired
    emailstringrequired
    departmentstringrequired
    hire_datestringrequired
    termination_datestringrequired
    employment_statusenum: "active" | "terminated" | "leave"required
    work_statestringrequired
    home_statestringrequired
    salary_typeenum: "hourly" | "salary" | "unknown"required
    hourly_ratenumberrequired
    annual_salarynumberrequired
    i9_section1_completebooleanrequired
    i9_section2_completebooleanrequired
    i9_reverification_neededbooleanrequired
    work_auth_typestringrequired
    work_auth_expirystringrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/employee-roster.getEmployeesByStateList employees whose canonical work_state matches the supplied two-letter code (e.g. 'OH'). asOf is optional; without it, the active roster filtered by work_state is returned. With asOf, the asOf logic from getActiveRoster applies first, then the work_state filter narrows the result.

List employees whose canonical work_state matches the supplied two-letter code (e.g. 'OH'). asOf is optional; without it, the active roster filtered by work_state is returned. With asOf, the asOf logic from getActiveRoster applies first, then the work_state filter narrows the result.

Cookie session or Bearer token

Request body EmployeeRosterGetEmployeesByStateInputrequired

FieldTypeRequiredDescription
statestringrequired
asOfstring · date-timeoptional

Responses

  • 200Successful invocationEmployeeRosterGetEmployeesByStateOutput
    FieldTypeRequiredDescription
    employeesarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/employee-roster.countEmployeesCount active employees on the caller's tenant. Pass `entityId` to scope to a single employer (PEPM Source 3 pattern). Replaces the ad-hoc count query in src/lib/billing/pepm-quantity.ts — migrated in Part F (KRT-1159). asOf is supported via the same join-with-payroll_pay_periods logic getActiveRoster uses.

Count active employees on the caller's tenant. Pass `entityId` to scope to a single employer (PEPM Source 3 pattern). Replaces the ad-hoc count query in src/lib/billing/pepm-quantity.ts — migrated in Part F (KRT-1159). asOf is supported via the same join-with-payroll_pay_periods logic getActiveRoster uses.

Cookie session or Bearer token

Request body EmployeeRosterCountEmployeesInputrequired

FieldTypeRequiredDescription
asOfstring · date-timeoptional
entityIdstring · uuidoptional

Responses

  • 200Successful invocationEmployeeRosterCountEmployeesOutput
    FieldTypeRequiredDescription
    countintegerrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/employee-roster.getStateChangesDetect work_state transitions across employees by walking payroll_pay_periods paycheck history since the supplied date. Returns one StateChangeEvent per detected transition (e.g. an employee moving MA→KS mid-quarter). The trigger source for the Phase 1+ state-registration agent.

Detect work_state transitions across employees by walking payroll_pay_periods paycheck history since the supplied date. Returns one StateChangeEvent per detected transition (e.g. an employee moving MA→KS mid-quarter). The trigger source for the Phase 1+ state-registration agent.

Cookie session or Bearer token

Request body EmployeeRosterGetStateChangesInputrequired

FieldTypeRequiredDescription
sincestring · date-timerequired

Responses

  • 200Successful invocationEmployeeRosterGetStateChangesOutput
    FieldTypeRequiredDescription
    changesarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/employee-roster.getRosterWithSsnHashRoster rows for a single entity, with `ssn_hash` exposed in addition to the public EmployeeRosterRow fields. ELEVATED risk: ssn_hash is the cross-payroll-graph join key but is NOT part of the public PII contract. Use only from cross-reference / audit-defense consumers. Filters by employment_status='active' by default; with `asOf`, applies the same payroll_pay_periods liveness heuristic getActiveRoster uses. Excludes rows whose ssn_hash is NULL (those rows can't be joined against the payroll fact graph anyway).

Roster rows for a single entity, with `ssn_hash` exposed in addition to the public EmployeeRosterRow fields. ELEVATED risk: ssn_hash is the cross-payroll-graph join key but is NOT part of the public PII contract. Use only from cross-reference / audit-defense consumers. Filters by employment_status='active' by default; with `asOf`, applies the same payroll_pay_periods liveness heuristic getActiveRoster uses. Excludes rows whose ssn_hash is NULL (those rows can't be joined against the payroll fact graph anyway).

Cookie session or Bearer token

Request body EmployeeRosterGetRosterWithSsnHashInputrequired

FieldTypeRequiredDescription
entityIdstring · uuidrequired
asOfstring · date-timeoptional

Responses

  • 200Successful invocationEmployeeRosterGetRosterWithSsnHashOutput
    FieldTypeRequiredDescription
    employeesarray<object>required
  • 400Validation error (input schema rejected). risk_level=elevated.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:foreign-qualification13

POST/v1/foreign-qualification.listForeignQualRulesList the state foreign-qualification catalog (global config): per-(state, entity_kind) SOS certificate-of-authority rules — agency, form, state filing fee, good-standing prerequisite and doing-business notes — with the verification ladder status of every cell and honest per-status counts. Cells below the display gate (human_reviewed) must never be rendered as authoritative to customers.

List the state foreign-qualification catalog (global config): per-(state, entity_kind) SOS certificate-of-authority rules — agency, form, state filing fee, good-standing prerequisite and doing-business notes — with the verification ladder status of every cell and honest per-status counts. Cells below the display gate (human_reviewed) must never be rendered as authoritative to customers.

Cookie session or Bearer token

Request body ForeignQualificationListForeignQualRulesInputrequired

FieldTypeRequiredDescription
stateCodestringoptional
entityKindenum: "corporation" | "llc" | "nonprofit" | "lp" | …optional
verificationStatusenum: "unverified" | "human_reviewed" | "verified"optional

Responses

  • 200Successful invocationForeignQualificationListForeignQualRulesOutput
    FieldTypeRequiredDescription
    rulesarray<object>required
    countsobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.getForeignQualRuleFetch one foreign-qualification catalog cell with the (state, entity_kind) → (state, 'default') fallback. Null rule = no catalog coverage yet. Advisory context only — doing_business_notes never assert an obligation.

Fetch one foreign-qualification catalog cell with the (state, entity_kind) → (state, 'default') fallback. Null rule = no catalog coverage yet. Advisory context only — doing_business_notes never assert an obligation.

Cookie session or Bearer token

Request body ForeignQualificationGetForeignQualRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
entityKindenum: "corporation" | "llc" | "nonprofit" | "lp" | …optional

Responses

  • 200Successful invocationForeignQualificationGetForeignQualRuleOutput
    FieldTypeRequiredDescription
    ruleobjectrequired
    usedDefaultFallbackbooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.proposeForeignQualRuleResearch-agent write path for the foreign-qualification catalog. Upserts one (state, entity_kind) cell as verification_status='unverified' with mandatory provenance (source_url + retrieved_at). REFUSES to touch a cell already at human_reviewed/verified — verified cells are never downgraded (AC-22 clone); corrections go through the review queue.

Research-agent write path for the foreign-qualification catalog. Upserts one (state, entity_kind) cell as verification_status='unverified' with mandatory provenance (source_url + retrieved_at). REFUSES to touch a cell already at human_reviewed/verified — verified cells are never downgraded (AC-22 clone); corrections go through the review queue.

Cookie session or Bearer token

Request body ForeignQualificationProposeForeignQualRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
entityKindenum: "corporation" | "llc" | "nonprofit" | "lp" | …optional
agencyCodestringrequired
agencyNamestringrequired
portalUrlstring · urioptional
formNamestringoptional
filingFeeUsdnumberoptional
expediteFeeNotesstringoptional
goodStandingRequiredbooleanoptional
goodStandingMaxAgeDaysintegeroptional
registeredAgentRequiredbooleanoptional
nameCheckNotesstringoptional
doingBusinessNotesstringoptional
penaltyNotesstringoptional
processingTimeNotesstringoptional
sourceUrlstring · urirequired
retrievedAtstring · date-timerequired
notesstringoptional

Responses

  • 200Successful invocationForeignQualificationProposeForeignQualRuleOutput
    FieldTypeRequiredDescription
    ruleobjectrequired
    createdbooleanrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.promoteForeignQualRulePromote a foreign-qualification catalog cell along the verification ladder (unverified → human_reviewed → verified). APPROVAL_REQUIRED and UI-only: the handler rejects any non-human principal (AC-20 clone) and refuses cells with no source_url provenance (CWE-345).

Promote a foreign-qualification catalog cell along the verification ladder (unverified → human_reviewed → verified). APPROVAL_REQUIRED and UI-only: the handler rejects any non-human principal (AC-20 clone) and refuses cells with no source_url provenance (CWE-345).

Cookie session or Bearer token

Request body ForeignQualificationPromoteForeignQualRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
entityKindenum: "corporation" | "llc" | "nonprofit" | "lp" | …optional
targetStatusenum: "human_reviewed" | "verified"required
reviewerEmailstring · emailrequired
reasonstringrequired

Responses

  • 200Successful invocationForeignQualificationPromoteForeignQualRuleOutput
    FieldTypeRequiredDescription
    ruleobjectrequired
    fromStatusenum: "unverified" | "human_reviewed" | "verified"required
    toStatusenum: "unverified" | "human_reviewed" | "verified"required
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.listForeignQualificationsList the tenant's foreign-qualification tracker rows (once per entity × state), filterable by entity, state, status and obligation assessment. Advisory rows are unconfirmed legal judgments — callers must exclude them from compliance/on-track counts (design D5/D6). Paginated (default 25). Tenant-scoped via the invocation context.

List the tenant's foreign-qualification tracker rows (once per entity × state), filterable by entity, state, status and obligation assessment. Advisory rows are unconfirmed legal judgments — callers must exclude them from compliance/on-track counts (design D5/D6). Paginated (default 25). Tenant-scoped via the invocation context.

Cookie session or Bearer token

Request body ForeignQualificationListForeignQualificationsInputrequired

FieldTypeRequiredDescription
entityIdstringoptional
stateCodestringoptional
statusenum: "pending" | "prepared" | "submitted" | "approved" | …optional
obligationAssessmentenum: "advisory" | "confirmed" | "not_required"optional
excludeAdvisorybooleanoptional
limitintegeroptional
offsetintegeroptional

Responses

  • 200Successful invocationForeignQualificationListForeignQualificationsOutput
    FieldTypeRequiredDescription
    qualificationsarray<object>required
    totalnumberrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.getForeignQualificationsByEntityFetch every foreign-qualification tracker row for one entity (optionally one state) — advisory, confirmed, dismissed and recorded qualifications. Tenant-scoped.

Fetch every foreign-qualification tracker row for one entity (optionally one state) — advisory, confirmed, dismissed and recorded qualifications. Tenant-scoped.

Cookie session or Bearer token

Request body ForeignQualificationGetForeignQualificationsByEntityInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
stateCodestringoptional

Responses

  • 200Successful invocationForeignQualificationGetForeignQualificationsByEntityOutput
    FieldTypeRequiredDescription
    qualificationsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.detectForeignQualNeedsDry-run compute of an entity's foreign-qualification detection signal (design §4): per candidate state, whether the advisory signal fires (operating evidence outside the formation state with no qualification on record) or an explicit disposition (already_tracked / not_foreign / no_signal / needs_input when the formation state is unknown). Writes NOTHING — the sweep's detection roll persists advisory rows; this method answers 'what would be flagged?'. ADVISORY POSTURE: a firing signal is never an obligation assertion — a human CPA confirms.

Dry-run compute of an entity's foreign-qualification detection signal (design §4): per candidate state, whether the advisory signal fires (operating evidence outside the formation state with no qualification on record) or an explicit disposition (already_tracked / not_foreign / no_signal / needs_input when the formation state is unknown). Writes NOTHING — the sweep's detection roll persists advisory rows; this method answers 'what would be flagged?'. ADVISORY POSTURE: a firing signal is never an obligation assertion — a human CPA confirms.

Cookie session or Bearer token

Request body ForeignQualificationDetectForeignQualNeedsInputrequired

FieldTypeRequiredDescription
entityIdstringrequired

Responses

  • 200Successful invocationForeignQualificationDetectForeignQualNeedsOutput
    FieldTypeRequiredDescription
    resultobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.createForeignQualificationCreate one manual foreign-qualification tracker row (source='manual') for an entity × state. Defaults to obligation_assessment='advisory'; creating a CONFIRMED row is a human CPA judgment and rejects agent principals (design D5). Duplicate states are rejected by the once-per-state UNIQUE.

Create one manual foreign-qualification tracker row (source='manual') for an entity × state. Defaults to obligation_assessment='advisory'; creating a CONFIRMED row is a human CPA judgment and rejects agent principals (design D5). Duplicate states are rejected by the once-per-state UNIQUE.

Cookie session or Bearer token

Request body ForeignQualificationCreateForeignQualificationInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
stateCodestringrequired
obligationAssessmentenum: "advisory" | "confirmed"optional
assessmentNotestringoptional
notesstringoptional

Responses

  • 200Successful invocationForeignQualificationCreateForeignQualificationOutput
    FieldTypeRequiredDescription
    qualificationobjectrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.recordExistingQualificationRecord an ALREADY-HELD foreign qualification (design D12 backfill): the row lands status='approved', obligation_assessment='confirmed', source='manual' with the state-issued qualification_date + sos_file_number. This is the authoritative annual-reports foreign anchor (design D9) and permanently suppresses detection advisories for the state (once-per-state UNIQUE).

Record an ALREADY-HELD foreign qualification (design D12 backfill): the row lands status='approved', obligation_assessment='confirmed', source='manual' with the state-issued qualification_date + sos_file_number. This is the authoritative annual-reports foreign anchor (design D9) and permanently suppresses detection advisories for the state (once-per-state UNIQUE).

Cookie session or Bearer token

Request body ForeignQualificationRecordExistingQualificationInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
stateCodestringrequired
qualificationDatestringrequired
sosFileNumberstringoptional
notesstringoptional

Responses

  • 200Successful invocationForeignQualificationRecordExistingQualificationOutput
    FieldTypeRequiredDescription
    qualificationobjectrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.updateForeignQualificationMetadataEdit tracker metadata on one foreign-qualification row: the obligation assessment (confirm the obligation — unlocks prepare — or dismiss as not_required with a REQUIRED assessment note; both are human-only CPA judgments that reject agent principals, design D5), assignee and notes. Writes a structured audit event capturing before/after.

Edit tracker metadata on one foreign-qualification row: the obligation assessment (confirm the obligation — unlocks prepare — or dismiss as not_required with a REQUIRED assessment note; both are human-only CPA judgments that reject agent principals, design D5), assignee and notes. Writes a structured audit event capturing before/after.

Cookie session or Bearer token

Request body ForeignQualificationUpdateForeignQualificationMetadataInputrequired

FieldTypeRequiredDescription
foreignQualificationIdstringrequired
obligationAssessmentenum: "confirmed" | "not_required"optional
assessmentNotestringoptional
assigneestringoptional
notesstringoptional
reasonstringrequired

Responses

  • 200Successful invocationForeignQualificationUpdateForeignQualificationMetadataOutput
    FieldTypeRequiredDescription
    qualificationobjectrequired
    changedFieldsarray<string>required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.prepareForeignQualificationPopulate a foreign qualification's prepared form payload (officers, principal address, home-state formation details, the customer's OWN foreign-state registered agent — Kreto is not the RA — and the good-standing checklist) and transition pending/manual_required → prepared. APPROVAL_REQUIRED and UI-only. HARD GUARDS (design D5/D7): refused unless obligation_assessment='confirmed' (a human CPA judgment) and the catalog cell is at/above the display gate; a required good-standing certificate must be recorded as obtained. PII in form_payload is scrubbed from audit rows.

Populate a foreign qualification's prepared form payload (officers, principal address, home-state formation details, the customer's OWN foreign-state registered agent — Kreto is not the RA — and the good-standing checklist) and transition pending/manual_required → prepared. APPROVAL_REQUIRED and UI-only. HARD GUARDS (design D5/D7): refused unless obligation_assessment='confirmed' (a human CPA judgment) and the catalog cell is at/above the display gate; a required good-standing certificate must be recorded as obtained. PII in form_payload is scrubbed from audit rows.

Cookie session or Bearer token

Request body ForeignQualificationPrepareForeignQualificationInputrequired

FieldTypeRequiredDescription
foreignQualificationIdstringrequired
formPayloadobjectrequired

Responses

  • 200Successful invocationForeignQualificationPrepareForeignQualificationOutput
    FieldTypeRequiredDescription
    qualificationobjectrequired
    fromStatusenum: "pending" | "prepared" | "submitted" | "approved" | …required
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.requestForeignQualConciergeFilingRecord the '$149 File it for me' concierge request on a prepared foreign qualification: stamps filing_requested_at/by (design D3 — an annotation on 'prepared', not a status) and charges the $149 as a standalone Stripe invoice (created + finalized, so it bills every customer; owner 2026-07-10; fail-closed when STRIPE_SECRET_KEY is unset; double-bill safe). APPROVAL_REQUIRED: this moves money, so the v1 dispatcher blocks non-interactive API-key / MCP callers (KRT-1657) — it requires an interactive human session. Concierge gate (design D7): the catalog cell must be 'verified'. The click by an authenticated CPA/owner IS the recorded filing authorization. The state's own filing fee is separate and paid to the state.

Record the '$149 File it for me' concierge request on a prepared foreign qualification: stamps filing_requested_at/by (design D3 — an annotation on 'prepared', not a status) and charges the $149 as a standalone Stripe invoice (created + finalized, so it bills every customer; owner 2026-07-10; fail-closed when STRIPE_SECRET_KEY is unset; double-bill safe). APPROVAL_REQUIRED: this moves money, so the v1 dispatcher blocks non-interactive API-key / MCP callers (KRT-1657) — it requires an interactive human session. Concierge gate (design D7): the catalog cell must be 'verified'. The click by an authenticated CPA/owner IS the recorded filing authorization. The state's own filing fee is separate and paid to the state.

Cookie session or Bearer token

Request body ForeignQualificationRequestForeignQualConciergeFilingInputrequired

FieldTypeRequiredDescription
foreignQualificationIdstringrequired

Responses

  • 200Successful invocationForeignQualificationRequestForeignQualConciergeFilingOutput
    FieldTypeRequiredDescription
    qualificationobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/foreign-qualification.transitionForeignQualificationStatusApply a matrix-gated status transition to a foreign-qualification tracker row (exact ear/esr 7-status machine). Supports the mark-filed extras (confirmationNumber + filedAt on → submitted), the approval record (qualificationDate + sosFileNumber on → approved — this becomes the authoritative annual-reports foreign anchor, design D9), the confirmedImmediately chain, and the manual withdrawal record (withdrawnAt on → expired; the sweep never writes expired). Every hop writes a hash-chained audit_events row.

Apply a matrix-gated status transition to a foreign-qualification tracker row (exact ear/esr 7-status machine). Supports the mark-filed extras (confirmationNumber + filedAt on → submitted), the approval record (qualificationDate + sosFileNumber on → approved — this becomes the authoritative annual-reports foreign anchor, design D9), the confirmedImmediately chain, and the manual withdrawal record (withdrawnAt on → expired; the sweep never writes expired). Every hop writes a hash-chained audit_events row.

Cookie session or Bearer token

Request body ForeignQualificationTransitionForeignQualificationStatusInputrequired

FieldTypeRequiredDescription
foreignQualificationIdstringrequired
newStatusenum: "pending" | "prepared" | "submitted" | "approved" | …required
reasonstringrequired
confirmationNumberstringoptional
filedAtstring · date-timeoptional
qualificationDatestringoptional
sosFileNumberstringoptional
confirmedImmediatelybooleanoptional
withdrawnAtstringoptional
lastErrorstringoptional

Responses

  • 200Successful invocationForeignQualificationTransitionForeignQualificationStatusOutput
    FieldTypeRequiredDescription
    qualificationobjectrequired
    fromStatusenum: "pending" | "prepared" | "submitted" | "approved" | …required
    toStatusenum: "pending" | "prepared" | "submitted" | "approved" | …required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:handbooks13

POST/v1/handbooks.listHandbookModulesList the handbook policy-module catalog (global config): per (jurisdiction × topic) modules with each module's CURRENT version and its per-version verification-ladder status, plus honest per-status counts. Assembly gate is verified-only (§0-1b): anything below 'verified' must never be rendered on a tenant surface as usable text.

List the handbook policy-module catalog (global config): per (jurisdiction × topic) modules with each module's CURRENT version and its per-version verification-ladder status, plus honest per-status counts. Assembly gate is verified-only (§0-1b): anything below 'verified' must never be rendered on a tenant surface as usable text.

Cookie session or Bearer token

Request body HandbooksListHandbookModulesInputrequired

FieldTypeRequiredDescription
jurisdictionstringoptional
categoryenum: "federal_core" | "state_required" | "state_recommended"optional
verificationStatusenum: "unverified" | "human_reviewed" | "verified"optional

Responses

  • 200Successful invocationHandbooksListHandbookModulesOutput
    FieldTypeRequiredDescription
    modulesarray<object>required
    countsobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.getHandbookModuleFetch one handbook policy module by (jurisdiction, topic) with its FULL version history (each version carries its own ladder status — verifying v3 says nothing about v4). Null module = no catalog coverage; the caller renders a coverage gap, never a blank.

Fetch one handbook policy module by (jurisdiction, topic) with its FULL version history (each version carries its own ladder status — verifying v3 says nothing about v4). Null module = no catalog coverage; the caller renders a coverage gap, never a blank.

Cookie session or Bearer token

Request body HandbooksGetHandbookModuleInputrequired

FieldTypeRequiredDescription
jurisdictionstringrequired
topicstringrequired

Responses

  • 200Successful invocationHandbooksGetHandbookModuleOutput
    FieldTypeRequiredDescription
    moduleobjectrequired
    versionsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.proposeHandbookModuleResearch-agent write path for the policy-module catalog. Creates the (jurisdiction, topic) module identity if missing and appends a NEW version row at verification_status='unverified' with mandatory provenance. NEVER touches an existing verified version (AC-22 clone) — a law change is a new version, promoted only by a human (AC-20 wall). Inputs are public (jurisdiction, topic) facts — PII-free by construction.

Research-agent write path for the policy-module catalog. Creates the (jurisdiction, topic) module identity if missing and appends a NEW version row at verification_status='unverified' with mandatory provenance. NEVER touches an existing verified version (AC-22 clone) — a law change is a new version, promoted only by a human (AC-20 wall). Inputs are public (jurisdiction, topic) facts — PII-free by construction.

Cookie session or Bearer token

Request body HandbooksProposeHandbookModuleInputrequired

FieldTypeRequiredDescription
jurisdictionstringrequired
topicstringrequired
titlestringrequired
categoryenum: "federal_core" | "state_required" | "state_recommended"required
minEmployeeCountintegeroptional
applicabilityobjectoptional
displayOrderintegeroptional
bodyMdstringrequired
changeSummarystringoptional
lawEffectiveDatestringoptional
statuteCitationsarray<object>required
draftedByenum: "research_agent" | "human"optional
draftProvenanceobjectoptional
sourceUrlstring · urirequired
retrievedAtstring · date-timerequired
notesstringoptional

Responses

  • 200Successful invocationHandbooksProposeHandbookModuleOutput
    FieldTypeRequiredDescription
    moduleobjectrequired
    versionobjectrequired
    moduleCreatedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.proposeStateRequiredTopicResearch-agent write path for the §3A2 completeness registry — which topics a state REQUIRES at what headcount (a fee-catalog-class checkable fact). Upserts one (jurisdiction, topic) row as 'unverified' with mandatory provenance. REFUSES to touch a row already at human_reviewed/verified (no-downgrade AC-22 clone). The §4 gap computation only trusts VERIFIED registry rows.

Research-agent write path for the §3A2 completeness registry — which topics a state REQUIRES at what headcount (a fee-catalog-class checkable fact). Upserts one (jurisdiction, topic) row as 'unverified' with mandatory provenance. REFUSES to touch a row already at human_reviewed/verified (no-downgrade AC-22 clone). The §4 gap computation only trusts VERIFIED registry rows.

Cookie session or Bearer token

Request body HandbooksProposeStateRequiredTopicInputrequired

FieldTypeRequiredDescription
jurisdictionstringrequired
topicstringrequired
requirementKindenum: "required" | "recommended"required
minEmployeeCountintegeroptional
applicabilityobjectoptional
statuteCitationsarray<object>required
sourceUrlstring · urirequired
retrievedAtstring · date-timerequired
notesstringoptional

Responses

  • 200Successful invocationHandbooksProposeStateRequiredTopicOutput
    FieldTypeRequiredDescription
    topicRowobjectrequired
    createdbooleanrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.promoteHandbookModuleVersionPromote one policy-module VERSION along the verification ladder (unverified → human_reviewed → verified). APPROVAL_REQUIRED and UI-only: rejects any non-human principal (AC-20 wall), refuses missing source_url provenance. The promotion UI shows the §0-1(b) honest definition of what the click asserts. On 'verified': the prior verified version gets superseded_at and current_version_id advances (§7 step 3). 'human_reviewed' remains admin-queue-only — it renders on NO tenant surface (§0-1b).

Promote one policy-module VERSION along the verification ladder (unverified → human_reviewed → verified). APPROVAL_REQUIRED and UI-only: rejects any non-human principal (AC-20 wall), refuses missing source_url provenance. The promotion UI shows the §0-1(b) honest definition of what the click asserts. On 'verified': the prior verified version gets superseded_at and current_version_id advances (§7 step 3). 'human_reviewed' remains admin-queue-only — it renders on NO tenant surface (§0-1b).

Cookie session or Bearer token

Request body HandbooksPromoteHandbookModuleVersionInputrequired

FieldTypeRequiredDescription
moduleVersionIdstringrequired
targetStatusenum: "human_reviewed" | "verified"required
reviewerEmailstring · emailrequired
reasonstringrequired

Responses

  • 200Successful invocationHandbooksPromoteHandbookModuleVersionOutput
    FieldTypeRequiredDescription
    versionobjectrequired
    fromStatusenum: "unverified" | "human_reviewed" | "verified"required
    toStatusenum: "unverified" | "human_reviewed" | "verified"required
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.promoteStateRequiredTopicPromote a §3A2 completeness-registry row along the verification ladder. APPROVAL_REQUIRED and UI-only (AC-20 wall — rejects non-human principals; refuses missing source_url). Only VERIFIED registry rows feed the honest-gaps computation.

Promote a §3A2 completeness-registry row along the verification ladder. APPROVAL_REQUIRED and UI-only (AC-20 wall — rejects non-human principals; refuses missing source_url). Only VERIFIED registry rows feed the honest-gaps computation.

Cookie session or Bearer token

Request body HandbooksPromoteStateRequiredTopicInputrequired

FieldTypeRequiredDescription
jurisdictionstringrequired
topicstringrequired
targetStatusenum: "human_reviewed" | "verified"required
reviewerEmailstring · emailrequired
reasonstringrequired

Responses

  • 200Successful invocationHandbooksPromoteStateRequiredTopicOutput
    FieldTypeRequiredDescription
    topicRowobjectrequired
    fromStatusenum: "unverified" | "human_reviewed" | "verified"required
    toStatusenum: "unverified" | "human_reviewed" | "verified"required
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.retireHandbookModuleVersionEMERGENCY version-level retire (§0-5d): a repealed/amended/enjoined statute pulls a verified version from assembly IMMEDIATELY, without waiting for a replacement to clear review — the ONE sanctioned exemption from no-downgrade. APPROVAL_REQUIRED, human-only, reason mandatory. Existing pins are unaffected (reconstructability holds) but published handbooks pinning this version get flagged by checkHandbookDrift.

EMERGENCY version-level retire (§0-5d): a repealed/amended/enjoined statute pulls a verified version from assembly IMMEDIATELY, without waiting for a replacement to clear review — the ONE sanctioned exemption from no-downgrade. APPROVAL_REQUIRED, human-only, reason mandatory. Existing pins are unaffected (reconstructability holds) but published handbooks pinning this version get flagged by checkHandbookDrift.

Cookie session or Bearer token

Request body HandbooksRetireHandbookModuleVersionInputrequired

FieldTypeRequiredDescription
moduleVersionIdstringrequired
reasonstringrequired

Responses

  • 200Successful invocationHandbooksRetireHandbookModuleVersionOutput
    FieldTypeRequiredDescription
    versionobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.listHandbooksList the tenant's handbook instances (per entity, versioned), filterable by entity and status. Paginated (default 25). Tenant-scoped via the invocation context.

List the tenant's handbook instances (per entity, versioned), filterable by entity and status. Paginated (default 25). Tenant-scoped via the invocation context.

Cookie session or Bearer token

Request body HandbooksListHandbooksInputrequired

FieldTypeRequiredDescription
entityIdstringoptional
statusenum: "draft" | "published" | "superseded" | "archived"optional
limitintegeroptional
offsetintegeroptional

Responses

  • 200Successful invocationHandbooksListHandbooksOutput
    FieldTypeRequiredDescription
    handbooksarray<object>required
    totalnumberrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.generateHandbookDraftGenerate a handbook DRAFT for an entity: deterministic module selection (selectHandbookModules) from live operating states + per-state headcount, assembly gate = verified-only, honest coverage gaps computed against the §3A2 registry (uncovered states gap UNCONDITIONALLY), generation-time staleness warnings (§0-5c). Pins exact module-version ids. Publishing is a separate APPROVAL_REQUIRED step with the blocking disclaimer checkbox.

Generate a handbook DRAFT for an entity: deterministic module selection (selectHandbookModules) from live operating states + per-state headcount, assembly gate = verified-only, honest coverage gaps computed against the §3A2 registry (uncovered states gap UNCONDITIONALLY), generation-time staleness warnings (§0-5c). Pins exact module-version ids. Publishing is a separate APPROVAL_REQUIRED step with the blocking disclaimer checkbox.

Cookie session or Bearer token

Request body HandbooksGenerateHandbookDraftInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
titlestringoptional
companyInputsobjectoptional

Responses

  • 200Successful invocationHandbooksGenerateHandbookDraftOutput
    FieldTypeRequiredDescription
    handbookobjectrequired
    selectionobjectrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.publishHandbookPublish a draft handbook. APPROVAL_REQUIRED and UI-only: the §0-2(b) blocking disclaimer checkbox is part of the contract — refuses disclaimerAccepted !== true, stamps disclaimer_ack_at/by, records the exact checkbox copy in the hash-chained audit trail, freezes the pins + states_snapshot, supersedes the prior published version, and queues the PDF render (onboarding-docs queue posture — never a half-written published row).

Publish a draft handbook. APPROVAL_REQUIRED and UI-only: the §0-2(b) blocking disclaimer checkbox is part of the contract — refuses disclaimerAccepted !== true, stamps disclaimer_ack_at/by, records the exact checkbox copy in the hash-chained audit trail, freezes the pins + states_snapshot, supersedes the prior published version, and queues the PDF render (onboarding-docs queue posture — never a half-written published row).

Cookie session or Bearer token

Request body HandbooksPublishHandbookInputrequired

FieldTypeRequiredDescription
handbookIdstringrequired
disclaimerAcceptedbooleanrequired

Responses

  • 200Successful invocationHandbooksPublishHandbookOutput
    FieldTypeRequiredDescription
    handbookobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.sendHandbookAcknowledgmentsCreate one acknowledgment EVIDENCE row per active roster employee of the published handbook's entity — snapshotting name/email/work_state at send (§3E) — and email each a tokenized link (signature_requests clone). Employees without email land in an honest 'cannot reach' list. Idempotent: existing (handbook, employee) rows are skipped.

Create one acknowledgment EVIDENCE row per active roster employee of the published handbook's entity — snapshotting name/email/work_state at send (§3E) — and email each a tokenized link (signature_requests clone). Employees without email land in an honest 'cannot reach' list. Idempotent: existing (handbook, employee) rows are skipped.

Cookie session or Bearer token

Request body HandbooksSendHandbookAcknowledgmentsInputrequired

FieldTypeRequiredDescription
handbookIdstringrequired

Responses

  • 200Successful invocationHandbooksSendHandbookAcknowledgmentsOutput
    FieldTypeRequiredDescription
    creatednumberrequired
    skippedExistingnumberrequired
    cannotReacharray<object>required
    emailFailuresnumberrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.getHandbookAckStatusThe acknowledgment tracking matrix for one handbook: per-employee sent/viewed/acknowledged status with honest counts. secure_token is never returned. Tenant-scoped.

The acknowledgment tracking matrix for one handbook: per-employee sent/viewed/acknowledged status with honest counts. secure_token is never returned. Tenant-scoped.

Cookie session or Bearer token

Request body HandbooksGetHandbookAckStatusInputrequired

FieldTypeRequiredDescription
handbookIdstringrequired

Responses

  • 200Successful invocationHandbooksGetHandbookAckStatusOutput
    FieldTypeRequiredDescription
    acksarray<object>required
    countsobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/handbooks.checkHandbookDriftFlag every published handbook of an entity that is stale on either axis (§7 step 4): pinned-module drift (pins a superseded or emergency-retired version) or selection-input drift (a deterministic re-run of selectHandbookModules against LIVE operating states + headcount diverges from states_snapshot — new state registered, threshold crossed). Read-only; never auto-republishes (§0-5e).

Flag every published handbook of an entity that is stale on either axis (§7 step 4): pinned-module drift (pins a superseded or emergency-retired version) or selection-input drift (a deterministic re-run of selectHandbookModules against LIVE operating states + headcount diverges from states_snapshot — new state registered, threshold crossed). Read-only; never auto-republishes (§0-5e).

Cookie session or Bearer token

Request body HandbooksCheckHandbookDriftInputrequired

FieldTypeRequiredDescription
entityIdstringrequired

Responses

  • 200Successful invocationHandbooksCheckHandbookDriftOutput
    FieldTypeRequiredDescription
    entityIdstringrequired
    flagsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:i9-records6

POST/v1/i9-records.createI9RecordCreate an I-9 record from Section 1 form data. SSN plaintext is encrypted via the public.app_create_secret vault wrapper; only the returned secret UUID is stored on the row. Dual-writes employees.i9_section1_complete = true. APPROVAL_REQUIRED.

Create an I-9 record from Section 1 form data. SSN plaintext is encrypted via the public.app_create_secret vault wrapper; only the returned secret UUID is stored on the row. Dual-writes employees.i9_section1_complete = true. APPROVAL_REQUIRED.

Cookie session or Bearer token

Request body I9RecordsCreateI9RecordInputrequired

FieldTypeRequiredDescription
employeeIdstring · uuidrequired
citizenshipStatusenum: "us_citizen" | "noncitizen_national" | "lpr" | "authorized_alien"required
section1Dataobjectrequired
ssnstringoptional

Responses

  • 200Successful invocationI9RecordsCreateI9RecordOutput
    FieldTypeRequiredDescription
    idstring · uuidrequired
    tenant_idstring · uuidrequired
    employee_idstring · uuidrequired
    citizenship_statusenum: "us_citizen" | "noncitizen_national" | "lpr" | "authorized_alien" | …required
    section1_completed_atstringrequired
    section2_completed_atstringrequired
    has_ssnbooleanrequired
    ssn_last_4stringrequired
    retention_untilstringrequired
    is_archivedbooleanrequired
    pdf_pathstringrequired
    supporting_docs_pathsarray<string>required
    created_atstringrequired
    updated_atstringrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/i9-records.getI9RecordFetch a single I-9 record by id, including decrypted SSN plaintext for the CPA detail view. APPROVAL_REQUIRED. The `ssn` field is redacted from audit outputs while the live caller receives the actual value (R13 mitigation, mirrors credential-vault.getCredential).

Fetch a single I-9 record by id, including decrypted SSN plaintext for the CPA detail view. APPROVAL_REQUIRED. The `ssn` field is redacted from audit outputs while the live caller receives the actual value (R13 mitigation, mirrors credential-vault.getCredential).

Cookie session or Bearer token

Request body I9RecordsGetI9RecordInputrequired

FieldTypeRequiredDescription
i9RecordIdstring · uuidrequired

Responses

  • 200Successful invocationI9RecordsGetI9RecordOutput
    FieldTypeRequiredDescription
    idstring · uuidrequired
    tenant_idstring · uuidrequired
    employee_idstring · uuidrequired
    citizenship_statusenum: "us_citizen" | "noncitizen_national" | "lpr" | "authorized_alien" | …required
    section1_completed_atstringrequired
    section2_completed_atstringrequired
    has_ssnbooleanrequired
    ssn_last_4stringrequired
    retention_untilstringrequired
    is_archivedbooleanrequired
    pdf_pathstringrequired
    supporting_docs_pathsarray<string>required
    created_atstringrequired
    updated_atstringrequired
    ssnstringrequired
    section1_dataobjectrequired
    section2_dataobjectrequired
    list_a_docsarray<object>required
    list_b_docsarray<object>required
    list_c_docsarray<object>required
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/i9-records.updateI9RecordSection2Update an i9_record with Section 2 employer-review data. Validates Section 1 completion + USCIS document combination (List A XOR List B+C). Dual-writes employees.i9_section2_complete = true. APPROVAL_REQUIRED.

Update an i9_record with Section 2 employer-review data. Validates Section 1 completion + USCIS document combination (List A XOR List B+C). Dual-writes employees.i9_section2_complete = true. APPROVAL_REQUIRED.

Cookie session or Bearer token

Request body I9RecordsUpdateI9RecordSection2Inputrequired

FieldTypeRequiredDescription
i9RecordIdstring · uuidrequired
section2Dataobjectrequired
reviewerUserIdstring · uuidoptional

Responses

  • 200Successful invocationI9RecordsUpdateI9RecordSection2Output
    FieldTypeRequiredDescription
    idstring · uuidrequired
    tenant_idstring · uuidrequired
    employee_idstring · uuidrequired
    citizenship_statusenum: "us_citizen" | "noncitizen_national" | "lpr" | "authorized_alien" | …required
    section1_completed_atstringrequired
    section2_completed_atstringrequired
    has_ssnbooleanrequired
    ssn_last_4stringrequired
    retention_untilstringrequired
    is_archivedbooleanrequired
    pdf_pathstringrequired
    supporting_docs_pathsarray<string>required
    created_atstringrequired
    updated_atstringrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/i9-records.listI9RecordsList I-9 records in the caller's tenant. Returns metadata only (no plaintext SSN, no full section data). The `ssn_last_4` field is left null on this path — fetch via getI9Record for last-4 display. AUTONOMOUS.

List I-9 records in the caller's tenant. Returns metadata only (no plaintext SSN, no full section data). The `ssn_last_4` field is left null on this path — fetch via getI9Record for last-4 display. AUTONOMOUS.

Cookie session or Bearer token

Request body I9RecordsListI9RecordsInputrequired

FieldTypeRequiredDescription
employeeIdstring · uuidoptional
includeArchivedbooleanoptional

Responses

  • 200Successful invocationI9RecordsListI9RecordsOutput
    FieldTypeRequiredDescription
    recordsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/i9-records.addI9SupportingDocumentUpload a supporting document (passport image, driver's license, SSN card, etc.) for an I-9 record. Stores bytes in Supabase Storage cct-docs bucket under i9/<record-id>/list_<a|b|c>_doc_<n>.<ext> and appends the path to i9_records.supporting_docs_paths. APPROVAL_REQUIRED.

Upload a supporting document (passport image, driver's license, SSN card, etc.) for an I-9 record. Stores bytes in Supabase Storage cct-docs bucket under i9/<record-id>/list_<a|b|c>_doc_<n>.<ext> and appends the path to i9_records.supporting_docs_paths. APPROVAL_REQUIRED.

Cookie session or Bearer token

Request body I9RecordsAddI9SupportingDocumentInputrequired

FieldTypeRequiredDescription
i9RecordIdstring · uuidrequired
listenum: "a" | "b" | "c"required
indexintegerrequired
filenamestringrequired
mimeTypestringrequired
fileBytesstring · binaryrequired

Responses

  • 200Successful invocationI9RecordsAddI9SupportingDocumentOutput
    FieldTypeRequiredDescription
    idstring · uuidrequired
    tenant_idstring · uuidrequired
    employee_idstring · uuidrequired
    citizenship_statusenum: "us_citizen" | "noncitizen_national" | "lpr" | "authorized_alien" | …required
    section1_completed_atstringrequired
    section2_completed_atstringrequired
    has_ssnbooleanrequired
    ssn_last_4stringrequired
    retention_untilstringrequired
    is_archivedbooleanrequired
    pdf_pathstringrequired
    supporting_docs_pathsarray<string>required
    created_atstringrequired
    updated_atstringrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/i9-records.generateI9PdfRender a USCIS Form I-9 PDF from i9_records data, store at cct-docs/i9/<id>/form.pdf, and update i9_records.pdf_path. Idempotent: subsequent calls overwrite the same path. SSN is decrypted internally and rendered into the PDF; never returned to the caller. APPROVAL_REQUIRED.

Render a USCIS Form I-9 PDF from i9_records data, store at cct-docs/i9/<id>/form.pdf, and update i9_records.pdf_path. Idempotent: subsequent calls overwrite the same path. SSN is decrypted internally and rendered into the PDF; never returned to the caller. APPROVAL_REQUIRED.

Cookie session or Bearer token

Request body I9RecordsGenerateI9PdfInputrequired

FieldTypeRequiredDescription
i9RecordIdstring · uuidrequired

Responses

  • 200Successful invocationI9RecordsGenerateI9PdfOutput
    FieldTypeRequiredDescription
    i9RecordIdstring · uuidrequired
    pdf_pathstringrequired
    byte_sizeintegerrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:location-detection4

POST/v1/location-detection.recordLocationChangeRecord a detected or operator-entered work-state transition for an employee. Idempotent on (employee_id, effective_date) — re-recording the same date returns the existing row's id with isDuplicate=true. NOTIFY — operator decision OR payroll-detection adapter call; the follow-up confirmLocationChange gates SUI/PFL jurisdiction routing.

Record a detected or operator-entered work-state transition for an employee. Idempotent on (employee_id, effective_date) — re-recording the same date returns the existing row's id with isDuplicate=true. NOTIFY — operator decision OR payroll-detection adapter call; the follow-up confirmLocationChange gates SUI/PFL jurisdiction routing.

Cookie session or Bearer token

Request body LocationDetectionRecordLocationChangeInputrequired

FieldTypeRequiredDescription
employeeIdstring · uuidrequired
toStatestringrequired
fromStatestringoptional
effectiveDatestringrequired
sourceenum: "payroll_detection" | "operator_manual" | "finch_sync" | "gusto_sync" | …required
metadataobjectoptional

Responses

  • 200Successful invocationLocationDetectionRecordLocationChangeOutput
    FieldTypeRequiredDescription
    idstring · uuidrequired
    employeeIdstring · uuidrequired
    toStatestringrequired
    effectiveDatestringrequired
    isDuplicatebooleanrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/location-detection.listLocationChangesReturn tenant-scoped work-state transition history. Optional `entityId` / `employeeId` filters narrow the result; `onlyConfirmed` filters to operator-confirmed rows. Ordered most-recent effective_date first. AUTONOMOUS — read-only.

Return tenant-scoped work-state transition history. Optional `entityId` / `employeeId` filters narrow the result; `onlyConfirmed` filters to operator-confirmed rows. Ordered most-recent effective_date first. AUTONOMOUS — read-only.

Cookie session or Bearer token

Request body LocationDetectionListLocationChangesInputrequired

FieldTypeRequiredDescription
entityIdstring · uuidoptional
employeeIdstring · uuidoptional
onlyConfirmedbooleanoptional
limitintegeroptional

Responses

  • 200Successful invocationLocationDetectionListLocationChangesOutput
    FieldTypeRequiredDescription
    changesarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/location-detection.confirmLocationChangeOperator confirms a detected work-state transition is real (not a payroll-data typo). Sets is_confirmed=true + confirmed_at + confirmed_by. Once confirmed, the locationDetection agent treats the row as the canonical state-of-record for the employee from effective_date forward. NOTIFY — operator override.

Operator confirms a detected work-state transition is real (not a payroll-data typo). Sets is_confirmed=true + confirmed_at + confirmed_by. Once confirmed, the locationDetection agent treats the row as the canonical state-of-record for the employee from effective_date forward. NOTIFY — operator override.

Cookie session or Bearer token

Request body LocationDetectionConfirmLocationChangeInputrequired

FieldTypeRequiredDescription
idstring · uuidrequired

Responses

  • 200Successful invocationLocationDetectionConfirmLocationChangeOutput
    FieldTypeRequiredDescription
    idstring · uuidrequired
    isConfirmedenum: truerequired
    confirmedAtstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/location-detection.getLatestLocationByEmployeeReturn the most recent confirmed work-state transition for an employee (as-of optional date; defaults to now). Returns {toState: null} when no confirmed rows exist. AUTONOMOUS — read-only.

Return the most recent confirmed work-state transition for an employee (as-of optional date; defaults to now). Returns {toState: null} when no confirmed rows exist. AUTONOMOUS — read-only.

Cookie session or Bearer token

Request body LocationDetectionGetLatestLocationByEmployeeInputrequired

FieldTypeRequiredDescription
employeeIdstring · uuidrequired
asOfstringoptional

Responses

  • 200Successful invocationLocationDetectionGetLatestLocationByEmployeeOutput
    FieldTypeRequiredDescription
    employeeIdstring · uuidrequired
    toStatestringrequired
    effectiveDatestringrequired
    isConfirmedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:mailbox1

POST/v1/mailbox.listInboundList inbound mail for an employer entity. Returns received mail rows (newest first) with sender info, status, OCR text, and notice linkage. Tenant-scoped; RLS enforced with a defense-in-depth cross-tenant assertion. AUTONOMOUS — read-only, recoverable, no agency impact.

List inbound mail for an employer entity. Returns received mail rows (newest first) with sender info, status, OCR text, and notice linkage. Tenant-scoped; RLS enforced with a defense-in-depth cross-tenant assertion. AUTONOMOUS — read-only, recoverable, no agency impact.

Cookie session or Bearer token

Request body MailboxListInboundInputrequired

FieldTypeRequiredDescription
entityIdstringrequired

Responses

  • 200Successful invocationMailboxListInboundOutput
    FieldTypeRequiredDescription
    itemsarray<object>required
    totalintegerrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:mfa7

POST/v1/mfa.getMatrixRead the Kreto-curated MFA capability row for a portal: supported second-factor methods, the preferred waterfall rung, whether the portal's identity layer blocks VoIP numbers, and the Google-Voice canary state. Use when enrolling a credential to pick the right MFA strategy for that portal.

Read the Kreto-curated MFA capability row for a portal: supported second-factor methods, the preferred waterfall rung, whether the portal's identity layer blocks VoIP numbers, and the Google-Voice canary state. Use when enrolling a credential to pick the right MFA strategy for that portal.

Cookie session or Bearer token

Request body MfaGetMatrixInputrequired

FieldTypeRequiredDescription
agencyIdstringrequired

Responses

  • 200Successful invocationMfaGetMatrixOutput
    FieldTypeRequiredDescription
    entryobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/mfa.resolveStrategyResolve which MFA rung the portal worker will drive for this account + portal: the account's per-portal override wins, else the curated matrix, else freeze_required (an unknown MFA method freezes the credential and requires a human — AC-13). A resolved 'sms' rung degrades to route_to_human while the relay is dormant.

Resolve which MFA rung the portal worker will drive for this account + portal: the account's per-portal override wins, else the curated matrix, else freeze_required (an unknown MFA method freezes the credential and requires a human — AC-13). A resolved 'sms' rung degrades to route_to_human while the relay is dormant.

Cookie session or Bearer token

Request body MfaResolveStrategyInputrequired

FieldTypeRequiredDescription
agencyIdstringrequired

Responses

  • 200Successful invocationMfaResolveStrategyOutput
    FieldTypeRequiredDescription
    strategyone of (enum: "totp" | "email" | "sms" | "route_to_human" | … · enum: "freeze_required")required
    sourceenum: "override" | "matrix" | "unresolved"required
    voipBlockedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/mfa.listHandoffsList the account's route-to-human MFA handoffs, newest first: any pending request (a portal session is waiting for a human to supply a code right now) plus the recent ledger (fulfilled / expired / escalated). Code values are never returned — codes are write-only.

List the account's route-to-human MFA handoffs, newest first: any pending request (a portal session is waiting for a human to supply a code right now) plus the recent ledger (fulfilled / expired / escalated). Code values are never returned — codes are write-only.

Cookie session or Bearer token

Request body MfaListHandoffsInputrequired

application/json

Responses

  • 200Successful invocationMfaListHandoffsOutput
    FieldTypeRequiredDescription
    handoffsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/mfa.submitHandoffCodeSupply the MFA code a waiting portal session asked for (route-to-human). Fulfills the pending handoff so the portal worker can inject the code; refused once the session window has lapsed. UI-only.

Supply the MFA code a waiting portal session asked for (route-to-human). Fulfills the pending handoff so the portal worker can inject the code; refused once the session window has lapsed. UI-only.

Cookie session or Bearer token

Request body MfaSubmitHandoffCodeInputrequired

FieldTypeRequiredDescription
handoffIdstringrequired
codestringrequired

Responses

  • 200Successful invocationMfaSubmitHandoffCodeOutput
    FieldTypeRequiredDescription
    fulfilledbooleanrequired
    windowLapsedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/mfa.listRelayNumbersList the account's leased receive-only relay numbers (one per credential, per the locked per-client model) and whether the SMS relay is currently enabled. Released numbers stay listed for the audit trail (AC-19).

List the account's leased receive-only relay numbers (one per credential, per the locked per-client model) and whether the SMS relay is currently enabled. Released numbers stay listed for the audit trail (AC-19).

Cookie session or Bearer token

Request body MfaListRelayNumbersInputrequired

application/json

Responses

  • 200Successful invocationMfaListRelayNumbersOutput
    FieldTypeRequiredDescription
    numbersarray<object>required
    smsEnabledbooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/mfa.leaseRelayNumberLease a receive-only relay number for one credential (the SMS rung of the waterfall). Dormant: refuses with sms_disabled until OTP_SMS_ENABLED and a provider account exist. UI-only.

Lease a receive-only relay number for one credential (the SMS rung of the waterfall). Dormant: refuses with sms_disabled until OTP_SMS_ENABLED and a provider account exist. UI-only.

Cookie session or Bearer token

Request body MfaLeaseRelayNumberInputrequired

FieldTypeRequiredDescription
credentialIdstringrequired

Responses

  • 200Successful invocationMfaLeaseRelayNumberOutput
    FieldTypeRequiredDescription
    numberobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/mfa.releaseRelayNumberRelease a leased relay number (AC-19: credential revocation releases its relay number; the row is kept for the audit trail). UI-only.

Release a leased relay number (AC-19: credential revocation releases its relay number; the row is kept for the audit trail). UI-only.

Cookie session or Bearer token

Request body MfaReleaseRelayNumberInputrequired

FieldTypeRequiredDescription
numberIdstringrequired

Responses

  • 200Successful invocationMfaReleaseRelayNumberOutput
    FieldTypeRequiredDescription
    releasedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:notice-intake14

POST/v1/notice-intake.uploadNoticeUpload a notice document to the notice intake pipeline. Computes SHA-256, uploads to Supabase Storage, INSERTs into notices, then fires runNoticePipeline() inline (fire-and-forget). AUTONOMOUS — recoverable; no agency impact at this stage.

Upload a notice document to the notice intake pipeline. Computes SHA-256, uploads to Supabase Storage, INSERTs into notices, then fires runNoticePipeline() inline (fire-and-forget). AUTONOMOUS — recoverable; no agency impact at this stage.

Cookie session or Bearer token

Request body NoticeIntakeUploadNoticeInputrequired

FieldTypeRequiredDescription
fileBufferstring · binaryrequired
fileNamestringrequired
contentTypestringrequired
sourceenum: "cpa_upload" | "employer_upload" | "email_intake" | "mail_scan" | …required
entityIdstringoptional
sourceVendorDocIdstringoptional
parentNoticeIdstringoptional

Responses

  • 200Successful invocationNoticeIntakeUploadNoticeOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    documentIdstringrequired
    storagePathstringrequired
    contentHashstringrequired
    pipelineEnqueuedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.ingestEmailWrap the existing /api/webhooks/inbound-email logic into a typed service method. Slug-based routing → domain fallback → unmatched queue. AUTONOMOUS — system-driven, idempotent at the inbound_emails row level.

Wrap the existing /api/webhooks/inbound-email logic into a typed service method. Slug-based routing → domain fallback → unmatched queue. AUTONOMOUS — system-driven, idempotent at the inbound_emails row level.

Cookie session or Bearer token

Request body NoticeIntakeIngestEmailInputrequired

FieldTypeRequiredDescription
resendPayloadobjectrequired

Responses

  • 200Successful invocationNoticeIntakeIngestEmailOutput
    FieldTypeRequiredDescription
    inboundEmailIdstringrequired
    matchMethodenum: "slug" | "domain" | "none"required
    matchedTenantIdstringrequired
    matchedEntityIdstringrequired
    unmatchedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.classifyNoticeWrap agentClassify with a typed service-method surface. Reads the notice's raw_text + state, calls the LLM classifier, persists notice_type_classified + classification_confidence + notice_facts. AUTONOMOUS — read-modify, recoverable.

Wrap agentClassify with a typed service-method surface. Reads the notice's raw_text + state, calls the LLM classifier, persists notice_type_classified + classification_confidence + notice_facts. AUTONOMOUS — read-modify, recoverable.

Cookie session or Bearer token

Request body NoticeIntakeClassifyNoticeInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired

Responses

  • 200Successful invocationNoticeIntakeClassifyNoticeOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    noticeTypestringrequired
    confidencenumberrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.ingestNoticeWrap agentIngest with a typed service-method surface. Runs OCR / text-extraction (Google Document AI -> Claude Vision fallback) + SHA-256 dedup, persists raw_text + sha256_hash + pipeline_status. AUTONOMOUS — read-modify, recoverable.

Wrap agentIngest with a typed service-method surface. Runs OCR / text-extraction (Google Document AI -> Claude Vision fallback) + SHA-256 dedup, persists raw_text + sha256_hash + pipeline_status. AUTONOMOUS — read-modify, recoverable.

Cookie session or Bearer token

Request body NoticeIntakeIngestNoticeInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired

Responses

  • 200Successful invocationNoticeIntakeIngestNoticeOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    pipelineStatusstringrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.validateNoticeWrap agentValidate with a typed service-method surface. Runs SUI / rate verification + payroll cross-reference, flags protest + potential savings, persists pipeline_status + protest_recommended. AUTONOMOUS — read-modify, recoverable.

Wrap agentValidate with a typed service-method surface. Runs SUI / rate verification + payroll cross-reference, flags protest + potential savings, persists pipeline_status + protest_recommended. AUTONOMOUS — read-modify, recoverable.

Cookie session or Bearer token

Request body NoticeIntakeValidateNoticeInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired

Responses

  • 200Successful invocationNoticeIntakeValidateNoticeOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    pipelineStatusstringrequired
    protestRecommendedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.setNoticeDeadlineWrap agentDeadline with a typed service-method surface. Computes the response deadline + protest clock from the notice's classification + per-state rules, persists deadline + protest_deadline + pipeline_status. AUTONOMOUS — read-modify, recoverable.

Wrap agentDeadline with a typed service-method surface. Computes the response deadline + protest clock from the notice's classification + per-state rules, persists deadline + protest_deadline + pipeline_status. AUTONOMOUS — read-modify, recoverable.

Cookie session or Bearer token

Request body NoticeIntakeSetNoticeDeadlineInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired

Responses

  • 200Successful invocationNoticeIntakeSetNoticeDeadlineOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    pipelineStatusstringrequired
    deadlinestringrequired
    protestDeadlinestringrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.reclassifyNoticeOperator-driven re-classification. Re-runs the classifier AND cascades to downstream agents (validate, deadline, draft). NOTIFY — operator override, audit-visible. Reason field NOT redacted (operator-authored; if PII leaks, it's the operator's responsibility — flagged in README).

Operator-driven re-classification. Re-runs the classifier AND cascades to downstream agents (validate, deadline, draft). NOTIFY — operator override, audit-visible. Reason field NOT redacted (operator-authored; if PII leaks, it's the operator's responsibility — flagged in README).

Cookie session or Bearer token

Request body NoticeIntakeReclassifyNoticeInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired
reasonstringrequired

Responses

  • 200Successful invocationNoticeIntakeReclassifyNoticeOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    noticeTypestringrequired
    confidencenumberrequired
    cascadedAgentsarray<string>required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.routeNoticeAssign a notice to an employer entity. Mirrors entity-match-resolve route's 'confirmed' action. Pure data update — does NOT advance pipeline_status, does NOT cascade to downstream agents. NOTIFY — operator override, audit-visible.

Assign a notice to an employer entity. Mirrors entity-match-resolve route's 'confirmed' action. Pure data update — does NOT advance pipeline_status, does NOT cascade to downstream agents. NOTIFY — operator override, audit-visible.

Cookie session or Bearer token

Request body NoticeIntakeRouteNoticeInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired
entityIdstringrequired

Responses

  • 200Successful invocationNoticeIntakeRouteNoticeOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    previousEntityIdstringrequired
    newEntityIdstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.flagJunkMark a notice as junk. Sets is_junk=true + pipeline_status=DISMISSED. NOTIFY — recoverable (operator can unflag); no compliance impact from a wrong call. Compliance-impact gate is at submitProtest (Phase 3).

Mark a notice as junk. Sets is_junk=true + pipeline_status=DISMISSED. NOTIFY — recoverable (operator can unflag); no compliance impact from a wrong call. Compliance-impact gate is at submitProtest (Phase 3).

Cookie session or Bearer token

Request body NoticeIntakeFlagJunkInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired
reasonenum: "marketing" | "portal_automation" | "bounce_notification" | "newsletter" | …required
reasonDetailstringoptional

Responses

  • 200Successful invocationNoticeIntakeFlagJunkOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    isJunkenum: truerequired
    pipelineStatusenum: "DISMISSED"required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.unflagJunkReverse a junk flag. Sets is_junk=false + pipeline_status=PENDING so the normal pipeline can re-run. NOTIFY — operator override; the reason field is the operator's audit-rationale (10–500 chars).

Reverse a junk flag. Sets is_junk=false + pipeline_status=PENDING so the normal pipeline can re-run. NOTIFY — operator override; the reason field is the operator's audit-rationale (10–500 chars).

Cookie session or Bearer token

Request body NoticeIntakeUnflagJunkInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired
reasonstringrequired

Responses

  • 200Successful invocationNoticeIntakeUnflagJunkOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    isJunkenum: falserequired
    pipelineStatusenum: "PENDING"required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.draftNoticeWrap agentDraft with a typed service-method surface. Generates the protest-letter draft for the notice (persists `protest_draft` + `protest_draft_generated_at` + `pipeline_status='READY_FOR_REVIEW'`) and returns a typed acknowledgment. NOTIFY — read-modify, a human reviews the draft before any external send.

Wrap agentDraft with a typed service-method surface. Generates the protest-letter draft for the notice (persists `protest_draft` + `protest_draft_generated_at` + `pipeline_status='READY_FOR_REVIEW'`) and returns a typed acknowledgment. NOTIFY — read-modify, a human reviews the draft before any external send.

Cookie session or Bearer token

Request body NoticeIntakeDraftNoticeInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired

Responses

  • 200Successful invocationNoticeIntakeDraftNoticeOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    hasDraftbooleanrequired
    draftLengthintegerrequired
    pipelineStatusstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.approveNoticeOperator marks the generated draft as approved + ready to file. Records approved_at + approved_by + cpa_action='approved'. Does NOT transition pipeline_status or send anything externally. NOTIFY — reversible; fileNotice is the external-impact gate.

Operator marks the generated draft as approved + ready to file. Records approved_at + approved_by + cpa_action='approved'. Does NOT transition pipeline_status or send anything externally. NOTIFY — reversible; fileNotice is the external-impact gate.

Cookie session or Bearer token

Request body NoticeIntakeApproveNoticeInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired
notestringoptional

Responses

  • 200Successful invocationNoticeIntakeApproveNoticeOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    approvedAtstringrequired
    cpaActionenum: "approved"required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.fileNoticeOperator records that the approved response has been transmitted to the agency. Stores filed_at + filed_by + filing_method, advances pipeline_status to ACTIONED. Requires cpa_action='approved' (the approve-before-file invariant). NOTIFY — records external act; Kreto itself does NOT mail/fax/post in this op.

Operator records that the approved response has been transmitted to the agency. Stores filed_at + filed_by + filing_method, advances pipeline_status to ACTIONED. Requires cpa_action='approved' (the approve-before-file invariant). NOTIFY — records external act; Kreto itself does NOT mail/fax/post in this op.

Cookie session or Bearer token

Request body NoticeIntakeFileNoticeInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired
filingMethodenum: "mail" | "fax" | "online_portal" | "email" | …required
notestringoptional

Responses

  • 200Successful invocationNoticeIntakeFileNoticeOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    filedAtstringrequired
    filingMethodenum: "mail" | "fax" | "online_portal" | "email" | …required
    pipelineStatusenum: "ACTIONED"required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notice-intake.escalateNoticeFlag a notice for senior-CPA review. Sets is_escalated=true + escalated_at + escalated_by + escalation_reason. Does NOT change pipeline_status (escalation is orthogonal). Idempotent — re-calling updates the reason + timestamp. NOTIFY — flag-only; no external impact.

Flag a notice for senior-CPA review. Sets is_escalated=true + escalated_at + escalated_by + escalation_reason. Does NOT change pipeline_status (escalation is orthogonal). Idempotent — re-calling updates the reason + timestamp. NOTIFY — flag-only; no external impact.

Cookie session or Bearer token

Request body NoticeIntakeEscalateNoticeInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired
reasonstringrequired

Responses

  • 200Successful invocationNoticeIntakeEscalateNoticeOutput
    FieldTypeRequiredDescription
    noticeIdstringrequired
    isEscalatedenum: truerequired
    escalatedAtstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:notices4

POST/v1/notices.submitDraftFeedbackRecord thumbs-up/down feedback on a notice response draft. Asserts the notice and draft both belong to the caller's tenant, inserts a draft_feedback row, and emits a product-analytics event. NOTIFY — operator-driven, audit-visible.

Record thumbs-up/down feedback on a notice response draft. Asserts the notice and draft both belong to the caller's tenant, inserts a draft_feedback row, and emits a product-analytics event. NOTIFY — operator-driven, audit-visible.

Cookie session or Bearer token

Request body NoticesSubmitDraftFeedbackInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired
draftIdstringrequired
ratingenum: "thumbs_up" | "thumbs_down"required
commentstringoptional

Responses

  • 200Successful invocationNoticesSubmitDraftFeedbackOutput
    FieldTypeRequiredDescription
    successenum: truerequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notices.resolveEntityMatchResolve a notice's fuzzy entity match: confirm an existing entity, or create a new entity under the notice's tenant and assign it. Tenant-scoped with defense-in-depth assertions. NOTIFY — operator-driven, audit-visible.

Resolve a notice's fuzzy entity match: confirm an existing entity, or create a new entity under the notice's tenant and assign it. Tenant-scoped with defense-in-depth assertions. NOTIFY — operator-driven, audit-visible.

Cookie session or Bearer token

Request body NoticesResolveEntityMatchInputrequired

application/json

Responses

  • 200Successful invocationNoticesResolveEntityMatchOutput
    FieldTypeRequiredDescription
    successenum: truerequired
    entityIdstringrequired
    actionenum: "confirmed" | "create_new"required
    entityNamestringoptional
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notices.linkLink an agency-response notice to its parent (original) notice and record the response type (acceptance/counter/additional_info_request/rejection). Sets parent_notice_id + agency_response_type on the response notice. Both notices must belong to the caller's tenant. AUTONOMOUS — internal edge write, recoverable, no agency impact.

Link an agency-response notice to its parent (original) notice and record the response type (acceptance/counter/additional_info_request/rejection). Sets parent_notice_id + agency_response_type on the response notice. Both notices must belong to the caller's tenant. AUTONOMOUS — internal edge write, recoverable, no agency impact.

Cookie session or Bearer token

Request body NoticesLinkInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired
parentNoticeIdstringrequired
agencyResponseTypeenum: "acceptance" | "counter" | "additional_info_request" | "rejection"required

Responses

  • 200Successful invocationNoticesLinkOutput
    FieldTypeRequiredDescription
    successenum: truerequired
    noticeIdstringrequired
    parentNoticeIdstringrequired
    agencyResponseTypeenum: "acceptance" | "counter" | "additional_info_request" | "rejection"required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notices.deadlineSweepPreview the deadline escalations that would fire for your tenant — which compliance-notice deadlines are escalating and who would be notified. Read-only plan over the same ladder + candidate filter the hourly cron uses; sends nothing and writes nothing (the cron does the actual emails/push/Slack). Use to surface what deadlines need attention now. NOTIFY — surfaces work for human attention, no external impact.

Preview the deadline escalations that would fire for your tenant — which compliance-notice deadlines are escalating and who would be notified. Read-only plan over the same ladder + candidate filter the hourly cron uses; sends nothing and writes nothing (the cron does the actual emails/push/Slack). Use to surface what deadlines need attention now. NOTIFY — surfaces work for human attention, no external impact.

Cookie session or Bearer token

Request body NoticesDeadlineSweepInputrequired

FieldTypeRequiredDescription
entityIdstringoptional
horizonDaysintegeroptional

Responses

  • 200Successful invocationNoticesDeadlineSweepOutput
    FieldTypeRequiredDescription
    asOfstringrequired
    scannedNoticesintegerrequired
    escalationsarray<object>required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:notifications2

POST/v1/notifications.listList the account's vault notifications, newest first: pending time-critical items (awaiting a human acknowledgement) and the informational ledger (rotations completed, credentials frozen, health changes). Content is reference-and-action only — never a secret, code, or amount.

List the account's vault notifications, newest first: pending time-critical items (awaiting a human acknowledgement) and the informational ledger (rotations completed, credentials frozen, health changes). Content is reference-and-action only — never a secret, code, or amount.

Cookie session or Bearer token

Request body NotificationsListInputrequired

FieldTypeRequiredDescription
statusenum: "pending" | "acknowledged" | "expired"optional

Responses

  • 200Successful invocationNotificationsListOutput
    FieldTypeRequiredDescription
    notificationsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/notifications.ackAcknowledge a time-critical notification, stopping its escalation. Escalate-until-ack means until a HUMAN acks — UI-only by design.

Acknowledge a time-critical notification, stopping its escalation. Escalate-until-ack means until a HUMAN acks — UI-only by design.

Cookie session or Bearer token

Request body NotificationsAckInputrequired

FieldTypeRequiredDescription
notificationIdstringrequired

Responses

  • 200Successful invocationNotificationsAckOutput
    FieldTypeRequiredDescription
    acknowledgedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:payments5

POST/v1/payments.remitRequest a payment from a stored payment/bank credential. Creates an approval request ONLY — money never moves without a human approving this exact request (the hard floor no configuration can relax). The responsible humans are notified WITHOUT the amount; they first see the figure on the approval screen.

Request a payment from a stored payment/bank credential. Creates an approval request ONLY — money never moves without a human approving this exact request (the hard floor no configuration can relax). The responsible humans are notified WITHOUT the amount; they first see the figure on the approval screen.

Cookie session or Bearer token

Request body PaymentsRemitInputrequired

FieldTypeRequiredDescription
credentialIdstringrequired
payeestringrequired
amountCentsintegerrequired
currencystringoptional
memostringoptional

Responses

  • 200Successful invocationPaymentsRemitOutput
    FieldTypeRequiredDescription
    requestobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/payments.listList the account's payment approval requests, newest first. Use to surface what is awaiting human approval; approving is UI-only.

List the account's payment approval requests, newest first. Use to surface what is awaiting human approval; approving is UI-only.

Cookie session or Bearer token

Request body PaymentsListInputrequired

FieldTypeRequiredDescription
statusenum: "requested" | "approved" | "rejected" | "expired"optional

Responses

  • 200Successful invocationPaymentsListOutput
    FieldTypeRequiredDescription
    requestsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/payments.approveApprove a pending payment request — the money-movement hard floor. Requires a human actor and a typed amount that matches the request exactly; the approval (approver identity + amount) is sealed into the tamper-evident audit chain and becomes the authorization. UI-only; no configuration can bypass this step.

Approve a pending payment request — the money-movement hard floor. Requires a human actor and a typed amount that matches the request exactly; the approval (approver identity + amount) is sealed into the tamper-evident audit chain and becomes the authorization. UI-only; no configuration can bypass this step.

Cookie session or Bearer token

Request body PaymentsApproveInputrequired

FieldTypeRequiredDescription
approvalIdstringrequired
confirmAmountCentsintegerrequired

Responses

  • 200Successful invocationPaymentsApproveOutput
    FieldTypeRequiredDescription
    requestobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/payments.rejectReject a pending payment request. The rejection is recorded on the audit chain. UI-only.

Reject a pending payment request. The rejection is recorded on the audit chain. UI-only.

Cookie session or Bearer token

Request body PaymentsRejectInputrequired

FieldTypeRequiredDescription
approvalIdstringrequired

Responses

  • 200Successful invocationPaymentsRejectOutput
    FieldTypeRequiredDescription
    requestobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/payments.executeExecute an APPROVED payment. DORMANT: Kreto has no payment rails — this refuses payment_rails_unavailable for every request, approved or not. When an ACH/provider integration lands it slots in here; the approval floor above it does not change. UI-only.

Execute an APPROVED payment. DORMANT: Kreto has no payment rails — this refuses payment_rails_unavailable for every request, approved or not. When an ACH/provider integration lands it slots in here; the approval floor above it does not change. UI-only.

Cookie session or Bearer token

Request body PaymentsExecuteInputrequired

FieldTypeRequiredDescription
approvalIdstringrequired

Responses

  • 200Successful invocationPaymentsExecuteOutput
    FieldTypeRequiredDescription
    executedenum: falserequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:payroll1

POST/v1/payroll.connectInitiate a payroll connection for an entity. Returns 'connected' (already linked), 'consent_required' (the employer must accept the KRT-768 consent in the UI first — never recorded on their behalf), or 'pending' (consent present; a pending connection intent is recorded and the employer completes the provider OAuth in the UI). Use to unblock a notice that needs payroll. NOTIFY — records the intent; the actual link is the employer's OAuth action.

Initiate a payroll connection for an entity. Returns 'connected' (already linked), 'consent_required' (the employer must accept the KRT-768 consent in the UI first — never recorded on their behalf), or 'pending' (consent present; a pending connection intent is recorded and the employer completes the provider OAuth in the UI). Use to unblock a notice that needs payroll. NOTIFY — records the intent; the actual link is the employer's OAuth action.

Cookie session or Bearer token

Request body PayrollConnectInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
providerenum: "gusto" | "adp_run" | "paychex" | "paylocity" | …required

Responses

  • 200Successful invocationPayrollConnectOutput
    FieldTypeRequiredDescription
    entityIdstringrequired
    providerenum: "gusto" | "adp_run" | "paychex" | "paylocity" | …required
    statusenum: "connected" | "consent_required" | "pending"required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:peo7

POST/v1/peo.listEmployersList the PEO tenant's managed employer book with per-employer compliance rollups: open-notice count, obligations due within 30 days, state registrations in flight, compliance score, declared employee count, and PEPM subscription status. Paginated via `page` (1-indexed) and `pageSize` (1-50, default 12). Optional `filter` (all | attention | registrations_in_flight | no_subscription), case-insensitive `search` on legal name, and `sort` (name | score | open_notices). Tenant-scoped. Returns aggregates + business identifiers only — no PII (EIN as last-4 only, no contact fields). Requires the ENABLE_PEO_PORTAL flag; refuses with FEATURE_DISABLED when off.

List the PEO tenant's managed employer book with per-employer compliance rollups: open-notice count, obligations due within 30 days, state registrations in flight, compliance score, declared employee count, and PEPM subscription status. Paginated via `page` (1-indexed) and `pageSize` (1-50, default 12). Optional `filter` (all | attention | registrations_in_flight | no_subscription), case-insensitive `search` on legal name, and `sort` (name | score | open_notices). Tenant-scoped. Returns aggregates + business identifiers only — no PII (EIN as last-4 only, no contact fields). Requires the ENABLE_PEO_PORTAL flag; refuses with FEATURE_DISABLED when off.

Cookie session or Bearer token

Request body PeoListEmployersInputrequired

FieldTypeRequiredDescription
pageintegeroptional
pageSizeintegeroptional
filterenum: "all" | "attention" | "registrations_in_flight" | "no_subscription"optional
searchstringoptional
sortenum: "name" | "score" | "open_notices"optional

Responses

  • 200Successful invocationPeoListEmployersOutput
    FieldTypeRequiredDescription
    employersarray<object>required
    totalintegerrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/peo.getPortfolioSummaryBook-level compliance + billing summary for the PEO tenant: employer count, total open notices, state registrations in flight, obligations due within 30 days, the top-5 at-risk employers by ascending compliance score, and the estimated monthly PEPM total (estimate at the live per-entity rate — read-only, no Stripe interaction). Takes no input. Tenant-scoped; returns aggregates + business identifiers only, no PII. Requires the ENABLE_PEO_PORTAL flag; refuses with FEATURE_DISABLED when off.

Book-level compliance + billing summary for the PEO tenant: employer count, total open notices, state registrations in flight, obligations due within 30 days, the top-5 at-risk employers by ascending compliance score, and the estimated monthly PEPM total (estimate at the live per-entity rate — read-only, no Stripe interaction). Takes no input. Tenant-scoped; returns aggregates + business identifiers only, no PII. Requires the ENABLE_PEO_PORTAL flag; refuses with FEATURE_DISABLED when off.

Cookie session or Bearer token

Request body PeoGetPortfolioSummaryInputrequired

application/json

Responses

  • 200Successful invocationPeoGetPortfolioSummaryOutput
    FieldTypeRequiredDescription
    employerCountintegerrequired
    openNoticesintegerrequired
    registrationsInFlightintegerrequired
    obligationsDue30integerrequired
    atRiskarray<object>required
    estimatedMonthlyPepmUsdnumberrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/peo.getBillingRollupRead-only aggregate PEPM billing view over the PEO tenant's employer book: one row per employer with the resolved billing quantity (via the live source-priority chain: payroll > declared > employees), quantity source, subscription status, estimated monthly cost at the current per-entity rate, and whether a Stripe customer-portal link is available — plus book-wide totals (billable employees, estimated monthly total, subscribed count, and how many employers were excluded as unresolvable). All figures are ESTIMATES; this method never creates or mutates any Stripe object. Paginated via `page` / `pageSize` (1-50, default 12). Requires the ENABLE_PEO_PORTAL flag; refuses with FEATURE_DISABLED when off.

Read-only aggregate PEPM billing view over the PEO tenant's employer book: one row per employer with the resolved billing quantity (via the live source-priority chain: payroll > declared > employees), quantity source, subscription status, estimated monthly cost at the current per-entity rate, and whether a Stripe customer-portal link is available — plus book-wide totals (billable employees, estimated monthly total, subscribed count, and how many employers were excluded as unresolvable). All figures are ESTIMATES; this method never creates or mutates any Stripe object. Paginated via `page` / `pageSize` (1-50, default 12). Requires the ENABLE_PEO_PORTAL flag; refuses with FEATURE_DISABLED when off.

Cookie session or Bearer token

Request body PeoGetBillingRollupInputrequired

FieldTypeRequiredDescription
pageintegeroptional
pageSizeintegeroptional

Responses

  • 200Successful invocationPeoGetBillingRollupOutput
    FieldTypeRequiredDescription
    rowsarray<object>required
    totalintegerrequired
    totalsobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/peo.addEmployerAdd a single managed employer to the PEO tenant's book. Creates an entities row (legal name, primary state, optional EIN — persisted as last-4 only — contact fields, declared employee count) plus the hash-chained audit event, reusing the standard employer-creation path. Refuses with DUPLICATE_EMPLOYER (409) when an employer with the same normalized legal name + primary state already exists. Requires the ENABLE_PEO_PORTAL flag; refuses with FEATURE_DISABLED when off.

Add a single managed employer to the PEO tenant's book. Creates an entities row (legal name, primary state, optional EIN — persisted as last-4 only — contact fields, declared employee count) plus the hash-chained audit event, reusing the standard employer-creation path. Refuses with DUPLICATE_EMPLOYER (409) when an employer with the same normalized legal name + primary state already exists. Requires the ENABLE_PEO_PORTAL flag; refuses with FEATURE_DISABLED when off.

Cookie session or Bearer token

Request body PeoAddEmployerInputrequired

FieldTypeRequiredDescription
legalNamestringrequired
primaryStatestringrequired
einstringoptional
contactNamestringoptional
contactEmailstring · emailoptional
declaredEmployeeCountintegeroptional

Responses

  • 200Successful invocationPeoAddEmployerOutput
    FieldTypeRequiredDescription
    entityIdstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/peo.validateEmployerImportValidate and stage an employer-book CSV for the PEO tenant. Parses the CSV server-side (columns: legal_name*, primary_state*, ein, contact_name, contact_email, declared_employee_count; 2 MB / 2,000 row caps), normalizes every row, reduces any full EIN to its last 4 digits, detects duplicates against both existing employers and other rows in the same file, and stages every row with a per-row verdict (valid | error | duplicate) plus machine-readable reasons. Returns the staged import id and verdict counts. STAGING ONLY — never creates employers; a human must review and commit the staged import from the portal. Refuses with IMPORT_TOO_LARGE (400) over the caps, VALIDATION_FAILED (422) for an unparseable file or broken header, and FEATURE_DISABLED (403) when the ENABLE_PEO_PORTAL flag is off.

Validate and stage an employer-book CSV for the PEO tenant. Parses the CSV server-side (columns: legal_name*, primary_state*, ein, contact_name, contact_email, declared_employee_count; 2 MB / 2,000 row caps), normalizes every row, reduces any full EIN to its last 4 digits, detects duplicates against both existing employers and other rows in the same file, and stages every row with a per-row verdict (valid | error | duplicate) plus machine-readable reasons. Returns the staged import id and verdict counts. STAGING ONLY — never creates employers; a human must review and commit the staged import from the portal. Refuses with IMPORT_TOO_LARGE (400) over the caps, VALIDATION_FAILED (422) for an unparseable file or broken header, and FEATURE_DISABLED (403) when the ENABLE_PEO_PORTAL flag is off.

Cookie session or Bearer token

Request body PeoValidateEmployerImportInputrequired

FieldTypeRequiredDescription
filenamestringrequired
csvTextstringrequired

Responses

  • 200Successful invocationPeoValidateEmployerImportOutput
    FieldTypeRequiredDescription
    importIdstringrequired
    rowCountintegerrequired
    validCountintegerrequired
    errorCountintegerrequired
    duplicateCountintegerrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/peo.getImportRead a staged employer-CSV import: the summary (filename, lifecycle status, row/valid/error/duplicate counts, committed-at) plus the staged rows with per-row verdicts (valid | error | duplicate), machine-readable reasons, and — after a commit — the created entity id or per-row commit error. Feeds the import wizard's review and commit-progress screens. Paginated via `page` / `pageSize` (1-2,000, default 2,000 — one page covers a whole v1 import). Tenant-scoped; returns business identifiers only (EIN as last-4, no contact fields). Refuses with IMPORT_NOT_FOUND (404) for unknown or other-tenant imports and FEATURE_DISABLED (403) when the ENABLE_PEO_PORTAL flag is off.

Read a staged employer-CSV import: the summary (filename, lifecycle status, row/valid/error/duplicate counts, committed-at) plus the staged rows with per-row verdicts (valid | error | duplicate), machine-readable reasons, and — after a commit — the created entity id or per-row commit error. Feeds the import wizard's review and commit-progress screens. Paginated via `page` / `pageSize` (1-2,000, default 2,000 — one page covers a whole v1 import). Tenant-scoped; returns business identifiers only (EIN as last-4, no contact fields). Refuses with IMPORT_NOT_FOUND (404) for unknown or other-tenant imports and FEATURE_DISABLED (403) when the ENABLE_PEO_PORTAL flag is off.

Cookie session or Bearer token

Request body PeoGetImportInputrequired

FieldTypeRequiredDescription
importIdstringrequired
pageintegeroptional
pageSizeintegeroptional

Responses

  • 200Successful invocationPeoGetImportOutput
    FieldTypeRequiredDescription
    importobjectrequired
    rowsarray<object>required
    rowTotalintegerrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/peo.commitEmployerImportCommit a staged employer-CSV import — the HUMAN approval gate of the bulk-import pipeline. Verifies the import belongs to the tenant and is committable (status 'staged', or 'failed' to resume a partial failure), flips it to 'committing', and enqueues the idempotent peo_import_commit worker job that creates one employer (entities row) per valid staged row with hash-chained audit evidence. Returns the job id; poll peo.getImport for per-row progress. Session-only: APPROVAL_REQUIRED risk level (excluded from MCP/CLI; the API dispatcher refuses non-session callers) and the handler rejects any non-user actor. Refuses with IMPORT_NOT_STAGED (409) for non-committable states, IMPORT_NOT_FOUND (404) for unknown or other-tenant imports, and FEATURE_DISABLED (403) when the ENABLE_PEO_PORTAL flag is off.

Commit a staged employer-CSV import — the HUMAN approval gate of the bulk-import pipeline. Verifies the import belongs to the tenant and is committable (status 'staged', or 'failed' to resume a partial failure), flips it to 'committing', and enqueues the idempotent peo_import_commit worker job that creates one employer (entities row) per valid staged row with hash-chained audit evidence. Returns the job id; poll peo.getImport for per-row progress. Session-only: APPROVAL_REQUIRED risk level (excluded from MCP/CLI; the API dispatcher refuses non-session callers) and the handler rejects any non-user actor. Refuses with IMPORT_NOT_STAGED (409) for non-committable states, IMPORT_NOT_FOUND (404) for unknown or other-tenant imports, and FEATURE_DISABLED (403) when the ENABLE_PEO_PORTAL flag is off.

Cookie session or Bearer token

Request body PeoCommitEmployerImportInputrequired

FieldTypeRequiredDescription
importIdstringrequired

Responses

  • 200Successful invocationPeoCommitEmployerImportOutput
    FieldTypeRequiredDescription
    jobIdstringrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:poa-filing3

POST/v1/poa-filing.generate8821Generate an IRS Form 8821 (Tax Information Authorization) naming Kreto Inc. as the taxpayer's information designee. Fills the official IRS PDF template with the taxpayer's entity data and selected tax matters / years, uploads the unsigned PDF to Supabase Storage, creates a draft poa_authorizations row and a signature_requests row, returns the signing URL. The taxpayer (authorized signer on the entity) signs via the existing signing flow; finalization writes the signed PDF URL back to the poa_authorizations row.

Generate an IRS Form 8821 (Tax Information Authorization) naming Kreto Inc. as the taxpayer's information designee. Fills the official IRS PDF template with the taxpayer's entity data and selected tax matters / years, uploads the unsigned PDF to Supabase Storage, creates a draft poa_authorizations row and a signature_requests row, returns the signing URL. The taxpayer (authorized signer on the entity) signs via the existing signing flow; finalization writes the signed PDF URL back to the poa_authorizations row.

Cookie session or Bearer token

Request body PoaFilingGenerate8821Inputrequired

FieldTypeRequiredDescription
employerEntityIdstringrequired
taxMattersarray<enum: "income" | "employment" | "excise" | "estate" | …>required
taxYearsarray<integer>required
signerEmailstring · emailoptional
signerTitlestringoptional

Responses

  • 200Successful invocationPoaFilingGenerate8821Output
    FieldTypeRequiredDescription
    poaAuthorizationIdstringrequired
    signatureRequestIdstringrequired
    signingUrlstringrequired
    unsignedPdfUrlstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/poa-filing.listPendingFilingsAdmin-only: list signed IRS Form 8821 POAs awaiting filing or in post-filing IRS states. Cross-tenant (Kreto staff console). Returns submission_status, signer info, filing_date, and CAF number for each row. Use to triage what 8821s are ready to upload to irs.gov/Submit8821, or to audit recent filings.

Admin-only: list signed IRS Form 8821 POAs awaiting filing or in post-filing IRS states. Cross-tenant (Kreto staff console). Returns submission_status, signer info, filing_date, and CAF number for each row. Use to triage what 8821s are ready to upload to irs.gov/Submit8821, or to audit recent filings.

Cookie session or Bearer token

Request body PoaFilingListPendingFilingsInputrequired

FieldTypeRequiredDescription
statusenum: "signed" | "submitted" | "accepted" | "rejected"optionalFilter by submission_status. Omit to receive every non-draft row.
limitintegeroptional
offsetintegeroptional

Responses

  • 200Successful invocationPoaFilingListPendingFilingsOutput
    FieldTypeRequiredDescription
    rowsarray<object>required
    totalintegerrequired
  • 400Validation error (input schema rejected). risk_level=elevated.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/poa-filing.transitionPoaFilingStatusAdmin-only: advance the IRS 8821 filing state machine for a single POA. Allowed: signed→submitted (Kreto staff uploaded to IRS portal), submitted→accepted (record CAF number from IRS ack), submitted→ rejected (record IRS rejection reason). Any other transition errors. Use to mirror IRS portal interactions back into Kreto state.

Admin-only: advance the IRS 8821 filing state machine for a single POA. Allowed: signed→submitted (Kreto staff uploaded to IRS portal), submitted→accepted (record CAF number from IRS ack), submitted→ rejected (record IRS rejection reason). Any other transition errors. Use to mirror IRS portal interactions back into Kreto state.

Cookie session or Bearer token

Request body PoaFilingTransitionPoaFilingStatusInputrequired

FieldTypeRequiredDescription
poaAuthorizationIdstringrequired
toStatusenum: "submitted" | "accepted" | "rejected"required
cafNumberstringoptional
rejectionReasonstringoptional

Responses

  • 200Successful invocationPoaFilingTransitionPoaFilingStatusOutput
    FieldTypeRequiredDescription
    poaAuthorizationIdstringrequired
    submissionStatusenum: "signed" | "submitted" | "accepted" | "rejected" | …required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:policy2

POST/v1/policy.getGet the mailbox automation policy for the caller's tenant (or a specific entity): the per-action execution-mode matrix + step-up threshold + outbound posture, and the deadline-escalation ladder. Returns conservative code defaults (isDefault=true) when no policy row exists. AUTONOMOUS — read-only.

Get the mailbox automation policy for the caller's tenant (or a specific entity): the per-action execution-mode matrix + step-up threshold + outbound posture, and the deadline-escalation ladder. Returns conservative code defaults (isDefault=true) when no policy row exists. AUTONOMOUS — read-only.

Cookie session or Bearer token

Request body PolicyGetInputrequired

FieldTypeRequiredDescription
entityIdstringoptional

Responses

  • 200Successful invocationPolicyGetOutput
    FieldTypeRequiredDescription
    policyobjectrequired
    isDefaultbooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/policy.updateSet the mailbox automation policy for the caller's tenant (or a specific entity): the per-action execution-mode matrix + step-up threshold + outbound posture, and the deadline-escalation ladder. Upserts the single (tenant, entity) row and seals an audit event. NOTIFY — a human-made control-plane change; it never auto-executes anything itself.

Set the mailbox automation policy for the caller's tenant (or a specific entity): the per-action execution-mode matrix + step-up threshold + outbound posture, and the deadline-escalation ladder. Upserts the single (tenant, entity) row and seals an audit event. NOTIFY — a human-made control-plane change; it never auto-executes anything itself.

Cookie session or Bearer token

Request body PolicyUpdateInputrequired

FieldTypeRequiredDescription
entityIdstringoptional
byActionTypeobjectrequired
escalationobjectrequired

Responses

  • 200Successful invocationPolicyUpdateOutput
    FieldTypeRequiredDescription
    policyobjectrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:resolutions8

POST/v1/resolutions.getGet a single resolution draft by id for the caller's tenant. Returns the draft letter, status, and the agentic resolution metadata (needs_input/needs_connection/decision_context/trace). Tenant-scoped with a defense-in-depth cross-tenant assertion. AUTONOMOUS — read-only.

Get a single resolution draft by id for the caller's tenant. Returns the draft letter, status, and the agentic resolution metadata (needs_input/needs_connection/decision_context/trace). Tenant-scoped with a defense-in-depth cross-tenant assertion. AUTONOMOUS — read-only.

Cookie session or Bearer token

Request body ResolutionsGetInputrequired

FieldTypeRequiredDescription
resolutionIdstringrequired

Responses

  • 200Successful invocationResolutionsGetOutput
    FieldTypeRequiredDescription
    resolutionobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/resolutions.listList all resolution draft versions for a notice (newest version first) for the caller's tenant. Use to surface a notice's proposed responses and their approval status. Tenant-scoped with a defense-in-depth cross-tenant assertion. AUTONOMOUS — read-only.

List all resolution draft versions for a notice (newest version first) for the caller's tenant. Use to surface a notice's proposed responses and their approval status. Tenant-scoped with a defense-in-depth cross-tenant assertion. AUTONOMOUS — read-only.

Cookie session or Bearer token

Request body ResolutionsListInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired

Responses

  • 200Successful invocationResolutionsListOutput
    FieldTypeRequiredDescription
    itemsarray<object>required
    totalintegerrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/resolutions.reconcileAndDraftReconcile an actionable notice against the entity's connected payroll and draft a resolution. Returns needs_connection (no payroll linked) or needs_input (payroll missing for the period) synchronously; otherwise enqueues the reconcile+draft worker job and returns 'queued' (read the draft + line-level trace via resolutions.get/list). AUTONOMOUS — computes + queues; a human reviews the draft before anything files.

Reconcile an actionable notice against the entity's connected payroll and draft a resolution. Returns needs_connection (no payroll linked) or needs_input (payroll missing for the period) synchronously; otherwise enqueues the reconcile+draft worker job and returns 'queued' (read the draft + line-level trace via resolutions.get/list). AUTONOMOUS — computes + queues; a human reviews the draft before anything files.

Cookie session or Bearer token

Request body ResolutionsReconcileAndDraftInputrequired

FieldTypeRequiredDescription
noticeIdstringrequired

Responses

  • 200Successful invocationResolutionsReconcileAndDraftOutput
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/resolutions.supplyInputSupply the missing fields a draft is blocked on, clearing needs_input (AC-6). Records the values so the reconcile can re-run, and surfaces the draft for review. NOTIFY — writes a human-reviewed update; files nothing.

Supply the missing fields a draft is blocked on, clearing needs_input (AC-6). Records the values so the reconcile can re-run, and surfaces the draft for review. NOTIFY — writes a human-reviewed update; files nothing.

Cookie session or Bearer token

Request body ResolutionsSupplyInputInputrequired

FieldTypeRequiredDescription
resolutionIdstringrequired
inputsobjectrequired

Responses

  • 200Successful invocationResolutionsSupplyInputOutput
    FieldTypeRequiredDescription
    resolutionobjectrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/resolutions.recordOutcomeRecord an agency response on a resolution — acceptance confirms the matter, anything else reopens it (AC-12) — and seal the transition into the SHA-256 audit chain. AUTONOMOUS — deterministic classification of the agency's reply; no human gate.

Record an agency response on a resolution — acceptance confirms the matter, anything else reopens it (AC-12) — and seal the transition into the SHA-256 audit chain. AUTONOMOUS — deterministic classification of the agency's reply; no human gate.

Cookie session or Bearer token

Request body ResolutionsRecordOutcomeInputrequired

FieldTypeRequiredDescription
resolutionIdstringrequired
agencyResponseTypeenum: "acceptance" | "counter" | "additional_info_request" | "rejection"required

Responses

  • 200Successful invocationResolutionsRecordOutcomeOutput
    FieldTypeRequiredDescription
    resolutionobjectrequired
    outcomeenum: "confirmed" | "reopened"required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/resolutions.approveApprove a resolution draft (transitions draft -> approved). Requires a typed confirmation phrase ("APPROVE"). APPROVAL_REQUIRED — human gate; files/moves nothing by itself (execute is the external-impact step). UI-only: not exposed via MCP/CLI.

Approve a resolution draft (transitions draft -> approved). Requires a typed confirmation phrase ("APPROVE"). APPROVAL_REQUIRED — human gate; files/moves nothing by itself (execute is the external-impact step). UI-only: not exposed via MCP/CLI.

Cookie session or Bearer token

Request body ResolutionsApproveInputrequired

FieldTypeRequiredDescription
resolutionIdstringrequired
confirmationPhrasestringrequiredTyped confirmation — must equal "APPROVE" (AC-9 typed-confirm).

Responses

  • 200Successful invocationResolutionsApproveOutput
    FieldTypeRequiredDescription
    resolutionobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/resolutions.rejectReject a resolution draft (transitions draft -> rejected). Records the reason; redraft=true signals the redraft loop, otherwise the matter is finalized. APPROVAL_REQUIRED — human gate; UI-only, not MCP/CLI-exposed.

Reject a resolution draft (transitions draft -> rejected). Records the reason; redraft=true signals the redraft loop, otherwise the matter is finalized. APPROVAL_REQUIRED — human gate; UI-only, not MCP/CLI-exposed.

Cookie session or Bearer token

Request body ResolutionsRejectInputrequired

FieldTypeRequiredDescription
resolutionIdstringrequired
reasonstringoptional
redraftbooleanoptional

Responses

  • 200Successful invocationResolutionsRejectOutput
    FieldTypeRequiredDescription
    resolutionobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/resolutions.executeExecute an approved resolution: record the agency filing (operator-attested) and advance the notice to ACTIONED, sealing a hash-chained audit receipt. Requires the draft to be 'approved' (post-approval invariant) and not already executed. APPROVAL_REQUIRED — UI/session-only (not MCP/CLI); Kreto records the filing, it does not auto-transmit.

Execute an approved resolution: record the agency filing (operator-attested) and advance the notice to ACTIONED, sealing a hash-chained audit receipt. Requires the draft to be 'approved' (post-approval invariant) and not already executed. APPROVAL_REQUIRED — UI/session-only (not MCP/CLI); Kreto records the filing, it does not auto-transmit.

Cookie session or Bearer token

Request body ResolutionsExecuteInputrequired

FieldTypeRequiredDescription
resolutionIdstringrequired
filingMethodenum: "mail" | "fax" | "online_portal" | "email" | …required
notestringoptional

Responses

  • 200Successful invocationResolutionsExecuteOutput
    FieldTypeRequiredDescription
    resolutionobjectrequired
    filingobjectrequired
    sealedAtstringrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:signature-consents3

POST/v1/signature-consents.captureConsentPersist an employer officer's signature + scoped consent for state filings. Use when an officer has signed on a canvas and explicitly authorized Kreto to apply the captured signature to per-state PDFs (Middesk-match signature-warehouse model). Idempotent: returns existing un-revoked consent for the same (officer, scope) instead of duplicating.

Persist an employer officer's signature + scoped consent for state filings. Use when an officer has signed on a canvas and explicitly authorized Kreto to apply the captured signature to per-state PDFs (Middesk-match signature-warehouse model). Idempotent: returns existing un-revoked consent for the same (officer, scope) instead of duplicating.

Cookie session or Bearer token

Request body SignatureConsentsCaptureConsentInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
officerMemberIdstringrequired
scopeenum: "sos_and_payroll_tax" | "state_registration_only" | "all_state_filings"required
signatureDataUrlstringrequired
ipstringrequired
userAgentstringrequired

Responses

  • 200Successful invocationSignatureConsentsCaptureConsentOutput
    FieldTypeRequiredDescription
    consentobjectrequired
    isNewCapturebooleanrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/signature-consents.getActiveConsentLook up the latest active (un-revoked) signature consent for an entity + scope. Use when generating a state filing to find the signature image to stamp on the PDF. Returns null if no active consent exists — caller should prompt the officer to sign first.

Look up the latest active (un-revoked) signature consent for an entity + scope. Use when generating a state filing to find the signature image to stamp on the PDF. Returns null if no active consent exists — caller should prompt the officer to sign first.

Cookie session or Bearer token

Request body SignatureConsentsGetActiveConsentInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
scopeenum: "sos_and_payroll_tax" | "state_registration_only" | "all_state_filings"required
officerMemberIdstringoptional

Responses

  • 200Successful invocationSignatureConsentsGetActiveConsentOutput
    FieldTypeRequiredDescription
    consentobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/signature-consents.revokeConsentSoft-revoke a signature consent so it cannot be applied to future filings. Past filings already stamped with the signature retain their stamps (audit immutability). Use when an officer leaves the company or the customer wants to withdraw authorization.

Soft-revoke a signature consent so it cannot be applied to future filings. Past filings already stamped with the signature retain their stamps (audit immutability). Use when an officer leaves the company or the customer wants to withdraw authorization.

Cookie session or Bearer token

Request body SignatureConsentsRevokeConsentInputrequired

FieldTypeRequiredDescription
consentIdstringrequired
revocationReasonstringrequired

Responses

  • 200Successful invocationSignatureConsentsRevokeConsentOutput
    FieldTypeRequiredDescription
    consentobjectrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:state-coverage1

POST/v1/state-coverage.getByStateFetch one US state's compliance coverage for an employer: all registrations (with state account numbers), open notices (not in terminal status), and open recommendations. Use when an agent or the UI drawer needs deep detail on a single state. Example agent question: 'What's our SUI registration status in California?' Returns empty arrays for any signal that has no data — never throws on missing rows.

Fetch one US state's compliance coverage for an employer: all registrations (with state account numbers), open notices (not in terminal status), and open recommendations. Use when an agent or the UI drawer needs deep detail on a single state. Example agent question: 'What's our SUI registration status in California?' Returns empty arrays for any signal that has no data — never throws on missing rows.

Cookie session or Bearer token

Request body StateCoverageGetByStateInputrequired

FieldTypeRequiredDescription
tenantIdstringrequired
employerEntityIdstringrequired
stateCodestringrequired

Responses

  • 200Successful invocationStateCoverageGetByStateOutput
    FieldTypeRequiredDescription
    stateCodestringrequired
    registrationsarray<object>required
    openNoticesarray<object>required
    recommendationsarray<object>required
  • 400Validation error (input schema rejected). risk_level=elevated.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:state-registration26

POST/v1/state-registration.detectNewStateRequirementGiven a StateChangeEvent (an employee moved from one state to another), return the requirements that apply for the destination state. Reads the TS rules registry; does NOT write to DB. AUTONOMOUS — agents may call freely; the trigger pipeline lives in PR-D's worker handler.

Given a StateChangeEvent (an employee moved from one state to another), return the requirements that apply for the destination state. Reads the TS rules registry; does NOT write to DB. AUTONOMOUS — agents may call freely; the trigger pipeline lives in PR-D's worker handler.

Cookie session or Bearer token

Request body StateRegistrationDetectNewStateRequirementInputrequired

FieldTypeRequiredDescription
stateChangeEventobjectrequired

Responses

  • 200Successful invocationStateRegistrationDetectNewStateRequirementOutput
    FieldTypeRequiredDescription
    requirementsarray<object>required
    reasoningstringrequired
    stateSupportedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.listRequiredAccountsList required state-agency accounts for a given state. When employerEntityId is supplied, also returns the subset of requirements already registered (status NOT IN rejected/expired) for that employer. Reads from rules registry. AUTONOMOUS.

List required state-agency accounts for a given state. When employerEntityId is supplied, also returns the subset of requirements already registered (status NOT IN rejected/expired) for that employer. Reads from rules registry. AUTONOMOUS.

Cookie session or Bearer token

Request body StateRegistrationListRequiredAccountsInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
employerEntityIdstringoptional

Responses

  • 200Successful invocationStateRegistrationListRequiredAccountsOutput
    FieldTypeRequiredDescription
    stateCodestringrequired
    stateSupportedbooleanrequired
    accountsarray<object>required
    alreadyRegisteredarray<enum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.prepareRegistrationFormValidate a registration form payload against the per-state Zod schema and persist (upsert) a row in employer_state_registrations with status='prepared'. dryRun=true returns the validated payload without persisting. APPROVAL_REQUIRED — Phase 0 metadata only (HITL gate in Phase 3).

Validate a registration form payload against the per-state Zod schema and persist (upsert) a row in employer_state_registrations with status='prepared'. dryRun=true returns the validated payload without persisting. APPROVAL_REQUIRED — Phase 0 metadata only (HITL gate in Phase 3).

Cookie session or Bearer token

Request body StateRegistrationPrepareRegistrationFormInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
stateCodestringrequired
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required
formPayloadobjectoptional
dryRunbooleanoptional
sourceenum: "manual" | "mosey" | "portal"optional
sourceExternalIdstringoptional

Responses

  • 200Successful invocationStateRegistrationPrepareRegistrationFormOutput
    FieldTypeRequiredDescription
    registrationobjectrequired
    validatedPayloadobjectoptional
    dryRunbooleanrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.submitRegistrationSubmit a prepared registration to the state portal via Browserbase. The most consequential method in Phase E — actually files with a government agency. APPROVAL_REQUIRED (Phase 0 metadata-only; HITL gate in Phase 3). Dispatches via the StatePortalAdapter registry; throws NotImplementedError for states without a wired adapter.

Submit a prepared registration to the state portal via Browserbase. The most consequential method in Phase E — actually files with a government agency. APPROVAL_REQUIRED (Phase 0 metadata-only; HITL gate in Phase 3). Dispatches via the StatePortalAdapter registry; throws NotImplementedError for states without a wired adapter.

Cookie session or Bearer token

Request body StateRegistrationSubmitRegistrationInputrequired

FieldTypeRequiredDescription
registrationIdstringrequired
dryRunbooleanoptional

Responses

  • 200Successful invocationStateRegistrationSubmitRegistrationOutput
    FieldTypeRequiredDescription
    registrationobjectrequired
    dryRunbooleanrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.checkRegistrationStatusReturn the current status of a registration. PR-A reads DB last-known state only (pollSource='db_only'). PR-B/C wires actual portal polling via Browserbase (pollSource='portal_polled'). AUTONOMOUS.

Return the current status of a registration. PR-A reads DB last-known state only (pollSource='db_only'). PR-B/C wires actual portal polling via Browserbase (pollSource='portal_polled'). AUTONOMOUS.

Cookie session or Bearer token

Request body StateRegistrationCheckRegistrationStatusInputrequired

FieldTypeRequiredDescription
registrationIdstringrequired

Responses

  • 200Successful invocationStateRegistrationCheckRegistrationStatusOutput
    FieldTypeRequiredDescription
    registrationobjectrequired
    pollSourceenum: "db_only" | "portal_polled"required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.getRegistrationByEntityLook up the in-flight registration for (tenantId, entityId, stateCode, requirementType). Returns null when no row matches (rejected/expired excluded). AUTONOMOUS.

Look up the in-flight registration for (tenantId, entityId, stateCode, requirementType). Returns null when no row matches (rejected/expired excluded). AUTONOMOUS.

Cookie session or Bearer token

Request body StateRegistrationGetRegistrationByEntityInputrequired

FieldTypeRequiredDescription
entityIdstringrequired
stateCodestringrequired
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required

Responses

  • 200Successful invocationStateRegistrationGetRegistrationByEntityOutput
    FieldTypeRequiredDescription
    registrationobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.listRegistrationsPaginated read of employer_state_registrations rows for the tracking UI. Tenant-scoped via ctx.tenantId; optional entity / status / state / requirement_type / source filters. Returns at most pageSize rows per call (default 25, max 100).

Paginated read of employer_state_registrations rows for the tracking UI. Tenant-scoped via ctx.tenantId; optional entity / status / state / requirement_type / source filters. Returns at most pageSize rows per call (default 25, max 100).

Cookie session or Bearer token

Request body StateRegistrationListRegistrationsInputrequired

FieldTypeRequiredDescription
entityIdstringoptional
statusenum: "pending" | "prepared" | "awaiting_approval" | "preflight_failed" | …optional
stateCodestringoptional
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …optional
sourceenum: "manual" | "mosey" | "portal"optional
pageintegeroptional
pageSizeintegeroptional

Responses

  • 200Successful invocationStateRegistrationListRegistrationsOutput
    FieldTypeRequiredDescription
    registrationsarray<object>required
    pageintegerrequired
    pageSizeintegerrequired
    totalintegerrequired
    hasMorebooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.transitionStatusApply a manual CPA-driven status transition to an existing registration row. Validates the (from, to) pair against the per-state allowedTransitions matrix (with universal default fallback). Writes a structured audit event capturing the transition + reason. NOTIFY classification: agents can call but the action is logged for human review.

Apply a manual CPA-driven status transition to an existing registration row. Validates the (from, to) pair against the per-state allowedTransitions matrix (with universal default fallback). Writes a structured audit event capturing the transition + reason. NOTIFY classification: agents can call but the action is logged for human review.

Cookie session or Bearer token

Request body StateRegistrationTransitionStatusInputrequired

FieldTypeRequiredDescription
registrationIdstringrequired
newStatusenum: "pending" | "prepared" | "awaiting_approval" | "preflight_failed" | …required
reasonstringrequired
stateAccountNumberstringoptional
filedAtstring · date-timeoptional

Responses

  • 200Successful invocationStateRegistrationTransitionStatusOutput
    FieldTypeRequiredDescription
    registrationobjectrequired
    fromStatusenum: "pending" | "prepared" | "awaiting_approval" | "preflight_failed" | …required
    toStatusenum: "pending" | "prepared" | "awaiting_approval" | "preflight_failed" | …required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.updateRegistrationMetadataManually edit the tracker metadata fields (assigned_rate as a decimal fraction, assigned_deposit_frequency, effective_date, next_renewal_at) on an existing registration row. Absent key = unchanged, null = clear. Appends a human-readable notes line and a hash-chained audit_events row carrying per-field old → new + the required reason. `source` is never changed (creation provenance). NOTIFY classification: agents can call but the action is logged for human review.

Manually edit the tracker metadata fields (assigned_rate as a decimal fraction, assigned_deposit_frequency, effective_date, next_renewal_at) on an existing registration row. Absent key = unchanged, null = clear. Appends a human-readable notes line and a hash-chained audit_events row carrying per-field old → new + the required reason. `source` is never changed (creation provenance). NOTIFY classification: agents can call but the action is logged for human review.

Cookie session or Bearer token

Request body StateRegistrationUpdateRegistrationMetadataInputrequired

FieldTypeRequiredDescription
registrationIdstringrequired
assignedRatenumberoptional
assignedDepositFrequencyenum: "weekly" | "biweekly" | "semimonthly" | "monthly" | …optional
effectiveDatestringoptional
nextRenewalAtstringoptional
reasonstringrequired

Responses

  • 200Successful invocationStateRegistrationUpdateRegistrationMetadataOutput
    FieldTypeRequiredDescription
    registrationobjectrequired
    changedFieldsarray<string>required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.recordPortalResultInbound write path for state portal scrapers. Transitions a registration row to approved or rejected based on the portal's outcome, sets state_account_number on success, captures last_error on failure, and emits a recommendation row that the alert cron uses to email/push the CPA team. APPROVAL_REQUIRED per /goal Q8 decision — customer + external-facing writes are NOT MCP-exposable; the audit row carries the elevated risk level so Phase 3 HITL gates these calls. Auth: server-to-server via API key with scope state_registration.write.

Inbound write path for state portal scrapers. Transitions a registration row to approved or rejected based on the portal's outcome, sets state_account_number on success, captures last_error on failure, and emits a recommendation row that the alert cron uses to email/push the CPA team. APPROVAL_REQUIRED per /goal Q8 decision — customer + external-facing writes are NOT MCP-exposable; the audit row carries the elevated risk level so Phase 3 HITL gates these calls. Auth: server-to-server via API key with scope state_registration.write.

Cookie session or Bearer token

Request body StateRegistrationRecordPortalResultInputrequired

FieldTypeRequiredDescription
registrationIdstringrequired
outcomeenum: "approved" | "rejected"required
stateAccountNumberstringoptional
decidedAtstring · date-timeoptional
lastErrorstringoptional

Responses

  • 200Successful invocationStateRegistrationRecordPortalResultOutput
    FieldTypeRequiredDescription
    registrationobjectrequired
    recommendationIdstringrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.generateDe1FilingGenerate a draft California Form DE 1 (covers SUI + Withholding + SDI/PFL on a single CA EDD form) filled with the employer's intake data and stamped with the captured officer signature. Creates a state_filings parent row + 3 employer_state_registrations rows (SUI/Withholding/PFML) all linked via filing_id. NOTIFY risk: this is a draft for human review before CP-CA3 submits to myEDD.

Generate a draft California Form DE 1 (covers SUI + Withholding + SDI/PFL on a single CA EDD form) filled with the employer's intake data and stamped with the captured officer signature. Creates a state_filings parent row + 3 employer_state_registrations rows (SUI/Withholding/PFML) all linked via filing_id. NOTIFY risk: this is a draft for human review before CP-CA3 submits to myEDD.

Cookie session or Bearer token

Request body StateRegistrationGenerateDe1FilingInputrequired

FieldTypeRequiredDescription
employerEntityIdstringrequired
recommendationIdstringoptional
signatureConsentIdstringrequired
intakeobjectrequired

Responses

  • 200Successful invocationStateRegistrationGenerateDe1FilingOutput
    FieldTypeRequiredDescription
    filingIdstringrequired
    filingPdfUrlstringrequired
    employerStateRegistrationIdsarray<string>required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.generateStateFilingState-agnostic filing generator. Resolves the per-state rule for the given stateCode, validates intake against rule.stateIntakeSchema, embeds the captured signature, generates a draft PDF (from rule.pdfTemplatePath if set, else programmatic), and creates a state_filings parent row + one employer_state_registrations row per covered requirement_type. NOTIFY risk: draft only — submission to the state portal is CP-CA3 (APPROVAL_REQUIRED). Replaces the CA-specific generateDe1Filing for all new states.

State-agnostic filing generator. Resolves the per-state rule for the given stateCode, validates intake against rule.stateIntakeSchema, embeds the captured signature, generates a draft PDF (from rule.pdfTemplatePath if set, else programmatic), and creates a state_filings parent row + one employer_state_registrations row per covered requirement_type. NOTIFY risk: draft only — submission to the state portal is CP-CA3 (APPROVAL_REQUIRED). Replaces the CA-specific generateDe1Filing for all new states.

Cookie session or Bearer token

Request body StateRegistrationGenerateStateFilingInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
employerEntityIdstringrequired
recommendationIdstringoptional
signatureConsentIdstringrequired
intakeobjectrequired

Responses

  • 200Successful invocationStateRegistrationGenerateStateFilingOutput
    FieldTypeRequiredDescription
    filingIdstringrequired
    filingPdfUrlstringrequired
    employerStateRegistrationIdsarray<string>required
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.saveIntakeDraftUpsert the in-progress State Registration Wizard intake for a given (employer, state) so wizard state survives a refresh / crash / cross-device resume. Draft-only (NOTIFY): captures answers + resume metadata, generates no filing and submits nothing. One row per (tenant, employer, state) via the table's UNIQUE constraint — re-saving updates, never duplicates.

Upsert the in-progress State Registration Wizard intake for a given (employer, state) so wizard state survives a refresh / crash / cross-device resume. Draft-only (NOTIFY): captures answers + resume metadata, generates no filing and submits nothing. One row per (tenant, employer, state) via the table's UNIQUE constraint — re-saving updates, never duplicates.

Cookie session or Bearer token

Request body StateRegistrationSaveIntakeDraftInputrequired

FieldTypeRequiredDescription
employerEntityIdstringrequired
recommendationIdstringoptional
stateCodestringrequired
reasonForRegisteringstringoptional
qualifiersobjectoptional
stateSpecificDataobjectrequired

Responses

  • 200Successful invocationStateRegistrationSaveIntakeDraftOutput
    FieldTypeRequiredDescription
    draftIdstringrequired
    updatedAtstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.provisionPortalAccountAllocate a Kreto-owned portal-account credential for a (tenant, entity, state, agency) tuple. Generates a unique alias e-mail of the form <slug>.portal-<state>-<agency>@kreto.ai, generates a strong base64url password, and writes the credential to vault under agency_id='portal_<stateCode>'. Idempotent: re-call with the same tuple returns the existing credential. APPROVAL_REQUIRED (Phase 0 metadata-only; KRT-1554 step-up gates later).

Allocate a Kreto-owned portal-account credential for a (tenant, entity, state, agency) tuple. Generates a unique alias e-mail of the form <slug>.portal-<state>-<agency>@kreto.ai, generates a strong base64url password, and writes the credential to vault under agency_id='portal_<stateCode>'. Idempotent: re-call with the same tuple returns the existing credential. APPROVAL_REQUIRED (Phase 0 metadata-only; KRT-1554 step-up gates later).

Cookie session or Bearer token

Request body StateRegistrationProvisionPortalAccountInputrequired

FieldTypeRequiredDescription
entityIdstring · uuidrequired
stateCodestringrequired
agencyCodestringrequired

Responses

  • 200Successful invocationStateRegistrationProvisionPortalAccountOutput
    FieldTypeRequiredDescription
    credentialIdstring · uuidrequired
    aliasEmailstring · emailrequired
    agencyIdstringrequired
    statusstringrequired
    passwordstringrequired
    newlyProvisionedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.listCatalogRulesBrowse the state-registration catalog (state_filing_rules, global config — NO tenant filter). Optional filters: stateCode, requirementType, verificationStatus, needsResearch, monopolistic, jurisdictionType. Returns the matching rows plus HONEST per-status counts ({unverified, human_reviewed, verified}) for the filtered set — never a 'done/complete' claim (AC-23). AUTONOMOUS, read-only.

Browse the state-registration catalog (state_filing_rules, global config — NO tenant filter). Optional filters: stateCode, requirementType, verificationStatus, needsResearch, monopolistic, jurisdictionType. Returns the matching rows plus HONEST per-status counts ({unverified, human_reviewed, verified}) for the filtered set — never a 'done/complete' claim (AC-23). AUTONOMOUS, read-only.

Cookie session or Bearer token

Request body StateRegistrationListCatalogRulesInputrequired

FieldTypeRequiredDescription
stateCodestringoptional
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …optional
verificationStatusenum: "unverified" | "human_reviewed" | "verified"optional
needsResearchbooleanoptional
monopolisticbooleanoptional
jurisdictionTypeenum: "federal" | "state" | "locality"optional

Responses

  • 200Successful invocationStateRegistrationListCatalogRulesOutput
    FieldTypeRequiredDescription
    rowsarray<object>required
    countsobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.promoteCatalogRuleHuman gate: promote a catalog cell along the verification ladder (unverified → human_reviewed → verified). APPROVAL_REQUIRED, UI-only — excluded from MCP/CLI, and the handler REJECTS any non-human principal before any write (AC-20). Verifying requires provenance (source_url + retrieved_at, AC-18). Stamps reviewed_by / last_reviewed_at, and on verify also verified_at / verified_by / needs_research=false.

Human gate: promote a catalog cell along the verification ladder (unverified → human_reviewed → verified). APPROVAL_REQUIRED, UI-only — excluded from MCP/CLI, and the handler REJECTS any non-human principal before any write (AC-20). Verifying requires provenance (source_url + retrieved_at, AC-18). Stamps reviewed_by / last_reviewed_at, and on verify also verified_at / verified_by / needs_research=false.

Cookie session or Bearer token

Request body StateRegistrationPromoteCatalogRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required
toStatusenum: "human_reviewed" | "verified"required
reasonstringoptional

Responses

  • 200Successful invocationStateRegistrationPromoteCatalogRuleOutput
    FieldTypeRequiredDescription
    stateCodestringrequired
    requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required
    fromStatusenum: "unverified" | "human_reviewed" | "verified"required
    toStatusenum: "unverified" | "human_reviewed" | "verified"required
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.getCatalogRuleRead one catalog cell (state_filing_rules, global config — NO tenant filter): the rule row plus its typed ordered steps (state_filing_rule_steps), its prerequisite edges (state_filing_rule_prerequisites), and the resolved jurisdiction (via jurisdiction_code, else null). Powers the Cell Detail screen (jobs a+b, AC-5). AUTONOMOUS, read-only.

Read one catalog cell (state_filing_rules, global config — NO tenant filter): the rule row plus its typed ordered steps (state_filing_rule_steps), its prerequisite edges (state_filing_rule_prerequisites), and the resolved jurisdiction (via jurisdiction_code, else null). Powers the Cell Detail screen (jobs a+b, AC-5). AUTONOMOUS, read-only.

Cookie session or Bearer token

Request body StateRegistrationGetCatalogRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required

Responses

  • 200Successful invocationStateRegistrationGetCatalogRuleOutput
    FieldTypeRequiredDescription
    ruleobjectrequired
    stepsarray<object>required
    prerequisitesarray<object>required
    jurisdictionobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.listFilingRuleStepsList the typed, ordered registration steps for a (state, requirement) cell (state_filing_rule_steps, global config — NO tenant filter), ordered by step_order. The canonical step sequence is typed rows, never a prose blob (AC-7). AUTONOMOUS, read-only.

List the typed, ordered registration steps for a (state, requirement) cell (state_filing_rule_steps, global config — NO tenant filter), ordered by step_order. The canonical step sequence is typed rows, never a prose blob (AC-7). AUTONOMOUS, read-only.

Cookie session or Bearer token

Request body StateRegistrationListFilingRuleStepsInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required

Responses

  • 200Successful invocationStateRegistrationListFilingRuleStepsOutput
    FieldTypeRequiredDescription
    stepsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.listFilingRulePrerequisitesList the prerequisite dependency edges for a (state, requirement) cell (state_filing_rule_prerequisites, global config — NO tenant filter). Edges model account-type dependencies and SOS foreign qualification (prerequisite_kind='sos_foreign_qual', an edge — NOT a 6th requirement_type), queryable as a dependency chain (AC-10/13). AUTONOMOUS, read-only.

List the prerequisite dependency edges for a (state, requirement) cell (state_filing_rule_prerequisites, global config — NO tenant filter). Edges model account-type dependencies and SOS foreign qualification (prerequisite_kind='sos_foreign_qual', an edge — NOT a 6th requirement_type), queryable as a dependency chain (AC-10/13). AUTONOMOUS, read-only.

Cookie session or Bearer token

Request body StateRegistrationListFilingRulePrerequisitesInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required

Responses

  • 200Successful invocationStateRegistrationListFilingRulePrerequisitesOutput
    FieldTypeRequiredDescription
    prerequisitesarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.listJurisdictionsList jurisdictions (federal | state | locality) from the jurisdictions table (global config — NO tenant filter). Optional filters: jurisdictionType, parentCode. Locality-ready model — v1 seeds state-grain only, but a locality is just a future row (AC-15/16). AUTONOMOUS, read-only.

List jurisdictions (federal | state | locality) from the jurisdictions table (global config — NO tenant filter). Optional filters: jurisdictionType, parentCode. Locality-ready model — v1 seeds state-grain only, but a locality is just a future row (AC-15/16). AUTONOMOUS, read-only.

Cookie session or Bearer token

Request body StateRegistrationListJurisdictionsInputrequired

FieldTypeRequiredDescription
jurisdictionTypeenum: "federal" | "state" | "locality"optional
parentCodestringoptional

Responses

  • 200Successful invocationStateRegistrationListJurisdictionsOutput
    FieldTypeRequiredDescription
    jurisdictionsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.proposeFilingRuleResearch one (state, requirement) catalog cell via the Claude + web_search agent and upsert an UNVERIFIED proposal onto the cell BY PK (state_filing_rules, global config — NO tenant filter). The write ALWAYS leaves verification_status='unverified' and NEVER sets verified/human_reviewed (AC-19/20 — agents may never verify); writes provenance (source_url + retrieved_at, AC-18); idempotent-by-PK (AC-22). MUST NOT downgrade a human-promoted cell: on a human_reviewed OR verified cell it leaves the authoritative fields untouched and returns the existing row + the fresh proposal so a human can compare (no-downgrade). PII-free. NOTIFY: agents may call; a human reviews the proposal before promotion.

Research one (state, requirement) catalog cell via the Claude + web_search agent and upsert an UNVERIFIED proposal onto the cell BY PK (state_filing_rules, global config — NO tenant filter). The write ALWAYS leaves verification_status='unverified' and NEVER sets verified/human_reviewed (AC-19/20 — agents may never verify); writes provenance (source_url + retrieved_at, AC-18); idempotent-by-PK (AC-22). MUST NOT downgrade a human-promoted cell: on a human_reviewed OR verified cell it leaves the authoritative fields untouched and returns the existing row + the fresh proposal so a human can compare (no-downgrade). PII-free. NOTIFY: agents may call; a human reviews the proposal before promotion.

Cookie session or Bearer token

Request body StateRegistrationProposeFilingRuleInputrequired

FieldTypeRequiredDescription
stateCodestringrequired
requirementTypeenum: "sui_registration" | "withholding_registration" | "workers_comp" | "pfml" | …required

Responses

  • 200Successful invocationStateRegistrationProposeFilingRuleOutput
    FieldTypeRequiredDescription
    rowobjectrequired
    proposalobjectrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.approveRegistrationFilingRecord a CPA's approval to file a prepared registration and, for fee-bearing filings, authorize payment up to a bound amount (AC-15). The consequential human gate — APPROVAL_REQUIRED, UI-only, never exposed to MCP/CLI. Moves the registration to 'awaiting_approval' and enqueues pre-flight. Handler: Phase B.

Record a CPA's approval to file a prepared registration and, for fee-bearing filings, authorize payment up to a bound amount (AC-15). The consequential human gate — APPROVAL_REQUIRED, UI-only, never exposed to MCP/CLI. Moves the registration to 'awaiting_approval' and enqueues pre-flight. Handler: Phase B.

Cookie session or Bearer token

Request body StateRegistrationApproveRegistrationFilingInputrequired

FieldTypeRequiredDescription
registrationIdstring · uuidrequired
authorizedAmountCentsintegerrequired
billingDisclosurestringoptional

Responses

  • 200Successful invocationStateRegistrationApproveRegistrationFilingOutput
    FieldTypeRequiredDescription
    registrationIdstring · uuidrequired
    statusstringrequired
    approvalIdstring · uuidrequired
    preflightobjectrequired
    enqueuedbooleanrequired
    feeobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.runFilingPreflightRun the pre-flight filing validator (KRT-1544 rules: registration status, duplicate-account, idempotency, payload completeness) before any browser session launches (AC-2). Read-only, AUTONOMOUS. A failure blocks the filing and names the failing rule. Handler: Phase B.

Run the pre-flight filing validator (KRT-1544 rules: registration status, duplicate-account, idempotency, payload completeness) before any browser session launches (AC-2). Read-only, AUTONOMOUS. A failure blocks the filing and names the failing rule. Handler: Phase B.

Cookie session or Bearer token

Request body StateRegistrationRunFilingPreflightInputrequired

FieldTypeRequiredDescription
registrationIdstring · uuidrequired

Responses

  • 200Successful invocationStateRegistrationRunFilingPreflightOutput
    FieldTypeRequiredDescription
    okbooleanrequired
    failuresarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.verifyFilingOutcomeVerify an executor's claimed filing outcome against captured evidence (confirmation number + screenshot, optional re-check) before the registration is allowed to flip to 'submitted' (AC-5/AC-6). An unverifiable claim yields 'rejected' → needs_human, never 'submitted'. NOTIFY. Handler: Phase E.

Verify an executor's claimed filing outcome against captured evidence (confirmation number + screenshot, optional re-check) before the registration is allowed to flip to 'submitted' (AC-5/AC-6). An unverifiable claim yields 'rejected' → needs_human, never 'submitted'. NOTIFY. Handler: Phase E.

Cookie session or Bearer token

Request body StateRegistrationVerifyFilingOutcomeInputrequired

FieldTypeRequiredDescription
attemptIdstring · uuidrequired

Responses

  • 200Successful invocationStateRegistrationVerifyFilingOutcomeOutput
    FieldTypeRequiredDescription
    verdictenum: "confirmed" | "rejected"required
    confirmationNumberstringrequired
    reasonstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.storeIssuedCredentialStore a portal credential created during registration into the per-tenant credential vault (AC-11). APPROVAL_REQUIRED — creating a credential is a consequential vault write, so it stays UI-only and is NOT exposed to MCP/CLI (verifier-gate finding: a NOTIFY op would be auto-exposed, contra the approved roster). The secret is captured by the vault layer, never passed in model context. Handler: Phase F (needs a real portal-issued credential).

Store a portal credential created during registration into the per-tenant credential vault (AC-11). APPROVAL_REQUIRED — creating a credential is a consequential vault write, so it stays UI-only and is NOT exposed to MCP/CLI (verifier-gate finding: a NOTIFY op would be auto-exposed, contra the approved roster). The secret is captured by the vault layer, never passed in model context. Handler: Phase F (needs a real portal-issued credential).

Cookie session or Bearer token

Request body StateRegistrationStoreIssuedCredentialInputrequired

FieldTypeRequiredDescription
registrationIdstring · uuidrequired
portalUsernamestringrequired
agencyIdstringrequired

Responses

  • 200Successful invocationStateRegistrationStoreIssuedCredentialOutput
    FieldTypeRequiredDescription
    credentialIdstring · uuidrequired
    storedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/state-registration.recordManualFilingOutcomeRecord the outcome of a Kreto operator completing a filing from the ops-fallback queue (AC-10). Writes the SAME evidence shape as the agentic path (actor=user, via='manual'). APPROVAL_REQUIRED — a human is doing the consequential act; UI-only, never MCP/CLI. Handler: Phase E.

Record the outcome of a Kreto operator completing a filing from the ops-fallback queue (AC-10). Writes the SAME evidence shape as the agentic path (actor=user, via='manual'). APPROVAL_REQUIRED — a human is doing the consequential act; UI-only, never MCP/CLI. Handler: Phase E.

Cookie session or Bearer token

Request body StateRegistrationRecordManualFilingOutcomeInputrequired

FieldTypeRequiredDescription
registrationIdstring · uuidrequired
attemptIdstring · uuidoptional
outcomeenum: "submitted" | "rejected" | "needs_more_info"required
confirmationNumberstringoptional
feeAmountCentsintegeroptional
notesstringoptional

Responses

  • 200Successful invocationStateRegistrationRecordManualFilingOutcomeOutput
    FieldTypeRequiredDescription
    registrationIdstring · uuidrequired
    statusstringrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:team-invitations5

POST/v1/team-invitations.createInvitationCreate a team-invitation row, generate single-use accept token, and send the invite email. Returns plaintext accept_url ONCE.

Create a team-invitation row, generate single-use accept token, and send the invite email. Returns plaintext accept_url ONCE.

Cookie session or Bearer token

Request body TeamInvitationsCreateInvitationInputrequired

FieldTypeRequiredDescription
entity_idstring · uuidoptional
emailstring · emailrequired
roleenum: "controller" | "viewer"required

Responses

  • 200Successful invocationTeamInvitationsCreateInvitationOutput
    FieldTypeRequiredDescription
    invitationobjectrequired
    accept_urlstring · urirequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/team-invitations.listInvitationsList team invitations for an entity (defaults to caller's owned entity). Never returns plaintext tokens or token hashes.

List team invitations for an entity (defaults to caller's owned entity). Never returns plaintext tokens or token hashes.

Cookie session or Bearer token

Request body TeamInvitationsListInvitationsInputrequired

FieldTypeRequiredDescription
entity_idstring · uuidoptional
statusenum: "pending" | "accepted" | "revoked" | "expired"optional

Responses

  • 200Successful invocationTeamInvitationsListInvitationsOutput
    FieldTypeRequiredDescription
    invitationsarray<object>required
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/team-invitations.revokeInvitationRevoke a pending invitation. Idempotent for already-revoked/accepted rows (returns current status). Only entity owners may revoke.

Revoke a pending invitation. Idempotent for already-revoked/accepted rows (returns current status). Only entity owners may revoke.

Cookie session or Bearer token

Request body TeamInvitationsRevokeInvitationInputrequired

FieldTypeRequiredDescription
invitation_idstring · uuidrequired

Responses

  • 200Successful invocationTeamInvitationsRevokeInvitationOutput
    FieldTypeRequiredDescription
    idstring · uuidrequired
    statusstringrequired
  • 400Validation error (input schema rejected). risk_level=notify.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/team-invitations.acceptInvitationAccept a team invitation. Verifies token, expiry, self-acceptance, and email-mismatch guards. Inserts entity_members row on success. The caller MUST be signed in as the invited email.

Accept a team invitation. Verifies token, expiry, self-acceptance, and email-mismatch guards. Inserts entity_members row on success. The caller MUST be signed in as the invited email.

Cookie session or Bearer token

Request body TeamInvitationsAcceptInvitationInputrequired

FieldTypeRequiredDescription
tokenstringrequired

Responses

  • 200Successful invocationTeamInvitationsAcceptInvitationOutput
    FieldTypeRequiredDescription
    invitation_idstring · uuidrequired
    entity_idstring · uuidrequired
    rolestringrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/team-invitations.getInvitationByTokenPublic lookup by plaintext token (hashes on read; never returns hash or plaintext). Used by /accept-team-invite/[token] for render.

Public lookup by plaintext token (hashes on read; never returns hash or plaintext). Used by /accept-team-invite/[token] for render.

Cookie session or Bearer token

Request body TeamInvitationsGetInvitationByTokenInputrequired

FieldTypeRequiredDescription
tokenstringrequired

Responses

  • 200Successful invocationTeamInvitationsGetInvitationByTokenOutput
    FieldTypeRequiredDescription
    invitationobjectrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

l2:vault4

POST/v1/vault.getPolicyRead the account's vault policy (who may reveal plaintext, per-portal MFA overrides, notification routing), the immutable hard floors, and the break-glass lock state. Use to check whether vault operations are currently halted for the tenant.

Read the account's vault policy (who may reveal plaintext, per-portal MFA overrides, notification routing), the immutable hard floors, and the break-glass lock state. Use to check whether vault operations are currently halted for the tenant.

Cookie session or Bearer token

Request body VaultGetPolicyInputrequired

application/json

Responses

  • 200Successful invocationVaultGetPolicyOutput
    FieldTypeRequiredDescription
    policyobjectrequired
    lockobjectrequired
    vaultV1Enforcementbooleanrequired
  • 400Validation error (input schema rejected). risk_level=autonomous.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/vault.setPolicyUpdate the account's configurable vault policy: reveal visibility, per-portal MFA strategy overrides, notification routing. The hard floors (money approval, freeze-on-first-failure) are not accepted by this method by construction.

Update the account's configurable vault policy: reveal visibility, per-portal MFA strategy overrides, notification routing. The hard floors (money approval, freeze-on-first-failure) are not accepted by this method by construction.

Cookie session or Bearer token

Request body VaultSetPolicyInputrequired

FieldTypeRequiredDescription
revealVisibilityenum: "members" | "admins_only"optional
mfaMatrixOverrideobjectoptional
notificationRoutingobjectoptional

Responses

  • 200Successful invocationVaultSetPolicyOutput
    FieldTypeRequiredDescription
    policyobjectrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/vault.breakGlassEmergency brake: immediately halt all credential decryption, use, rotation, and reveal for the tenant WITHOUT destroying key material. Reversible — restoring requires dual confirmation. Use on suspected compromise.

Emergency brake: immediately halt all credential decryption, use, rotation, and reveal for the tenant WITHOUT destroying key material. Reversible — restoring requires dual confirmation. Use on suspected compromise.

Cookie session or Bearer token

Request body VaultBreakGlassInputrequired

FieldTypeRequiredDescription
reasonstringoptional

Responses

  • 200Successful invocationVaultBreakGlassOutput
    FieldTypeRequiredDescription
    lockedenum: truerequired
    lockedAtstringrequired
    alreadyLockedbooleanrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope
POST/v1/vault.restoreSecond half of break-glass: lift the tenant-wide vault halt. Requires two confirmations from DIFFERENT humans (interim out-of-band dual-confirm until KRT-1554 step-up auth ships). The first call marks the restore pending; a second call by a different user completes it.

Second half of break-glass: lift the tenant-wide vault halt. Requires two confirmations from DIFFERENT humans (interim out-of-band dual-confirm until KRT-1554 step-up auth ships). The first call marks the restore pending; a second call by a different user completes it.

Cookie session or Bearer token

Request body VaultRestoreInputrequired

application/json

Responses

  • 200Successful invocationVaultRestoreOutput
    FieldTypeRequiredDescription
    lockedbooleanrequired
    restorePendingbooleanrequired
    restoredbooleanrequired
    secondConfirmerRequiredbooleanrequired
  • 400Validation error (input schema rejected). risk_level=approval_required.L2ErrorEnvelope
  • 401Unauthorized (missing or invalid bearer token)L2ErrorEnvelope
  • 403Forbidden (missing scope or RLS denied). APPROVAL_REQUIRED ops additionally need a human approval token; see KRT-1554 step-up flow.L2ErrorEnvelope
  • 500Internal server errorL2ErrorEnvelope

My Compliance6

GET/api/my-compliance/profileRead the caller's business profile (employer-tier)

Returns the entity row scoped to the authenticated user via entity_members. Works for both cpa_member (returns first entity) and client_user (returns their single entity). Bearer auth requires employers.read scope.

Cookie session or Bearer token

Responses

  • 200Business profileMyComplianceProfile
    FieldTypeRequiredDescription
    entity_idstring · uuidrequired
    legal_namestringrequired
    ein_last4stringrequired
    primary_statestringrequired
    compliance_scoreintegerrequired
    created_atstring · date-timerequired
  • 401UnauthorizedMyComplianceError
  • 404No business profile linked to this userMyComplianceError
PATCH/api/my-compliance/profileUpdate business profile fields

Partial update of the caller's entity. Sends only the fields that changed. EIN is stored as last-4 only (PII rule). Bearer auth requires employers.write scope (CPA-tier only today; employer-tier write coming with granular scope expansion).

Cookie session or Bearer token

Request body MyComplianceProfilePatchrequired

FieldTypeRequiredDescription
legal_namestringoptional
ein_last4stringoptional
primary_statestringoptional

Responses

  • 200Profile updatedMyComplianceProfilePatchResponse
    FieldTypeRequiredDescription
    okbooleanrequired
    entityobjectrequired
  • 400Validation errorMyComplianceError
  • 404No business profile linked to this userMyComplianceError
GET/api/my-compliance/auditAudit log for the caller's entity

Read-only timeline of audit_events filtered to the entity the caller belongs to. Composite cursor pagination — pass next_cursor back as `before` to fetch the next page. Bearer auth requires audit.read scope.

Cookie session or Bearer token

Parameters

NameInTypeRequiredDescription
limitqueryintegeroptional
beforequerystringoptionalComposite cursor in the form '<iso8601>|<uuid>'. Legacy ISO-only cursors also accepted for backwards compatibility.

Responses

  • 200Audit log pageMyComplianceAuditList
    FieldTypeRequiredDescription
    eventsarray<MyComplianceAuditEvent>required
    next_cursorstringrequired
    entity_idstring · uuidoptional
  • 400Invalid cursorMyComplianceError
GET/api/my-compliance/api-tokensList the caller's non-revoked Bearer tokens

Returns API keys created by the authenticated user, filtered to their tenant. Plaintext is NEVER included — only key_prefix + metadata. Bearer auth NOT supported on this route (cookie-session only) to prevent a token from listing or mass-revoking peers.

Cookie session or Bearer token

Responses

  • 200Token list (non-revoked only)MyComplianceApiTokenList
    FieldTypeRequiredDescription
    tokensarray<MyComplianceApiToken>required
  • 401UnauthorizedMyComplianceError
POST/api/my-compliance/api-tokensMint a new employer-scoped Bearer token

Creates a new api_keys row via the same hash-on-write pipeline as /api/api-keys, but with the scopes constrained to the employer allow-list (notices.read, employers.read, payroll.read, audit.read). Plaintext is returned ONCE in `plaintext` — store it now; we keep only the bcrypt hash. RLS migration 20260615000000 enforces the scope subset at the DB layer too (defense in depth).

Cookie session or Bearer token

Request body MyComplianceApiTokenCreate

FieldTypeRequiredDescription
namestringoptional
scopesarray<string>optional

Responses

  • 200Token created. Plaintext returned ONCE.MyComplianceApiTokenCreated
    FieldTypeRequiredDescription
    okbooleanrequired
    plaintextstringrequired
    tokenobjectrequired
  • 500Failed to create tokenMyComplianceError
DELETE/api/my-compliance/api-tokensRevoke one of your own Bearer tokens

Soft-delete via revoked_at timestamp; audit traces survive. Scoped to the caller's own tokens by created_by_user_id — you cannot revoke peers' tokens even within the same tenant.

Cookie session or Bearer token

Parameters

NameInTypeRequiredDescription
idquerystring · uuidrequiredUUID of the api_keys row to revoke

Responses

  • 200Token revoked (idempotent — re-revoking is a no-op 200)MyComplianceOkResponse
    FieldTypeRequiredDescription
    okbooleanrequired
  • 400Missing token idMyComplianceError

Notices45

GET/api/notices/{id}/auditGet notice audit trail

Returns the immutable audit chain for a single notice, including every event's hash links and a `chain_valid` boolean attesting that the SHA-256 chain verifies cryptographically.

Bearer scopesaudit.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Audit chain + integrity attestationNoticeAuditResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    notice_idstring · uuidrequired
    entriesarray<AuditEntry>required
    chain_validbooleanrequired
    chain_break_atintegerrequired
    totalintegerrequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
GET/api/notices/{id}/document-urlGet signed URL for notice document

Returns a 1-hour signed URL for the original notice document. Tenant-scoped: only notices in the caller's tenant resolve to a URL.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Signed URL (or null if no document is attached)NoticeDocumentUrlResponse
    FieldTypeRequiredDescription
    urlstringrequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 429Rate limit exceededNoticeRateLimitResponse
GET/api/notices/{id}/draft-dataGet latest notice draft

Returns the latest resolution draft for a notice — content, summary, structured action_items, response_type, and status. Falls back to the legacy `response_drafts` table when no `resolution_drafts` row exists.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Latest draft (or null fields if none exists)NoticeDraftDataResponse
    FieldTypeRequiredDescription
    contentstringrequired
    summarystringrequired
    action_itemsarray<string>required
    response_typestringrequired
    statusstringoptional
    created_atstring · date-timeoptional
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
PATCH/api/notices/{id}/entityReassign notice to another entity

Re-attribute a notice to a different entity. Both notice and target entity must be in the caller's tenant; the entity is verified before the update so cross-tenant re-attribution is impossible.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body NoticeEntityPatchBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired

Responses

  • 200UpdatedNoticeEntityPatchResponse
    FieldTypeRequiredDescription
    successenum: truerequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice or target entity not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
POST/api/notices/{id}/confirm-stateConfirm notice state

Confirm or override the state on a notice. Used when AI extraction misses or misclassifies the state and a human corrects it. The override is logged to audit_events for compliance traceability.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body NoticeConfirmStateBodyrequired

FieldTypeRequiredDescription
confirmedStatestringrequired

Responses

  • 200ConfirmedNoticeSuccessResponse
    FieldTypeRequiredDescription
    successenum: truerequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
GET/api/notices/{id}/documentDownload notice document

Streams the original notice document (PDF/PNG/JPEG/TIFF) inline. Browser sees a Kreto URL, not a Supabase storage URL.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Binary document content (PDF/PNG/JPEG/TIFF) streamed inline. OpenAPI generator requires schemas for each content type — using z.string() (binary) as a generic placeholder; clients should consume the response stream directly per Content-Type header.string
  • 400Validation errorNoticeValidationErrorResponse
  • 401Unauthorized
  • 403Forbidden — missing required scope
  • 404Document not found / notice not in caller's tenant
  • 429Rate limit exceeded
GET/api/notices/{id}/supplementalGet notice supplemental data

Returns the active work_item, document_requests, and messages associated with a notice. All queries tenant-scoped.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Supplemental bundleNoticeSupplementalResponse
    FieldTypeRequiredDescription
    work_itemNoticeWorkItemrequired
    document_requestsarray<NoticeDocumentRequest>required
    messagesarray<NoticeMessage>required
    sender_namesobjectrequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
GET/api/notices/{id}/statusGet notice pipeline status

Returns pipeline status + classification result for a notice (notice_type_classified, classification_confidence, protest_deadline, financial_impact, protest_recommended, assigned_rate, pipeline_status).

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Pipeline statusNoticeStatusResponse
    FieldTypeRequiredDescription
    idstring · uuidrequired
    notice_typestringrequired
    statestringrequired
    pipeline_statusstringrequired
    notice_type_classifiedstringrequired
    classification_confidencenumberrequired
    protest_deadlinestring · daterequired
    financial_impactnumberrequired
    protest_recommendedbooleanrequired
    assigned_ratenumberrequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
POST/api/notices/{id}/statusUpdate notice triage fields

Update notice triage fields (assigned_rate, is_new_employer). is_new_employer is stored inside extracted_json (no dedicated column).

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body NoticeStatusPostBodyrequired

FieldTypeRequiredDescription
assigned_ratenumberoptional
is_new_employerbooleanoptional

Responses

  • 200UpdatedNoticeStatusPostResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    updatedobjectrequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
POST/api/notices/{id}/entity-match-resolveResolve fuzzy entity match

Resolve a fuzzy entity-match candidate set for a notice. `action=confirmed` assigns the notice to an existing entity (verified to belong to caller's tenant). `action=create_new` creates a new entity in the notice's tenant and assigns the notice to it.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body NoticeEntityMatchResolveBodyrequired

application/json

Responses

  • 200ResolvedNoticeEntityMatchResolveResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    entity_idstring · uuidrequired
    actionenum: "confirmed" | "create_new"required
    entity_namestringoptional
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice or resolved entity not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
GET/api/notices/{id}/similarFind similar resolved notices

Find anonymized resolution patterns + similar resolved notices for a given notice. The source notice lookup is tenant-scoped; the pattern + outcomes lookups are intentionally cross-tenant (anonymized aggregate, no PII).

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Resolution pattern + anonymized similar noticesNoticeSimilarResponse
    FieldTypeRequiredDescription
    patternResolutionPatternrequired
    similar_countintegerrequired
    similar_noticesarray<SimilarNotice>required
    recommendationstringrequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
GET/api/notices/{id}/outcomeGet notice outcome

Returns the most recent recorded outcome for a notice (or null).

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Outcome (or null)NoticeOutcomeGetResponse
    FieldTypeRequiredDescription
    outcomeNoticeOutcomerequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 429Rate limit exceededNoticeRateLimitResponse
POST/api/notices/{id}/outcomeRecord notice outcome

Record the resolution outcome when a notice is resolved. Inserts a notice_outcomes row, optionally captures classification feedback, closes the notice, and aggregates into the cross-tenant resolution_patterns inventory for similar-notice recommendations.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body NoticeOutcomePostBodyrequired

FieldTypeRequiredDescription
resolution_typestringrequired
resolution_notesstringoptional
resolution_methodstringoptional
corrected_typestringoptional
original_amountnumberoptional
final_amountnumberoptional
documents_usedarray<DocumentRef>optional
documents_missingarray<DocumentRef>optional
deadline_was_correctbooleanoptional
actual_deadlinestring · dateoptional
agency_response_datestring · dateoptional

Responses

  • 200Outcome recordedNoticeOutcomePostResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    outcome_idstring · uuidrequired
    savingsnumberrequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
POST/api/notices/{id}/interpretInterpret notice PDF (Claude)

Synchronously interpret the notice PDF using Claude. Downloads the raw PDF, runs PII-redacted extraction + classification, validates against quality gates (returns 422 if they fail), creates artifact + lineage records, and updates the notice with the result.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200InterpretedNoticeInterpretResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    noticeIdstring · uuidrequired
    artifactIdstring · uuidrequired
    interpretationobjectrequired
    qualityCheckobjectrequired
    metadataobjectrequired
  • 400Validation error / no storage path / PDF interpretation failedNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 422Quality gates failed (interpretation incomplete)NoticeInterpretQualityFailResponse
  • 429Rate limit exceededNoticeRateLimitResponse
POST/api/notices/classifyClassify notice text/file

Classify a notice from raw text (JSON body) or file upload (multipart/form-data). Runs PII redaction first, then LLM classification with a 15-second timeout. Cookie-session callers go through the Stripe subscription gate; Bearer-key callers do not.

Bearer scopesnotices.write

Request body NoticeClassifyJsonBodyrequired

FieldTypeRequiredDescription
textstringoptional
entity_idstring · uuidoptional

Responses

  • 200Classification resultNoticeClassifyResponse
    FieldTypeRequiredDescription
    notice_typestringrequired
    jurisdictionstringoptional
    deadlinestring · dateoptional
    severitystringoptional
    confidencenumberrequired
    categorystringoptional
    subcategorystringoptional
    extracted_factsobjectrequired
    enrichmentobjectrequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)NoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 429Rate limit exceededNoticeRateLimitResponse
  • 500Server error / classification timeoutNoticeUnauthorizedResponse
GET/api/notices/{id}/draftGet notice draft

Returns the latest resolution draft for a notice (resolution_drafts preferred, falls back to response_drafts, then to inline draft on notices.extracted_json). Tenant-scoped.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Latest draft + evidence packageNoticeDraftGetResponse
    FieldTypeRequiredDescription
    draftNoticeDraftRecordrequired
    evidence_packageNoticeEvidencePackagerequired
    notice_deadlinestring · daterequired
    sourceenum: "resolution_drafts" | "response_drafts" | "extracted_json"required
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice or draft not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
POST/api/notices/{id}/draftGenerate notice draft

Generate a new draft via the pipeline draft generator. Cookie-session callers go through the Stripe subscription gate; Bearer-key callers do not.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Draft generatedNoticeDraftPostResponse
    FieldTypeRequiredDescription
    draftNoticeDraftRecordrequired
    evidence_packageNoticeEvidencePackagerequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)NoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
  • 500Server error / draft generation failedNoticeUnauthorizedResponse
PATCH/api/notices/{id}/draftUpdate notice draft

Update the most recent draft's content. Tenant-scoped both on read and update — root-cause fix vs pre-Phase-4 which only filtered by id.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body NoticeDraftPatchBodyrequired

FieldTypeRequiredDescription
contentstringrequired

Responses

  • 200Draft updatedNoticeDraftPatchResponse
    FieldTypeRequiredDescription
    draftNoticeDraftRecordrequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404No draft found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
GET/api/notices/{id}/resolution-packageGet notice resolution package

Returns the most recent resolution package for a notice (or a stub when none has been generated). Tenant-scoped.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Existing package or 'not_generated' stubResolutionPackageGetResponse
    FieldTypeRequiredDescription
    package_idstring · uuidrequired
    statusstringrequired
    submission_methodstringoptional
    submitted_atstring · date-timeoptional
    metadataobjectoptional
    documentsarray<ResolutionPackageDocument>required
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 429Rate limit exceededNoticeRateLimitResponse
POST/api/notices/{id}/resolution-packageGenerate notice resolution package

Generate a resolution package after confirming all required documents are present. Returns 400 if any are missing. If `protest_recommended` on the notice, generates a protest letter via Claude (PII-redacted) and bundles evidence; otherwise generates a `verification_complete` summary. Creates a submissions row and updates notice status.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Package generatedResolutionPackagePostResponse
    FieldTypeRequiredDescription
    package_idstring · uuidrequired
    statusenum: "generated"required
    package_typeenum: "protest_letter" | "verification_complete"required
    documentsarray<ResolutionPackageDocument>required
  • 400Validation error / required documents missingNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice or entity not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
  • 500Server errorNoticeUnauthorizedResponse
GET/api/notices/{id}/detailGet notice detail

Returns the full notice + associated entity + audit_events + pipeline events + signed document URL + payroll context. Auto-applies any existing entity-level payroll verification when the tax year matches (re-uses prior payroll uploads across notices for the same entity).

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Notice detail bundleNoticeDetailResponse
    FieldTypeRequiredDescription
    noticeobjectrequired
    entityobjectrequired
    cpa_membersarray<object>required
    eventsarray<object>required
    pipeline_eventsarray<object>required
    document_urlstringrequired
    payrollobjectrequired
    entity_payrollobjectrequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
POST/api/notices/{id}/detailAdd note to notice timeline

Append a note to the notice's audit timeline. Tenant_id always sourced from the auth context — never from the body — to prevent cross-tenant audit writes (Gemini PR #471 review fix).

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body NoticeDetailPostBodyrequired

FieldTypeRequiredDescription
notestringrequired

Responses

  • 200Note appendedNoticeOkResponse
    FieldTypeRequiredDescription
    okenum: truerequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
PATCH/api/notices/{id}/detailUpdate notice status

Update the notice status. Tenant-scoped (root-cause fix vs pre-Phase-4 which only filtered by id).

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body NoticeDetailPatchBodyrequired

FieldTypeRequiredDescription
statusstringrequired

Responses

  • 200UpdatedNoticeOkResponse
    FieldTypeRequiredDescription
    okenum: truerequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
GET/api/notices/{id}/required-documentsGet required-documents checklist

Returns the document checklist required to resolve the notice. Each entry tagged status=uploaded | on_file | not_uploaded based on prior direct uploads, entity-level documents, payroll-on-file (tax-year + state matched), or existing payroll_verification.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Checklist + per-doc statusRequiredDocumentsGetResponse
    FieldTypeRequiredDescription
    notice_typestringrequired
    payroll_neededbooleanrequired
    descriptionstringoptional
    documentsarray<RequiredDocument>required
    all_uploadedbooleanrequired
    can_generate_resolutionbooleanrequired
  • 400Validation errorNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceededNoticeRateLimitResponse
POST/api/notices/{id}/required-documentsUpload checklist document

Upload a document for a checklist requirement. multipart/form-data with `file` + `document_key`. Payroll spreadsheets (CSV/XLSX) trigger the 4-path side-effect pipeline: PATH A rate verification, PATH B balance/payroll verification, PATH C ADP per-employee SUI, PATH D smart verification + auto-protest letter generation. All side effects are tenant-scoped (KRT-1479 P4b.7 root-cause fix).

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body RequiredDocumentsMultipartBodyrequired

FieldTypeRequiredDescription
filestringrequiredDocument file binary
document_keystringrequiredChecklist key, e.g., quarterly_sui_wages | quarterly_payroll_summary

Responses

  • 200Uploaded; checklist re-evaluatedRequiredDocumentsPostResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    document_idstring · uuidrequired
    all_uploadedbooleanrequired
  • 400Validation error / missing file or document_keyNoticeValidationErrorResponse
  • 401UnauthorizedNoticeUnauthorizedResponse
  • 403Forbidden — missing required scopeNoticeUnauthorizedResponse
  • 404Notice not found in caller's tenantNoticeNotFoundResponse
  • 429Rate limit exceeded (uploads use the 10/min ceiling)NoticeRateLimitResponse
  • 500Server error / storage upload / document insert failedNoticeUnauthorizedResponse
GET/api/noticesList notices

List notices for the caller's tenant with filters / sort / pagination. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
statusquerystringoptional
filterqueryenum: "needs_review" | "in_progress" | "overdue" | "resolved"optional
statequerystringoptional
searchquerystringoptional
date_fromquerystringoptional
date_toquerystringoptional
sort_byquerystringoptional
sort_dirquerystringoptional
pagequeryintegeroptional
page_sizequeryintegeroptional
limitqueryintegeroptional

Responses

  • 200NoticesNoticesListResponse
    FieldTypeRequiredDescription
    noticesarray<NoticeListItem>required
    totalintegerrequired
    pageintegerrequired
    page_sizeintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/notices/historical-finesHistorical fines analysis

Aggregated historical fines analysis with statute-of-limitations for the caller's tenant. Returns total fines, recoverable amounts, expiring counts, and per-state breakdown.

Bearer scopesnotices.read

Responses

  • 200Fines analysisHistoricalFinesResponse
    FieldTypeRequiredDescription
    totalFinesnumberrequired
    noticeCountintegerrequired
    recoverableAmountnumberrequired
    recoverableCountintegerrequired
    expiringCountintegerrequired
    expiredAmountnumberrequired
    topAmountsarray<object>required
    dateRangeobjectrequired
    byStateobjectrequired
    estimatedRecoveryobjectrequired
    historicalReviewPurchasedbooleanrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/notices/review-queueCPA review queue

CPA review queue ordered by deadline urgency. Notices in pipeline states NEEDS_REVIEW / READY_FOR_REVIEW / AWAITING_PAYROLL / VERIFIED. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
limitqueryintegeroptional
offsetqueryintegeroptional
financial_impactquerystringoptional

Responses

  • 200Review queueReviewQueueResponse
    FieldTypeRequiredDescription
    noticesarray<object>required
    countintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/{id}/actionCPA action on notice

CPA action on a reviewed notice (approve, dismiss, request revision). Triggers pipeline_status transition: approved→ACTIONED, dismissed→DISMISSED, revision_requested→NEEDS_REVIEW. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body NoticeActionBodyrequired

FieldTypeRequiredDescription
actionenum: "approved" | "dismissed" | "revision_requested"required
notesstringoptional

Responses

  • 200Action recordedNoticeActionResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    pipeline_statusstringrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 404Notice not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/notices/{id}/eventsList notice pipeline events

Pipeline event audit trail for a notice.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200EventsNoticeEventsListResponse
    FieldTypeRequiredDescription
    eventsarray<NoticeEvent>required
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Notice not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/{id}/eventsCreate notice pipeline event

Record a manual pipeline event on a notice (e.g. evidence_verified).

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body NoticeEventCreateBodyrequired

FieldTypeRequiredDescription
event_typestringrequired
descriptionstringoptional

Responses

  • 201Event recordedNoticeEventCreateResponse
    FieldTypeRequiredDescription
    eventNoticeEventrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Notice not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/{id}/generate-draftGenerate draft response

Manually trigger draft response generation for a notice. Cookie sessions go through the Stripe gate; Bearer keys bypass. Bearer scope: `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Draft generatedGenerateDraftResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    draft_idstring · uuidrequired
    draft_lengthintegerrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)MiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/{id}/processTrigger notice pipeline

Manually trigger the notice pipeline (re-classify, re-cross-reference, regenerate draft). CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`. Cookie sessions go through the Stripe gate.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Pipeline completeProcessNoticeResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    pipelineobjectrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)MiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/{id}/process-with-payrollProcess notice with payroll

Triggers validate+draft pipeline after payroll has been uploaded (only valid from AWAITING_PAYROLL). Cookie sessions go through the Stripe gate. Bearer scope: `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Pipeline completeProcessWithPayrollResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    resultobjectrequired
  • 400Validation error / wrong pipeline state / no payrollMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)MiscUnauthorizedResponse
  • 404Notice not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/notices/{id}/payroll-comparisonPayroll vs notice rate comparison

Compare a notice's assigned SUI rate against the employer's actual payroll data (with wage-base caps + quarterly breakdown). Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200ComparisonPayrollComparisonResponse
    FieldTypeRequiredDescription
    notice_ratenumberrequired
    actual_ratenumberrequired
    rate_deltanumberrequired
    estimated_overpaymentnumberrequired
    quartersarray<object>required
    wage_base_capnumberrequired
    statestringrequired
    tax_yearintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Notice not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/{id}/draft/advanceAdvance draft through approval chain

Advance the draft response through approval steps (reviewed → counter_signed → submitted). CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body DraftAdvanceBodyrequired

FieldTypeRequiredDescription
stepenum: "reviewed" | "counter_signed" | "submitted"required
notesstringoptional

Responses

  • 200Draft advancedDraftAdvanceResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    currentStepenum: "reviewed" | "counter_signed" | "submitted"required
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 404Notice not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/{id}/draft-feedbackSubmit draft feedback

Submit thumbs-up/thumbs-down feedback on a generated draft response. Used to train future draft generation. Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body DraftFeedbackBodyrequired

FieldTypeRequiredDescription
draft_idstring · uuidrequired
ratingenum: "thumbs_up" | "thumbs_down"required
commentstringoptional

Responses

  • 200Feedback recordedDraftFeedbackResponse
    FieldTypeRequiredDescription
    successenum: truerequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Notice or draft not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/{id}/confirm-sui-rateConfirm/override SUI rate

CPA confirms or overrides the ADP-sourced SUI rate. `confirm` marks the ADP rate as verified; `override` stores a CPA-corrected rate alongside the ADP original. Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body ConfirmSuiRateBodyrequired

FieldTypeRequiredDescription
actionenum: "confirm" | "override"required
override_ratenumberoptional

Responses

  • 200Rate confirmed/overriddenConfirmSuiRateResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    actionenum: "confirmed" | "overridden"required
    statestringrequired
    ratenumberoptional
    original_ratenumberoptional
    overridden_ratenumberoptional
    confirmed_bystring · uuidrequired
  • 400Validation error / cannot determine stateMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Notice or SUI rate record not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/{id}/fileMark notice filed

Mark a notice as filed with the agency (KRT-1476 Feature 1 AC5). Captures confirmation_number + filed_at. Auto two-step transition open|needs_review → in_progress → filed. Optimistic lock prevents double-file races. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body NoticeFileBodyrequired

FieldTypeRequiredDescription
confirmation_numberstringrequired
notesstringoptional

Responses

  • 200Notice filedNoticeFileResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    notice_idstring · uuidrequired
    statusenum: "filed"required
    confirmation_numberstringrequired
    filed_atstring · date-timerequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 404Notice not foundMiscNotFoundResponse
  • 409Already filed / closed / race lostNoticeFileConflictResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/notices/{id}/evidence/{type}Generate evidence PDF

Generate an evidence PDF for a protest package. type=payroll-summary or claims-history. Uploads to Supabase storage and returns a 1-hour signed URL when upload succeeds; falls back to direct PDF binary response when the upload fails (rare — non-fatal for the workflow).

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID
typepathenum: "payroll-summary" | "claims-history"requiredEvidence type

Responses

  • 200Signed URL (or PDF binary on storage failure)NoticeEvidenceResponse
    FieldTypeRequiredDescription
    urlstringrequired
    filenamestringrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Notice not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/{id}/verify-rateVerify SUI rate

Verify a notice's assigned SUI rate against the employer's payroll experience. If payroll data is incomplete, returns needsData=true + the list of required fields. Cookie sessions go through the Stripe gate. Bearer scope: `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body VerifyRateBody

FieldTypeRequiredDescription
totalBenefitChargesnumberoptional
totalContributionsnumberoptional
totalTaxableWagesnumberoptional
averageAnnualPayrollnumberoptional
yearsInBusinessintegeroptional
employeeCountintegeroptional
voluntaryContributionsnumberoptional

Responses

  • 200Rate verification result OR needsData promptone of (VerifyRateResultResponse · VerifyRateNeedsDataResponse)
  • 400Validation error / state not supportedMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)MiscUnauthorizedResponse
  • 404Notice not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/uploadUpload notice

Single-notice intake. Auto-matches/creates entity from extracted text, uploads to storage, creates notice + document records, fires the pipeline asynchronously. Cookie sessions go through Stripe gate + rate-limit + idempotency middleware. Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Request body objectrequired

FieldTypeRequiredDescription
filestring · binaryrequired
entity_idstring · uuidoptional

Responses

  • 200Uploaded (or duplicate)NoticeUploadResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    notice_idstring · uuidrequired
    document_idstring · uuidoptional
    storage_pathstringoptional
    content_hashstringrequired
    duplicateenum: trueoptional
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)MiscUnauthorizedResponse
  • 403Entity not found / not accessibleMiscUnauthorizedResponse
  • 409Duplicate notice (already uploaded)NoticeUploadDuplicateResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/bulk-uploadBulk upload historical notices

Bulk historical notice ingestion. Up to 50 files in one FormData. Runs OCR-only (no classification); creates notice records with pipeline_status='OCR_ONLY'. Cookie sessions go through the Stripe gate. Bearer scope: `notices.write`.

Bearer scopesnotices.write

Request body objectrequired

FieldTypeRequiredDescription
filesarray<string · binary>required

Responses

  • 200Upload + OCR resultNoticeBulkUploadResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    uploadCountintegerrequired
    ocrSuccessintegerrequired
    ocrFailedintegerrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)MiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/notices/{id}/cross-referenceCross-reference notice with payroll

Cross-reference notice against payroll data; runs SUI-specific analysis with state-by-state taxable wage bases + max rates when applicable. Returns needs_payroll_data:true when payroll data is missing for the relevant period (auto-falls-back to adjacent years). Persists cross_reference_analysis on the notice. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Responses

  • 200Result OR needs_payroll_data promptone of (CrossReferenceResultResponse · CrossReferenceNeedsDataResponse)
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Notice not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/notices/{id}/send-for-signatureSend notice response for signature

E-signature flow (KRT-1476 Feature 1 Phase 6): renders/uploads a response PDF if no document_id is provided, creates a signature_requests row with secure token + 7-day expiry, sends the signing-link email to the client. Returns signing_link + request_id even if email delivery fails (best-effort). CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredNotice UUID

Request body SendForSignatureBodyrequired

FieldTypeRequiredDescription
signer_namestringrequired
signer_emailstring · emailrequired
signer_titlestringoptional
expires_daysintegeroptional
document_idstring · uuidoptional
document_titlestringoptional

Responses

  • 201Signature request createdSendForSignatureResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    signing_linkstringrequired
    request_idstring · uuidrequired
    secure_tokenstringrequired
    expires_atstring · date-timerequired
    document_idstring · uuidrequired
    email_sentbooleanrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 404Notice or document not foundMiscNotFoundResponse
  • 409Notice already filed/closed OR document linked elsewhereMiscValidationErrorResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

Packets4

GET/api/packets/{id}Get response packet

Get response packet with status + document list + linked notice metadata (KRT-224).

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredResponse packet UUID

Responses

  • 200PacketPacketDetailResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    packetPacketDetailrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Packet not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/packets/{id}/downloadDownload response packet

Generate 7-day signed download URLs for all packet documents.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredResponse packet UUID

Responses

  • 200Signed URLsPacketDownloadResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    packet_idstring · uuidrequired
    documentsarray<PacketDownloadDocument>required
    expires_in_secondsintegerrequired
    messagestringrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Packet or documents not foundMiscNotFoundResponse
  • 409Packet still assemblingMiscValidationErrorResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/packets/{id}/submitSubmit response packet

Mark a response packet as submitted, record submission reference, and transition the linked notice to `filed` status. Refused unless packet is in `ready` state.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredResponse packet UUID

Request body PacketSubmitBodyrequired

FieldTypeRequiredDescription
submission_refstringrequired
submission_methodenum: "email" | "fax" | "portal" | "mail"optional
notesstringoptional

Responses

  • 200SubmittedPacketSubmitResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    packetobjectrequired
    messagestringrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Packet not foundMiscNotFoundResponse
  • 409Packet not in ready statusMiscValidationErrorResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/packets/assembleAssemble response packet

Trigger an async packet assembly job. Returns a job_id; poll the packet endpoint for status. Cookie sessions go through rate-limit + idempotency middleware.

Bearer scopesnotices.write

Request body PacketAssembleBodyrequired

FieldTypeRequiredDescription
notice_idstring · uuidrequired
resolution_idstring · uuidoptional
evidence_idsarray<string · uuid>optional

Responses

  • 200Job queuedPacketAssembleResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    job_idstring · uuidrequired
    notice_idstring · uuidrequired
    statusenum: "assembling"required
    messagestringrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Notice not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

Payroll9

GET/api/payroll/dataGet payroll dropdown data

Returns entities visible to the caller, optionally with notices for a specific entity. Backs the payroll-page entity dropdown.

Bearer scopespayroll.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidoptionalWhen present, also returns notices for this entity (tenant-scoped)

Responses

  • 200Entities + (optional) noticesPayrollDataResponse
    FieldTypeRequiredDescription
    entitiesarray<PayrollEntity>required
    noticesarray<PayrollNoticeSummary>required
  • 400Validation errorPayrollValidationErrorResponse
  • 401UnauthorizedPayrollUnauthorizedResponse
  • 403Forbidden — missing required scopePayrollUnauthorizedResponse
  • 429Rate limit exceededPayrollRateLimitResponse
GET/api/payroll/template.csvDownload payroll CSV template

Returns a CSV template for payroll data upload. Columns match the generic format payroll-validator.ts expects.

Bearer scopespayroll.read

Responses

  • 200CSV templatestring
  • 401Unauthorized
  • 403Forbidden — missing required scope
  • 429Rate limit exceeded
POST/api/payroll/parse-previewPreview payroll file headers

Server-side payroll preview parser. Returns only the header row + row count for client-side column-mapping; the full file still ships to /api/payroll/upload for processing. Routes XLSX through the hardened safeParseXLSX wrapper (xlsx@0.18.5 has known CVEs that the wrapper neutralizes).

Bearer scopespayroll.read

Request body PayrollMultipartFileBodyrequired

FieldTypeRequiredDescription
filestringrequiredCSV or Excel binary

Responses

  • 200Header preview + row countPayrollParsePreviewResponse
    FieldTypeRequiredDescription
    headersarray<string>required
    rowCountintegerrequired
    formatenum: "xlsx" | "csv"required
  • 400Validation error / invalid filePayrollValidationErrorResponse
  • 401UnauthorizedPayrollUnauthorizedResponse
  • 403Forbidden — missing required scopePayrollUnauthorizedResponse
  • 413File too large (>10 MB)PayrollValidationErrorResponse
  • 415Unsupported file typePayrollValidationErrorResponse
  • 429Rate limit exceededPayrollRateLimitResponse
POST/api/payroll/validateValidate ADP payroll CSV

ADP payroll CSV validator (KRT-396). Accepts multipart with `file` + `notice_id`. Validates the CSV against the ADP-specific validator and persists the result to validation_results. Tenant-scoped on the notice access check + insert.

Bearer scopespayroll.write

Request body PayrollValidateMultipartBodyrequired

FieldTypeRequiredDescription
filestringrequiredADP CSV file
notice_idstring · uuidrequiredNotice UUID to validate against

Responses

  • 200Validation result + persisted record idPayrollValidateResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    validation_result_idstring · uuidrequired
    validationobjectrequired
  • 400Validation error / file too large / not CSVPayrollValidationErrorResponse
  • 401UnauthorizedPayrollUnauthorizedResponse
  • 403Forbidden — missing required scopePayrollUnauthorizedResponse
  • 404Notice not found in caller's tenantPayrollNotFoundResponse
  • 429Rate limit exceededPayrollRateLimitResponse
  • 500Server errorPayrollUnauthorizedResponse
GET/api/payroll/pullGet payroll data status

Returns the current payroll-data status for an entity — cache tier, age in days, and active provider connection (if any). All queries tenant-scoped.

Bearer scopespayroll.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidrequiredEmployer entity UUID (required)

Responses

  • 200Status bundlePayrollPullStatusResponse
    FieldTypeRequiredDescription
    connectionobjectrequired
    payroll_dataobjectrequired
    cache_tierenum: "hot" | "warm" | "cold" | "none"required
    age_daysintegerrequired
  • 400Validation errorPayrollValidationErrorResponse
  • 401UnauthorizedPayrollUnauthorizedResponse
  • 403Forbidden — missing required scopePayrollUnauthorizedResponse
  • 429Rate limit exceededPayrollRateLimitResponse
  • 500Server errorPayrollUnauthorizedResponse
POST/api/payroll/pullTrigger payroll pull

Trigger a payroll pull for an employer entity. Routes through the tiered pull-engine cache (hot/warm/cold); `force_refresh=true` skips the hot tier. Returns 404 if no provider connection is configured.

Bearer scopespayroll.write

Request body PayrollPullPostBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
trigger_typestringrequired
trigger_refstringoptional
force_refreshbooleanoptional

Responses

  • 200Pull resultPayrollPullPostResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    cache_tierenum: "hot" | "warm" | "cold"required
    employee_countintegerrequired
    total_earningsnumberrequired
    statesarray<string>required
    pulled_atstring · date-timerequired
  • 400Validation errorPayrollValidationErrorResponse
  • 401UnauthorizedPayrollUnauthorizedResponse
  • 403Forbidden — missing required scopePayrollUnauthorizedResponse
  • 404No payroll data available — check employer connectionPayrollNotFoundResponse
  • 429Rate limit exceededPayrollRateLimitResponse
  • 500Server errorPayrollUnauthorizedResponse
POST/api/payroll/notice-syncADP credentialed payroll sync for a notice

Sync ADP payroll for a specific notice's quarter + 5 quarters of gap-fill. Credentials are stored temporarily in AWS SSM and deleted after the session unless `save_connection=true`. Plaintext NEVER persists outside SSM.

Bearer scopespayroll.write

Request body PayrollNoticeSyncBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
notice_idstring · uuidrequired
needed_yearintegerrequired
needed_quarterintegerrequired
usernamestringrequired
passwordstringrequired
company_codestringoptional
save_connectionbooleanoptional

Responses

  • 200Sync result + per-period statsPayrollNoticeSyncResponse
    FieldTypeRequiredDescription
    successbooleanrequired
    notice_idstring · uuidrequired
    notice_period_syncedbooleanrequired
    gap_periods_syncedintegerrequired
    total_employeesintegerrequired
    total_wage_recordsintegerrequired
    errorsarray<string>required
    messagestringrequired
  • 400Validation errorPayrollValidationErrorResponse
  • 401UnauthorizedPayrollUnauthorizedResponse
  • 403Forbidden — missing required scopePayrollUnauthorizedResponse
  • 429Rate limit exceededPayrollRateLimitResponse
  • 500Server error / SSM / connection upsert failurePayrollUnauthorizedResponse
POST/api/payroll/upload-reportUpload payroll report

Upload a payroll-related report file (CSV/PDF/Excel) for an entity. Persists to documents + Supabase storage. CSVs additionally get parsed and the parsed summary stored on the document row for downstream rate verification.

Bearer scopespayroll.write

Request body PayrollUploadReportMultipartBodyrequired

FieldTypeRequiredDescription
filestringrequiredCSV/PDF/Excel binary (max 50 MB)
report_typestringrequiredNormalized report type (e.g., payroll_journal)
entity_idstring · uuidrequired

Responses

  • 200Uploaded; document_id + parsed summary (CSV only)PayrollUploadReportResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    documentIdstring · uuidrequired
    fileUrlstringrequired
    storage_pathstringrequired
    content_hashstringrequired
    parsedobjectrequired
  • 400Validation errorPayrollValidationErrorResponse
  • 401UnauthorizedPayrollUnauthorizedResponse
  • 403Forbidden — missing required scopePayrollUnauthorizedResponse
  • 404Entity not found in caller's tenantPayrollNotFoundResponse
  • 429Rate limit exceeded (uploads use the 10/min ceiling)PayrollRateLimitResponse
  • 500Server error / storage upload / document insert failedPayrollUnauthorizedResponse
POST/api/payroll/uploadUpload payroll file (heavy)

Upload a payroll CSV or Excel file for an entity, optionally linked to a notice. Pipeline: storage upload → payroll_uploads + payroll_records insert → SUI detail extraction (per-employee/month/state from Excel) → mergePayrollData into entity_payroll_data → validation_results when notice-linked → auto-trigger verification pipeline for AWAITING_PAYROLL notices. Idempotency-aware: same x-idempotency-key replays the prior response.

Bearer scopespayroll.write

Request body PayrollUploadFormBodyrequired

FieldTypeRequiredDescription
filestringrequiredCSV or Excel binary (max 10 MB)
entity_idstring · uuidrequired
notice_idstring · uuidoptional
column_mapstringoptionalJSON-stringified ColumnMap (employee_name, gross_wages, state, etc.)

Responses

  • 200Uploaded; validation summary + records_stored countPayrollUploadResponseDetailed
    FieldTypeRequiredDescription
    okenum: truerequired
    payroll_upload_idstring · uuidrequired
    storage_pathstringrequired
    content_hashstringrequired
    validationPayrollUploadValidationSummaryrequired
    records_storedintegerrequired
  • 400Validation error / file too large / unsupported file type / unsafe XLSXPayrollValidationErrorResponse
  • 401UnauthorizedPayrollUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)PayrollUnauthorizedResponse
  • 403Forbidden — missing required scopePayrollUnauthorizedResponse
  • 404Entity or notice not found in caller's tenantPayrollNotFoundResponse
  • 429Rate limit exceeded (uploads use the 10/min ceiling)PayrollRateLimitResponse
  • 500Server error / storage / validation pipeline failurePayrollUnauthorizedResponse

POA7

GET/api/poa-authorizationsList POA authorizations

List POA authorizations for the caller's tenant (KRT-464). Filter by employer_entity_id / poa_entity_id; toggle inclusion of revoked rows with `include_revoked=true`. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
employer_entity_idquerystring · uuidoptional
poa_entity_idquerystring · uuidoptional
include_revokedquerybooleanoptional

Responses

  • 200POA authorizationsPOAAuthorizationsListResponse
    FieldTypeRequiredDescription
    authorizationsarray<POAAuthorization>required
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/poa-authorizationsRequest POA authorization

Request a new POA authorization (KRT-464). 409 if an authorization already exists for the same employer + poa + scope. Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Request body POAAuthorizationCreateBodyrequired

FieldTypeRequiredDescription
employer_entity_idstring · uuidrequired
poa_entity_idstring · uuidrequired
scopearray<POAScope>required

Responses

  • 201Authorization requestedPOAAuthorizationCreateResponse
    FieldTypeRequiredDescription
    authorizationPOAAuthorizationrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 409Authorization already existsMiscValidationErrorResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/poa-authorizations/{id}/generateGenerate pre-filled POA PDF

Generate a pre-filled POA PDF for a previously-created authorization. Two modes: `download` (returns the PDF + filing instructions only) and `send-for-signature` (creates a signature_request and emails the signer + a copy to the originating CPA). Bearer keys gate via `notices.write`. Kreto does NOT submit the form to the agency — the user files manually using the agency portal or mailing address in the `filing` block of the response.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredPOA authorization UUID

Request body POAGenerateBody

FieldTypeRequiredDescription
template_idstringrequiredPre-auth template id (e.g., 'poa-tax-representation'). Browse via GET /api/pre-authorization-templates.
modeenum: "download" | "send-for-signature"optional'download' returns the PDF only. 'send-for-signature' creates a signature_request, emails the signer + originator. Default: send-for-signature.
signer_namestringoptional
signer_emailstring · emailoptional
overridesobjectoptional

Responses

  • 200Mode=download: pre-filled PDF + filing instructionsobject
    FieldTypeRequiredDescription
    modeenum: "download"required
    authorization_idstring · uuidrequired
    template_idstringrequired
    template_namestringrequired
    document_pathstringrequired
    document_urlstringrequired
    document_hashstringrequired
    filingobjectrequired
    missing_required_fieldsarray<string>required
  • 201Mode=send-for-signature: signing request created + email queuedobject
    FieldTypeRequiredDescription
    modeenum: "send-for-signature"required
    authorization_idstring · uuidrequired
    signature_request_idstring · uuidrequired
    secure_tokenstringrequired
    signing_linkstringrequired
    expires_atstring · date-timerequired
    document_pathstringrequired
    document_urlstringrequired
    document_hashstringrequired
    template_idstringrequired
    template_namestringrequired
    filingobjectrequired
    missing_required_fieldsarray<string>required
    signer_emailstring · emailrequired
    originator_emailedbooleanrequired
  • 400Validation error (missing template_id, invalid body, etc.)MiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Authorization or employer entity not found in your tenantMiscNotFoundResponse
  • 409Authorization is revoked — cannot generate a documentMiscValidationErrorResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server error (PDF generation failure, DB error)MiscUnauthorizedResponse
PATCH/api/poa-authorizations/{id}Revoke POA authorization

Revoke a POA authorization. Bearer keys gate via `notices.write`. 409 if already revoked.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredPOA authorization UUID

Responses

  • 200Authorization revokedPOAAuthorizationRevokeResponse
    FieldTypeRequiredDescription
    authorizationPOAAuthorizationrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Authorization not foundMiscNotFoundResponse
  • 409Authorization already revokedMiscValidationErrorResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/pre-authorization-templatesList pre-auth templates

List pre-authorization templates from the global Kreto library. No tenant data is read. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
categoryquerystringoptional
statequerystringoptional

Responses

  • 200TemplatesPreAuthTemplatesListResponse
    FieldTypeRequiredDescription
    templatesarray<PreAuthTemplateSummary>required
    totalintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
GET/api/pre-authorization-templates/{id}Get pre-auth template

Retrieve full template details (content template + field definitions + signature fields). Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstringrequiredPre-auth template ID

Responses

  • 200TemplatePreAuthTemplateDetailResponse
    FieldTypeRequiredDescription
    templatePreAuthTemplateFullrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Template not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
POST/api/pre-authorization-templates/{id}/autofillAuto-fill pre-auth template

Auto-fill a pre-authorization template from entity data. Optionally renders to PDF and uploads to storage when generate_pdf=true (and employer_id is provided). CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstringrequiredPre-auth template ID

Request body PreAuthAutofillBodyrequired

FieldTypeRequiredDescription
entity_dataobjectrequired
overridesobjectoptional
generate_pdfbooleanoptional
employer_idstring · uuidoptional
cpa_namestringoptional
cpa_firmstringoptional

Responses

  • 200Auto-fill result (with optional pdf_path/pdf_hash)PreAuthAutofillResponse
    FieldTypeRequiredDescription
    rendered_contentstringrequired
    resolved_fieldsobjectrequired
    missing_required_fieldsarray<string>required
    missing_optional_fieldsarray<string>required
    pdf_pathstringoptional
    pdf_hashstringoptional
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 404Template not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

Reports7

GET/api/reports/notice-summaryNotice summary report

Group notices by status + (primary) type for the caller's tenant. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Responses

  • 200SummaryReportsNoticeSummaryResponse
    FieldTypeRequiredDescription
    by_statusobjectrequired
    by_typeobjectrequired
    totalintegerrequired
  • 401UnauthorizedReportsUnauthorizedResponse
  • 429Rate limit exceededReportsRateLimitResponse
  • 500Server errorReportsUnauthorizedResponse
GET/api/reports/roiROI report

ROI metrics: total savings, notices resolved, average resolution days, protests won, and ROI multiple. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Responses

  • 200ROIReportsRoiResponse
    FieldTypeRequiredDescription
    total_savingsnumberrequired
    notices_resolvedintegerrequired
    avg_resolution_daysintegerrequired
    protests_wonintegerrequired
    roi_multiplenumberrequired
  • 401UnauthorizedReportsUnauthorizedResponse
  • 429Rate limit exceededReportsRateLimitResponse
  • 500Server errorReportsUnauthorizedResponse
GET/api/reports/sui-impactSUI impact report

SUI-related notice analysis with per-notice breakdown. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Responses

  • 200SUI impactReportsSuiImpactResponse
    FieldTypeRequiredDescription
    summaryobjectrequired
    noticesarray<ReportsSuiImpactNotice>required
  • 401UnauthorizedReportsUnauthorizedResponse
  • 429Rate limit exceededReportsRateLimitResponse
  • 500Server errorReportsUnauthorizedResponse
GET/api/reports/compliance-scorecardCompliance scorecard

Entity-level compliance scores + trend signal (+5 / 0 / -5). Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Responses

  • 200ScorecardReportsScorecardResponse
    FieldTypeRequiredDescription
    entitiesarray<ReportsScorecardEntity>required
  • 401UnauthorizedReportsUnauthorizedResponse
  • 429Rate limit exceededReportsRateLimitResponse
  • 500Server errorReportsUnauthorizedResponse
GET/api/reports/state-authorizationState authorization report

POA status per entity per state, joining poa_authorizations + documents tables. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Responses

  • 200State authorizationReportsStateAuthResponse
    FieldTypeRequiredDescription
    entitiesarray<ReportsStateAuthEntity>required
  • 401UnauthorizedReportsUnauthorizedResponse
  • 429Rate limit exceededReportsRateLimitResponse
  • 500Server errorReportsUnauthorizedResponse
GET/api/reports/response-timeResponse-time report

Notice processing-time metrics (classification seconds, resolution days, draft hours) with monthly breakdown. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Responses

  • 200Response-time metricsReportsResponseTimeResponse
    FieldTypeRequiredDescription
    avg_classification_secondsintegerrequired
    avg_resolution_daysnumberrequired
    avg_draft_hoursnumberrequired
    total_processedintegerrequired
    by_montharray<ReportsResponseTimeMonth>required
  • 401UnauthorizedReportsUnauthorizedResponse
  • 429Rate limit exceededReportsRateLimitResponse
  • 500Server errorReportsUnauthorizedResponse
POST/api/reports/generateGenerate report

Generate a compliance report for the requested entities + date range. Returns JSON or a CSV file (Content-Disposition: attachment). Up to 50 entities per call. Bearer keys gate via `audit.read` (full tenant scope); cookie sessions use RLS-enforced entity access.

Bearer scopesaudit.read

Request body ReportsGenerateBodyrequired

FieldTypeRequiredDescription
typestringrequired
entityIdsarray<string · uuid>required
dateRangeobjectrequired
formatenum: "json" | "csv"optional

Responses

  • 200Report (JSON when format=json; CSV download otherwise)ReportsGenerateJsonResponse
    FieldTypeRequiredDescription
    typestringrequired
    rowsarray<object>required
    summaryobjectoptional
    csvstringoptional
  • 400Validation errorReportsValidationErrorResponse
  • 401UnauthorizedReportsUnauthorizedResponse
  • 403Access denied for one or more entityIdsReportsUnauthorizedResponse
  • 429Rate limit exceededReportsRateLimitResponse
  • 500Server errorReportsUnauthorizedResponse

Resolutions5

POST/api/resolutions/generateGenerate resolution draft

Generate a resolution draft via Claude. CPA-only on cookie sessions; Bearer keys gate via `notices.write`. PII redacted before LLM call. Idempotency-aware via x-idempotency-key.

Bearer scopesnotices.write

Request body ResolutionGenerateBodyrequired

FieldTypeRequiredDescription
notice_idstring · uuidrequired
evidence_idstring · uuidrequired
templateResolutionTemplaterequired
discrepanciesarray<ResolutionDiscrepancy>optional
additional_contextstringoptional

Responses

  • 200Draft generatedResolutionGenerateResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    draft_idstring · uuidrequired
    versionintegerrequired
    statusenum: "draft"required
    redacted_fieldsarray<string>required
  • 400Validation errorResolutionValidationErrorResponse
  • 401UnauthorizedResolutionUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)ResolutionUnauthorizedResponse
  • 403Forbidden — CPA access required / missing scopeResolutionUnauthorizedResponse
  • 404Notice or evidence packet not found in caller's tenantResolutionNotFoundResponse
  • 429Rate limit exceededResolutionRateLimitResponse
  • 500Server errorResolutionUnauthorizedResponse
GET/api/resolutions/{id}Get resolution draft

Returns the draft + joined evidence packet metadata + tenant status counts. 422 if draft has no evidence packet (data integrity).

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredResolution draft UUID

Responses

  • 200Draft + evidence + statsResolutionGetResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    draftall of (ResolutionDraftRecord · object)required
    statsobjectrequired
  • 400Validation errorResolutionValidationErrorResponse
  • 401UnauthorizedResolutionUnauthorizedResponse
  • 403Forbidden — missing required scopeResolutionUnauthorizedResponse
  • 404Draft not found in caller's tenantResolutionNotFoundResponse
  • 422Draft missing evidence packet (data integrity)ResolutionValidationErrorResponse
  • 429Rate limit exceededResolutionRateLimitResponse
  • 500Server errorResolutionUnauthorizedResponse
PATCH/api/resolutions/{id}Edit resolution draft (CPA)

CPA edits draft text. Only allowed in `draft` or `in_review` status.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredResolution draft UUID

Request body ResolutionPatchBodyrequired

FieldTypeRequiredDescription
cpa_editsstringrequired
statusenum: "in_review"optional

Responses

  • 200Draft updatedResolutionPatchResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    draft_idstring · uuidrequired
    statusstringrequired
  • 400Validation error / draft in non-editable statusResolutionValidationErrorResponse
  • 401UnauthorizedResolutionUnauthorizedResponse
  • 403Forbidden — CPA access requiredResolutionUnauthorizedResponse
  • 404Draft not found in caller's tenantResolutionNotFoundResponse
  • 429Rate limit exceededResolutionRateLimitResponse
  • 500Server errorResolutionUnauthorizedResponse
POST/api/resolutions/{id}/approveApprove resolution draft (CPA)

CPA approves a resolution draft. Status transitions in_review → approved. Only valid from in_review.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredResolution draft UUID

Request body ResolutionApproveBody

FieldTypeRequiredDescription
notesstringoptional

Responses

  • 200ApprovedResolutionApproveResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    draft_idstring · uuidrequired
    statusenum: "approved"required
  • 400Validation error / wrong statusResolutionValidationErrorResponse
  • 401UnauthorizedResolutionUnauthorizedResponse
  • 403Forbidden — CPA access requiredResolutionUnauthorizedResponse
  • 404Draft not found in caller's tenantResolutionNotFoundResponse
  • 429Rate limit exceededResolutionRateLimitResponse
  • 500Server errorResolutionUnauthorizedResponse
POST/api/resolutions/{id}/rejectReject resolution draft (CPA)

CPA rejects a draft (in_review → rejected) and optionally regenerates a fresh draft with rejection feedback. Returns new_draft_id when regeneration succeeds.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredResolution draft UUID

Request body ResolutionRejectBodyrequired

FieldTypeRequiredDescription
rejection_reasonstringrequired
regeneratebooleanoptional

Responses

  • 200RejectedResolutionRejectResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    draft_idstring · uuidrequired
    statusenum: "rejected"required
    new_draft_idstring · uuidrequired
  • 400Validation error / wrong statusResolutionValidationErrorResponse
  • 401UnauthorizedResolutionUnauthorizedResponse
  • 403Forbidden — CPA access requiredResolutionUnauthorizedResponse
  • 404Draft not found in caller's tenantResolutionNotFoundResponse
  • 429Rate limit exceededResolutionRateLimitResponse
  • 500Server errorResolutionUnauthorizedResponse

Settings2

GET/api/settings/firmGet firm settings

Firm/tenant settings (name, slug). Bearer keys gate via `admin.read`.

Bearer scopesadmin.read

Responses

  • 200SettingsSettingsFirmResponse
    FieldTypeRequiredDescription
    namestringrequired
    slugstringrequired
    created_atstring · date-timerequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Tenant not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
PATCH/api/settings/firmUpdate firm settings

Update firm/tenant settings (currently: name only). Bearer keys gate via `admin.read`.

Bearer scopesadmin.read

Request body SettingsFirmUpdateBodyrequired

FieldTypeRequiredDescription
namestringrequired

Responses

  • 200Settings updatedSettingsFirmResponse
    FieldTypeRequiredDescription
    namestringrequired
    slugstringrequired
    created_atstring · date-timerequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

SIDES10

GET/api/sides/enrollmentsList SIDES enrollments

List all SIDES employer enrollments for the caller's tenant. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Responses

  • 200EnrollmentsSidesEnrollmentsListResponse
    FieldTypeRequiredDescription
    enrollmentsarray<SidesEnrollment>required
  • 401UnauthorizedSidesUnauthorizedResponse
  • 403Forbidden — CPA access requiredSidesUnauthorizedResponse
  • 429Rate limit exceededSidesRateLimitResponse
  • 500Server errorSidesUnauthorizedResponse
POST/api/sides/enrollmentsEnroll employer in SIDES

Enroll an employer in SIDES for a specific state. NASWA admin-site enrollment is tracked locally; status starts as `pending`. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Request body SidesEnrollmentCreateBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
state_codestringrequired
employer_account_numberstringoptional

Responses

  • 201Enrollment createdSidesEnrollmentCreateResponse
    FieldTypeRequiredDescription
    enrollmentSidesEnrollmentrequired
  • 400Validation errorSidesValidationErrorResponse
  • 401UnauthorizedSidesUnauthorizedResponse
  • 403Forbidden — CPA access requiredSidesUnauthorizedResponse
  • 404Entity not foundSidesNotFoundResponse
  • 409Already enrolled in this stateSidesValidationErrorResponse
  • 429Rate limit exceededSidesRateLimitResponse
  • 500Server errorSidesUnauthorizedResponse
GET/api/sides/exchangesList SIDES exchanges

List inbound SIDES exchanges for the caller's tenant. Supports status / exchange_type / state_code filters, pagination, and sort. Any authenticated caller can read. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
statusquerystringoptional
exchange_typequerystringoptional
state_codequerystringoptional
sortqueryenum: "due_date" | "received_date" | "status"optional
limitqueryintegeroptional
offsetqueryintegeroptional

Responses

  • 200Exchanges + totalSidesExchangesListResponse
    FieldTypeRequiredDescription
    exchangesarray<SidesExchangeListItem>required
    totalintegerrequired
    limitintegerrequired
    offsetintegerrequired
  • 400Validation errorSidesValidationErrorResponse
  • 401UnauthorizedSidesUnauthorizedResponse
  • 429Rate limit exceededSidesRateLimitResponse
  • 500Server errorSidesUnauthorizedResponse
GET/api/sides/exchanges/{id}Get SIDES exchange

Fetch a single SIDES exchange + audit log. Any authenticated caller can read; cookie sessions with `client_user` role get a PII-reduced view (raw XML payloads + claimant names stripped). Bearer keys gate via `notices.read` and receive the full payload.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredSIDES exchange / claim UUID

Responses

  • 200Exchange + audit logSidesExchangeDetailResponse
    FieldTypeRequiredDescription
    exchangeobjectrequired
    audit_logarray<SidesAuditEntry>required
  • 401UnauthorizedSidesUnauthorizedResponse
  • 404Exchange not foundSidesNotFoundResponse
  • 429Rate limit exceededSidesRateLimitResponse
  • 500Server errorSidesUnauthorizedResponse
PUT/api/sides/exchanges/{id}Save SI draft response

Save a drafted SI response for an exchange. Validates via Zod and serializes to XML when valid; otherwise stashes the JSON body for round-trip editing. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredSIDES exchange / claim UUID

Request body SidesSaveDraftBodyrequired

FieldTypeRequiredDescription
responseobjectrequired

Responses

  • 200Draft savedSidesSaveDraftResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    validbooleanrequired
    errorsarray<object>required
  • 400Validation error / unsupported exchange typeSidesValidationErrorResponse
  • 401UnauthorizedSidesUnauthorizedResponse
  • 403Forbidden — CPA access requiredSidesUnauthorizedResponse
  • 404Exchange not foundSidesNotFoundResponse
  • 429Rate limit exceededSidesRateLimitResponse
  • 500Server errorSidesUnauthorizedResponse
POST/api/sides/exchanges/{id}/submitSubmit SI response (CPA)

Approve and submit an SI response to the SIDES Central Broker. The server injects claimantSSNLast4 from the original request XML, validates, serializes, and posts via the NASWA Model Connector CLI. Re-submit is rejected (409) once an exchange reaches responding/responded/acknowledged. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredSIDES exchange / claim UUID

Request body SidesSubmitBodyrequired

FieldTypeRequiredDescription
responseobjectrequired

Responses

  • 200SubmittedSidesSubmitResponse
    FieldTypeRequiredDescription
    okenum: truerequired
    statusenum: "responded"required
    response_filestringrequired
  • 400Validation error / unsupported exchange typeSidesValidationErrorResponse
  • 401UnauthorizedSidesUnauthorizedResponse
  • 403Forbidden — CPA access requiredSidesUnauthorizedResponse
  • 404Exchange not foundSidesNotFoundResponse
  • 409Exchange already submitted/acknowledged — re-submit blockedSidesValidationErrorResponse
  • 422Zod validation failed (with broker-rule remediation)SidesValidationErrorResponse
  • 429Rate limit exceededSidesRateLimitResponse
  • 500Server error (e.g., missing SSN in raw_request_xml)SidesUnauthorizedResponse
  • 502Broker rejected (with business-rule errors)SidesValidationErrorResponse
GET/api/sides/transmissionsList SIDES transmissions

SIDES transmission audit log. Filter by direction (inbound/outbound) and transmission_status. CPA-class roles only on cookie sessions; Bearer keys gate via `audit.read`.

Bearer scopesaudit.read

Parameters

NameInTypeRequiredDescription
directionqueryenum: "inbound" | "outbound"optional
statusquerystringoptional
limitqueryintegeroptional
offsetqueryintegeroptional

Responses

  • 200TransmissionsSidesTransmissionsListResponse
    FieldTypeRequiredDescription
    transmissionsarray<SidesTransmission>required
    totalintegerrequired
  • 401UnauthorizedSidesUnauthorizedResponse
  • 403Forbidden — CPA access requiredSidesUnauthorizedResponse
  • 429Rate limit exceededSidesRateLimitResponse
  • 500Server errorSidesUnauthorizedResponse
GET/api/sides/claimsList SIDES claims (legacy)

List SIDES claims (legacy /sides_separation_requests path). Filter by pending / auto_filled / in_review / overdue / submitted. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
filterqueryenum: "all" | "pending" | "auto_filled" | "in_review" | …optional
limitqueryintegeroptional
offsetqueryintegeroptional

Responses

  • 200ClaimsSidesClaimsListResponse
    FieldTypeRequiredDescription
    claimsarray<SidesClaimListItem>required
    totalintegerrequired
  • 401UnauthorizedSidesUnauthorizedResponse
  • 403Forbidden — CPA access requiredSidesUnauthorizedResponse
  • 429Rate limit exceededSidesRateLimitResponse
  • 500Server errorSidesUnauthorizedResponse
GET/api/sides/claims/{id}Get SIDES claim (legacy)

SIDES claim detail (legacy path) with related transmissions + linked notice. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredSIDES exchange / claim UUID

Responses

  • 200Claim + transmissions + noticeSidesClaimDetailResponse
    FieldTypeRequiredDescription
    claimobjectrequired
    transmissionsarray<SidesTransmission>required
    noticeobjectrequired
  • 401UnauthorizedSidesUnauthorizedResponse
  • 403Forbidden — CPA access requiredSidesUnauthorizedResponse
  • 404Claim not foundSidesNotFoundResponse
  • 429Rate limit exceededSidesRateLimitResponse
  • 500Server errorSidesUnauthorizedResponse
POST/api/sides/claims/{id}/respondSave SIDES claim draft (legacy)

Save a draft response on the legacy claims path. The `approve` action is permanently blocked (410) — the legacy table lacks the FEIN/state-account/SSN data required for a valid SIDES response. Use the v2 sides_exchanges path instead. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`. Cookie sessions go through the Stripe subscription gate.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredSIDES exchange / claim UUID

Request body SidesClaimRespondBodyrequired

FieldTypeRequiredDescription
actionenum: "save" | "approve"required
separation_reasonstringoptional
last_day_workedstringoptional
final_wages_centsintegeroptional
discharge_reasonstringoptional
voluntary_quit_reasonstringoptional
return_to_work_offeredbooleanoptional
notesstringoptional

Responses

  • 200Draft savedSidesClaimRespondResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    response_statusstringrequired
    actionstringrequired
  • 400Validation errorSidesValidationErrorResponse
  • 401UnauthorizedSidesUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)SidesUnauthorizedResponse
  • 403Forbidden — CPA access requiredSidesUnauthorizedResponse
  • 404Claim not foundSidesNotFoundResponse
  • 410Approve is permanently blocked on the legacy pathSidesValidationErrorResponse
  • 429Rate limit exceededSidesRateLimitResponse
  • 500Server errorSidesUnauthorizedResponse

States6

GET/api/statesList state agencies

List state agencies with tax rules for a given year (default 2026). Read-only Kreto reference data — no tenant scope.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
yearqueryintegeroptional

Responses

  • 200StatesStatesListResponse
    FieldTypeRequiredDescription
    dataarray<StateAgency>required
    countintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/states/{code}Get state detail

Single state detail with tax rules, surcharges, notice types, protest rules, POA rules, and statutes. Read-only reference data.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
codepathstringrequired2-letter state code
yearqueryintegeroptional

Responses

  • 200State detailStateDetailResponse
    FieldTypeRequiredDescription
    dataStateDetailrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404State not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/states/{code}/noticesList state notice types

List state notice types ranked by financial impact. Read-only reference data.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
codepathstringrequired2-letter state code

Responses

  • 200Notice typesStateNoticeTypesResponse
    FieldTypeRequiredDescription
    state_codestringrequired
    state_namestringrequired
    dataarray<StateNoticeType>required
    countintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404State not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/states/{code}/poaList state POA rules

List POA rules for a state. Read-only reference data.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
codepathstringrequired2-letter state code

Responses

  • 200POA rulesStatePoaResponse
    FieldTypeRequiredDescription
    state_codestringrequired
    state_namestringrequired
    dataarray<StatePoaRule>required
    countintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404State not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/states/compareCompare states

Compare up to 5 states side-by-side (full ruleset for each). Read-only reference data.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
statesquerystringrequired
yearqueryintegeroptional

Responses

  • 200Comparison dataStatesListResponse
    FieldTypeRequiredDescription
    dataarray<StateAgency>required
    countintegerrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/states/withholdingWithholding reciprocity

Withholding reciprocity calculator. Without query params, returns the full reciprocity map. With work_state + home_state, returns the specific reciprocity decision plus each state's full reciprocity list.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
work_statequerystringoptional
home_statequerystringoptional

Responses

  • 200Reciprocity dataStateWithholdingResponse
    FieldTypeRequiredDescription
    reciprocityAgreementsobjectoptional
    totalStatesWithReciprocityintegeroptional
    resultobjectoptional
    workStateReciprocityarray<string>optional
    homeStateReciprocityarray<string>optional
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse

TaxDocuments8

GET/api/tax-documentsList tax document requests

List tax document requests for caller's tenant. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidoptional
statusquerystringoptional
tax_yearqueryintegeroptional

Responses

  • 200RequestsTaxDocumentRequestsListResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    requestsarray<TaxDocumentRequest>required
    countintegerrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/tax-documentsCreate tax document request

Create a tax document collection request with optional AI checklist generation (KRT-322). Cookie sessions go through rate-limit + idempotency middleware. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Request body TaxDocumentRequestCreateBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
client_idstring · uuidoptional
tax_yearintegerrequired
tax_typeenum: "personal" | "business"required
entity_typeenum: "individual" | "s_corp" | "c_corp" | "partnership" | …optional
notice_idstring · uuidoptional
due_datestringoptional
generate_checklistbooleanoptional
prior_year_itemsarray<string>optional

Responses

  • 201Request createdTaxDocumentRequestCreateResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    requestTaxDocumentRequestrequired
    items_countintegerrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 404Entity not found in caller's tenantMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/tax-documents/{id}Get tax document request

Get tax document request detail with all items.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredTax document request UUID

Responses

  • 200Request + itemsTaxDocumentRequestDetailResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    requestTaxDocumentRequestrequired
    itemsarray<TaxDocumentRequestItem>required
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Request not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
PATCH/api/tax-documents/{id}/items/{itemId}Update tax document item

Update a tax document request item. CPA-class can update label / description / required; client_user / client can update status / uploaded_file / notes. Auto-completes the parent request when all required items reach verified or waived. Bearer keys gate via `notices.write` (treated as CPA-class).

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredTax document request UUID
itemIdpathstring · uuidrequiredTax document item UUID

Request body TaxDocumentItemUpdateBodyrequired

FieldTypeRequiredDescription
statusenum: "pending" | "uploaded" | "verified" | "rejected" | …optional
uploaded_filestringoptional
notesstringoptional
labelstringoptional
descriptionstringoptional
requiredbooleanoptional

Responses

  • 200Item updatedTaxDocumentItemUpdateResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    itemTaxDocumentRequestItemrequired
  • 400Validation error / expired requestMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Request or item not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/tax-documents/{id}/remindersList tax document reminders

List reminders sent for a tax document request + current reminder settings (paused state, custom deadline, due date). Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredTax document request UUID

Responses

  • 200Reminders + settingsTaxDocumentRemindersListResponse
    FieldTypeRequiredDescription
    successenum: truerequired
    remindersarray<TaxDocumentReminder>required
    settingsobjectrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Request not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
PATCH/api/tax-documents/{id}/remindersUpdate tax document reminder settings

Update reminder settings (pause/resume, set custom deadline). CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredTax document request UUID

Request body TaxDocumentRemindersUpdateBodyrequired

FieldTypeRequiredDescription
reminders_pausedbooleanoptional
custom_deadlinestringoptional

Responses

  • 200Settings updatedTaxDocumentRemindersUpdateResponse
    FieldTypeRequiredDescription
    successenum: truerequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 404Request not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/tax-documents/{id}/reminders/sendSend manual reminder

Send a manual reminder for a specific tax document request (KRT-324). CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`. Refused for completed/expired requests.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredTax document request UUID

Responses

  • 200Reminder sent (or skipped with reason)TaxDocumentManualReminderResponse
    FieldTypeRequiredDescription
    successbooleanoptional
    reminder_idstring · uuidrequired
    pending_items_countintegerrequired
    skippedbooleanoptional
    skip_reasonstringoptional
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 404Request not foundMiscNotFoundResponse
  • 422Cannot send reminder for completed/expired requestMiscValidationErrorResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/tax-documents/reminders/bulkBulk-send tax document reminders

Send reminders for the SELECTED documents. Each document id is resolved to its request_id (tenant-scoped) and each distinct request is reminded and audited independently (one audit row per request). Terminal (complete/expired) requests are skipped. CPA-class roles only on cookie sessions; Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Request body TaxDocumentBulkRemindersRequest

FieldTypeRequiredDescription
idsarray<string · uuid>requiredSelected document ids (1..200)

Responses

  • 200Bulk send result (applied / skipped / failed)TaxDocumentBulkRemindersResponse
    FieldTypeRequiredDescription
    appliedintegerrequired
    skippedarray<object>required
    failedarray<object>required
  • 401UnauthorizedMiscUnauthorizedResponse
  • 403Forbidden — CPA access requiredMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

TaxLiens2

GET/api/tax-liensList tax liens

List tax liens for the caller's tenant. Filters: entity_id, status, lien_type. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidoptional
statusquerystringoptional
lien_typequerystringoptional
limitqueryintegeroptional
offsetqueryintegeroptional

Responses

  • 200Tax liensTaxLiensListResponse
    FieldTypeRequiredDescription
    liensarray<TaxLien>required
    totalintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/tax-liensCreate tax lien

Create a tax lien record. Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Request body TaxLienCreateBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
lien_amountnumberrequired
notice_idstring · uuidoptional
lien_typestringoptional
lien_numberstringoptional
filing_datestringoptional
filing_jurisdictionstringoptional
tax_periodsarray<string>optional
tax_typestringoptional
response_deadlinestringoptional
release_conditionsstringoptional
agencystringoptional

Responses

  • 201Tax lien createdTaxLienCreateResponse
    FieldTypeRequiredDescription
    lienTaxLienrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Entity not found in caller's tenantMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

WageHour2

GET/api/wage-hourList W&H investigations

List Wage & Hour investigations (compliance category #5 — DOL). Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidoptional
statusquerystringoptional
investigation_typequerystringoptional
limitqueryintegeroptional
offsetqueryintegeroptional

Responses

  • 200InvestigationsWageHourListResponse
    FieldTypeRequiredDescription
    investigationsarray<WageHourInvestigation>required
    totalintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/wage-hourCreate W&H investigation

Create a Wage & Hour investigation record. Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Request body WageHourCreateBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
investigation_typestringrequired
notice_idstring · uuidoptional
investigation_numberstringoptional
complaint_typestringoptional
investigation_scopestringoptional
back_wages_owednumberoptional
penalty_amountnumberoptional
workers_affectedintegeroptional
classification_issuestringoptional
misclassified_countintegeroptional
overtime_hours_owednumberoptional
overtime_ratenumberoptional
notice_datestringoptional
response_deadlinestringoptional
hearing_datestringoptional
investigator_namestringoptional
agencystringoptional

Responses

  • 201Investigation createdWageHourCreateResponse
    FieldTypeRequiredDescription
    investigationWageHourInvestigationrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Entity not found in caller's tenantMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse

WorkersComp6

GET/api/workers-compList W/C policies

List workers' comp policies for the caller's tenant (compliance category #3). Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidoptional
statusquerystringoptional
limitqueryintegeroptional
offsetqueryintegeroptional

Responses

  • 200PoliciesWorkersCompPoliciesListResponse
    FieldTypeRequiredDescription
    policiesarray<WorkersCompPolicy>required
    totalintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/workers-compCreate W/C policy

Create a workers' comp policy. Bearer keys gate via `notices.write`.

Bearer scopesnotices.write

Request body WorkersCompPolicyCreateBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
policy_numberstringrequired
carrierstringrequired
statestringrequired
e_modnumberoptional
annual_premiumnumberoptional
statusstringoptional
effective_datestringoptional
expiration_datestringoptional

Responses

  • 201Policy createdWorkersCompPolicyCreateResponse
    FieldTypeRequiredDescription
    policyWorkersCompPolicyrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Entity not found in caller's tenantMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
GET/api/workers-comp/auditsList W/C audits

List workers' comp audits for the caller's tenant. Each row carries an inlined dispute recommendation when both original_premium and audited_premium are present. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Parameters

NameInTypeRequiredDescription
entity_idquerystring · uuidoptional
statusquerystringoptional
limitqueryintegeroptional
offsetqueryintegeroptional

Responses

  • 200AuditsWorkersCompAuditsListResponse
    FieldTypeRequiredDescription
    auditsarray<WorkersCompAudit>required
    totalintegerrequired
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/workers-comp/auditsCreate W/C audit

Create a workers' comp audit record. Bearer keys gate via `notices.write`. Cookie sessions go through the Stripe subscription gate; Bearer keys bypass.

Bearer scopesnotices.write

Request body WorkersCompAuditCreateBodyrequired

FieldTypeRequiredDescription
entity_idstring · uuidrequired
policy_idstring · uuidoptional
notice_idstring · uuidoptional
audit_typestringoptional
period_startstringoptional
period_endstringoptional
original_premiumnumberoptional
audited_premiumnumberoptional
deadlinestringoptional

Responses

  • 201Audit createdWorkersCompAuditCreateResponse
    FieldTypeRequiredDescription
    auditWorkersCompAuditrequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 402Subscription required (cookie-session callers only)MiscUnauthorizedResponse
  • 404Entity not found in caller's tenantMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/workers-comp/calculate-emodCalculate W/C e-mod

Stateless e-mod (experience modifier) calculator for workers' comp. No tenant data is read or written. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Request body WorkersCompEmodBodyrequired

FieldTypeRequiredDescription
actualLossesnumberrequired
expectedLossesnumberrequired
credibilityWeightnumberoptional
ballastValuenumberoptional

Responses

  • 200e-mod calculationWorkersCompEmodResponse
    FieldTypeRequiredDescription
    eModnumberrequired
    discountnumberoptional
    surchargenumberoptional
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
POST/api/workers-comp/calculate-premiumCalculate W/C premium

Stateless workers' comp premium calculator. Bearer keys gate via `notices.read`.

Bearer scopesnotices.read

Request body WorkersCompPremiumBodyrequired

FieldTypeRequiredDescription
classCodesarray<WorkersCompPremiumClassCode>required
eModnumberoptional

Responses

  • 200Premium calculationWorkersCompPremiumResponse
    FieldTypeRequiredDescription
    manualPremiumnumberrequired
    finalPremiumnumberrequired
    breakdownarray<object>required
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse

Workflows4

GET/api/workflowsList workflow rules

List workflow rules for the caller's tenant.

Bearer scopesnotices.read

Responses

  • 200RulesWorkflowRulesListResponse
    FieldTypeRequiredDescription
    rulesarray<WorkflowRule>required
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
POST/api/workflowsCreate workflow rule

Create a workflow rule. Trigger must be one of `notice.created`, `notice.deadline_approaching`, `notice.status_changed`, or `document.uploaded`.

Bearer scopesnotices.write

Request body WorkflowRuleCreateBodyrequired

FieldTypeRequiredDescription
namestringrequired
triggerenum: "notice.created" | "notice.deadline_approaching" | "notice.status_changed" | "document.uploaded"required
conditionsarray<WorkflowCondition>optional
actionsarray<WorkflowAction>optional

Responses

  • 201Rule createdWorkflowRuleResponse
    FieldTypeRequiredDescription
    ruleWorkflowRulerequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
PATCH/api/workflows/{id}Update workflow rule

Update a workflow rule (toggle is_active, edit fields).

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredWorkflow rule UUID

Request body WorkflowRuleUpdateBodyrequired

FieldTypeRequiredDescription
namestringoptional
triggerenum: "notice.created" | "notice.deadline_approaching" | "notice.status_changed" | "document.uploaded"optional
conditionsarray<WorkflowCondition>optional
actionsarray<WorkflowAction>optional
is_activebooleanoptional

Responses

  • 200Rule updatedWorkflowRuleResponse
    FieldTypeRequiredDescription
    ruleWorkflowRulerequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Rule not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse
DELETE/api/workflows/{id}Delete workflow rule

Delete a workflow rule.

Bearer scopesnotices.write

Parameters

NameInTypeRequiredDescription
idpathstring · uuidrequiredWorkflow rule UUID

Responses

  • 200Rule deletedobject
    FieldTypeRequiredDescription
    successenum: truerequired
  • 400Validation errorMiscValidationErrorResponse
  • 401UnauthorizedMiscUnauthorizedResponse
  • 404Rule not foundMiscNotFoundResponse
  • 429Rate limit exceededMiscRateLimitResponse
  • 500Server errorMiscUnauthorizedResponse