Service Health

Standard gRPC health checking protocol (grpc.health.v1). Health check endpoints are unauthenticated to allow ALB and Kubernetes probes. The aggregated endpoint reports healthy only when all backend services are up.

Check Unary

Synchronous health check. Returns the current health status of a service or the overall server. Used by AWS ALB health checks, Kubernetes liveness/readiness probes, and Envoy health checking.

Leave service empty to check overall server health, or specify a service name like com.symmetry.datagrpc.IngestionService

No auth required

              
Watch Server Stream

Streaming health status. The server immediately sends the current status, then sends updates whenever the health status changes. Used by service mesh sidecars for long-lived health monitoring.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -plaintext \
  -d '{"service": ""}' \
  api.symmetryfiling.com:443 \
  grpc.health.v1.Health/Watch

Service AgencyCatalogService

GetAgency Unary

---- Identity reads --------------------------------------------------------


              
GetAgencyByCmsKey Unary

              
ListAgencies Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListAgencies
GetAgencyOverlay Unary

---- Assembled overlay read ------------------------------------------------ Returns the agency plus its filings (with form children), deposits, and enrollments in one call.


              
ListAgencyFilings Server Stream

---- Overlay component reads ----------------------------------------------

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListAgencyFilings
ListAgencyDeposits Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListAgencyDeposits
ListAgencyEnrollments Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListAgencyEnrollments
ListTaxAgencyBankInfos Server Stream

---- Agency receiving-bank coordinates ------------------------------------- The account a deposit is paid TO. Shared, non-tenant reference data: every tenant filing in a jurisdiction credits the same agency account (the paying side -- BankAccount + ACHConfiguration -- is tenant-scoped and encrypted). Keyed by deposit_key (migration 030), matching AgencyDeposit above. The old (jurisdiction, form_type) pair could not express an agency running more than one receiving account -- a state's withholding and unemployment accounts matched it equally -- and DepositNachaAssembler broke the tie by taking whichever row it walked first, which routes a payment to an arbitrary agency account in a file that is well-formed and whose control totals foot. Get/Delete accept EITHER key: deposit_key when set, else the legacy pair, so a caller holding only the old pair can still reach a row that predates the key.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListTaxAgencyBankInfos
GetTaxAgencyBankInfo Unary

              

Service EntitySearchService

SearchStream Server Stream

Streaming variant for large result sets

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/SearchStream
GetSearchableEntities Unary

Get list of searchable entity types and their fields Useful for UI autocomplete and discovering available search options


              

Service EntityTableService

CreateAddress Unary

--------------------------------------------------------------------------- Address Operations ---------------------------------------------------------------------------


              
GetAddress Unary

              
UpdateAddress Unary

              
DeleteAddress Unary

              
RestoreAddress Unary

Restore soft-deleted Address


              
ListAddresses Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListAddresses
CreateCompany Unary

--------------------------------------------------------------------------- Company Operations ---------------------------------------------------------------------------


              
GetCompany Unary

              
UpdateCompany Unary

              
DeleteCompany Unary

              
RestoreCompany Unary

Restore soft-deleted Company


              
ListCompanies Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListCompanies
CreateCompanyPrimaryAddress Unary

Company Address Operations - creates address AND links to company atomically


              
CreateEmployee Unary

--------------------------------------------------------------------------- Employee Operations ---------------------------------------------------------------------------


              
GetEmployee Unary

              
UpdateEmployee Unary

              
DeleteEmployee Unary

              
RestoreEmployee Unary

Restore soft-deleted Employee


              
ListEmployees Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListEmployees
CreateEmployeeHomeAddress Unary

Employee Address Operations - creates address AND links to employee atomically


              
CreateEmployeeMailingAddress Unary

              
CreateEmployment Unary

--------------------------------------------------------------------------- Employment Operations ---------------------------------------------------------------------------


              
GetEmployment Unary

              
UpdateEmployment Unary

              
DeleteEmployment Unary

              
RestoreEmployment Unary

Restore soft-deleted Employment


              
ListEmployments Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListEmployments
CreateWorksiteLocation Unary

--------------------------------------------------------------------------- WorksiteLocation Operations ---------------------------------------------------------------------------


              
GetWorksiteLocation Unary

              
UpdateWorksiteLocation Unary

              
DeleteWorksiteLocation Unary

              
RestoreWorksiteLocation Unary

Restore soft-deleted WorksiteLocation


              
ListWorksiteLocations Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListWorksiteLocations
CreatePeo Unary

--------------------------------------------------------------------------- PEO (Professional Employer Organization) Operations ---------------------------------------------------------------------------


              
GetPeo Unary

              
UpdatePeo Unary

              
DeletePeo Unary

              
RestorePeo Unary

Restore soft-deleted PEO


              
ListPeos Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListPeos
CreatePeoPrimaryAddress Unary

PEO Address Operations - creates address AND links to PEO atomically


              
CreateServiceProvider Unary

--------------------------------------------------------------------------- ServiceProvider Operations ---------------------------------------------------------------------------


              
GetServiceProvider Unary

              
UpdateServiceProvider Unary

              
DeleteServiceProvider Unary

              
RestoreServiceProvider Unary

Restore soft-deleted ServiceProvider


              
ListServiceProviders Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListServiceProviders
CreateServiceProviderPrimaryAddress Unary

ServiceProvider Address Operations - creates address AND links to ServiceProvider atomically


              
CreatePreparer Unary

--------------------------------------------------------------------------- Preparer Operations ---------------------------------------------------------------------------


              
GetPreparer Unary

              
UpdatePreparer Unary

              
DeletePreparer Unary

              
RestorePreparer Unary

Restore soft-deleted Preparer


              
ListPreparers Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListPreparers
CreateBankAccount Unary

--------------------------------------------------------------------------- BankAccount Operations ---------------------------------------------------------------------------


              
GetBankAccount Unary

              
UpdateBankAccount Unary

              
DeleteBankAccount Unary

              
RestoreBankAccount Unary

Restore soft-deleted BankAccount


              
ListBankAccounts Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListBankAccounts
CreateACHConfiguration Unary

--------------------------------------------------------------------------- ACHConfiguration Operations ---------------------------------------------------------------------------


              
GetACHConfiguration Unary

              
UpdateACHConfiguration Unary

              
DeleteACHConfiguration Unary

              
RestoreACHConfiguration Unary

Restore soft-deleted ACHConfiguration


              
ListACHConfigurations Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListACHConfigurations
CreateStateTaxAccount Unary

--------------------------------------------------------------------------- StateTaxAccount Operations (PAF-1420) --------------------------------------------------------------------------- StateTaxAccount uses block-level encryption: account_number is hashed (HMAC-SHA256) for lookup, plaintext lives in encrypted_data_block. ste_tax_code is the canonical FK to libs/reference-data-models TaxDef.uniqueTaxId; tax_type / status are open CMS-vocabulary strings.


              
GetStateTaxAccount Unary

              
UpdateStateTaxAccount Unary

              
DeleteStateTaxAccount Unary

              
RestoreStateTaxAccount Unary

Restore soft-deleted StateTaxAccount


              
ListStateTaxAccounts Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListStateTaxAccounts
CreateAgencyData Unary

--------------------------------------------------------------------------- AgencyData operations (tenant-scoped agency-assigned field values) --------------------------------------------------------------------------- EAV store: one row per (owner, agency, field) value. ListAgencyData with owner_type + owner_id returns the per-owner collection. No PII / encryption.


              
GetAgencyData Unary

              
UpdateAgencyData Unary

              
DeleteAgencyData Unary

              
RestoreAgencyData Unary

Restore soft-deleted AgencyData


              
ListAgencyData Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListAgencyData
ListCompanyContacts Server Stream

---- Reporting agent authorizations (Form 8655) ---------------------------- READ ONLY on this service. The table is append-only: a new grant, a revocation and a restatement are all APPENDS, and they go through data-grpc's IngestReportingAgentAuthorization like any other ingested record. Offering Update/Delete here would imply an in-place edit that must never happen -- authority has to stay evaluable as of the signing date of a return filed while it was in force. ---- Company contacts ------------------------------------------------------ READ ONLY. Writes go through data-grpc's IngestCompanyContact and the ingestion pipeline's dual-write. List/Get return the MASKED contact: the name, email and phone columns hold HMAC-SHA256 hashes, so they are omitted rather than returned -- a hash rendered where a name is expected reads as corrupt data. GetCompanyContactDecrypted is the only path carrying plaintext and requires an audit context.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListCompanyContacts
GetCompanyContact Unary

              
GetCompanyContactDecrypted Unary

              
ListReportingAgentAuthorizations Server Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListReportingAgentAuthorizations
GetReportingAgentAuthorization Unary

              
GetAddressDecrypted Unary

              
GetCompanyDecrypted Unary

              
GetEmployeeDecrypted Unary

              
GetEmploymentDecrypted Unary

              
GetWorksiteLocationDecrypted Unary

              
GetPeoDecrypted Unary

              
GetServiceProviderDecrypted Unary

              
GetPreparerDecrypted Unary

              
GetBankAccountDecrypted Unary

              
GetACHConfigurationDecrypted Unary

              
GetStateTaxAccountDecrypted Unary

              
BatchCreateEntities Client Stream

--------------------------------------------------------------------------- Batch Operations (Client Streaming) ---------------------------------------------------------------------------

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/BatchCreateEntities
BatchUpdateEntities Client Stream
This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/BatchUpdateEntities
SearchCompanies Unary

              
SearchEmployees Unary

              
SearchEmployments Unary

              
SearchAddresses Unary

              
SearchWorksiteLocations Unary

              
SearchPeos Unary

              
SearchServiceProviders Unary

              
SearchPreparers Unary

              
SearchBankAccounts Unary

              
SearchACHConfigurations Unary

              
SearchStateTaxAccounts Unary

              

Service PiiAccessAuditService

ListPiiAccessAudit Unary

List PII access audit records for a tenant


              

Service SyncTrackingService

GetSyncTracking Unary

Get the latest sync tracking record for an entity If entity_type is UNSPECIFIED, looks up by entity_id only


              
ListSyncTracking Unary

List sync tracking history for an entity (ordered by tracking_id DESC)


              
ListSyncTrackingByCompany Unary

List sync tracking for all entities under a company (for SP/PEO multi-company views)


              
ListPendingSyncTracking Unary

List all pending sync records for a tenant (for monitoring)


              
ListFailedSyncTracking Unary

List all failed sync records for a tenant (for error analysis)


              

Service FilingJobService

---- Reads -----------------------------------------------------------------

ListFilingRuns Unary

Runs grouped by period_label with rollup counts + status breakdown, aggregated across tenants.


              
GetFilingRun Unary

Per-company rows for a single run (amounts, counts, status, approval stamps).


              
ListFilingJobs Server Stream

Flat job query across runs; period_label is the primary scope, the rest are optional filters.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListFilingJobs
ApproveFilingRun Unary

Move every PENDING_REVIEW job in the run to APPROVED, skipping ON_HOLD / EXCLUDED. Stamps approved_at/approved_by and writes history per job.


              
RejectFilingRun Unary

Run-level No-Go: move every PENDING_REVIEW job in the run to ON_HOLD (reversible; filing obligation stays OPEN), skipping APPROVED / ON_HOLD / EXCLUDED. Writes history per job. Like HoldCompany, a review-queue hold has no generation effect, so this does NOT emit Iceberg transitions.


              
ApproveCompany Unary

Per-company Go: PENDING_REVIEW -> APPROVED.


              
HoldCompany Unary

PENDING_REVIEW -> ON_HOLD (reversible; filing obligation stays OPEN).


              
ReleaseCompany Unary

ON_HOLD -> PENDING_REVIEW.


              
ExcludeCompany Unary

PENDING_REVIEW / ON_HOLD -> EXCLUDED. reason_code is REQUIRED; obligation becomes CLOSED for the run.


              
ReincludeCompany Unary

EXCLUDED -> PENDING_REVIEW (explicit, audited reversal).


              
RecallApproval Unary

APPROVED -> PENDING_REVIEW, allowed only while the job is not yet claimed (not PROCESSING).


              
ExcludeRecords Unary

Insert run-scoped record exclusions (does NOT change job status; the company still generates, minus the excluded records).


              
ListRecordExclusions Server Stream

Read active record exclusions for a run (optionally one company).

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/ListRecordExclusions
RemoveRecordExclusion Unary

Soft un-exclude (active = false).


              

Service IngestionService

High-level API for typed data ingestion. Accepts raw payroll data (employees, companies, tax liabilities, etc.) and streams them to Kinesis for processing. Unary methods are accessible via REST/JSON, streaming methods are gRPC-only.

IngestEmployees Bidirectional Stream

Stream employee records for bulk ingestion. Accepts a client stream of employee records and returns an aggregate response with success/failure counts.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestEmployees
IngestCompanies Bidirectional Stream

Stream company records for bulk ingestion. Accepts a client stream of company records and returns an aggregate response.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestCompanies
IngestTaxLiabilities Bidirectional Stream

Stream tax liability records for bulk ingestion. Accepts a client stream of liability records and returns an aggregate response.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestTaxLiabilities
IngestAppliedBenefits Bidirectional Stream

Stream applied-benefit records for bulk ingestion (PAF-1820). One record per (employee, pay_date, jurisdiction, wage_type, benefit_category) — the producer sums its own individual benefits into a category before sending, because the natural key excludes the reference code and two rows sharing a category would otherwise collapse under latest-wins.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestAppliedBenefits
IngestEmployments Bidirectional Stream

Stream employment relationship records for bulk ingestion.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestEmployments
IngestBankAccounts Bidirectional Stream

Stream bank account records for bulk ingestion.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestBankAccounts
IngestPreparers Bidirectional Stream

Stream tax preparer records for bulk ingestion.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestPreparers
IngestStateTaxAccounts Bidirectional Stream

Stream state tax account records for bulk ingestion.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestStateTaxAccounts
IngestCompanyTaxProfiles Bidirectional Stream

Stream company tax profile records for bulk ingestion (PAF-1616, append-only).

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestCompanyTaxProfiles
IngestTenantScheduleConfigs Bidirectional Stream

Stream tenant schedule config records for bulk ingestion (PAF-1921, append-only).

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestTenantScheduleConfigs
IngestTaxExemptions Bidirectional Stream

Stream tax exemption records for bulk ingestion (PAF-1616, append-only).

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestTaxExemptions
IngestTaxCorrections Bidirectional Stream

Stream correction declarations — a producer stating that liabilities restate a FILED period. Append-only; correlated to tax_liability by a composite natural key on scope, never a foreign key, so a declaration may arrive before, after, or without its rows.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestTaxCorrections
IngestReportingAgentAuthorizations Bidirectional Stream

Stream Form 8655 authority grants. Append-only: a revocation is a new version carrying revoked_at, never a delete, because authority must stay evaluable as of the signing date of a return filed while it was in force.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestReportingAgentAuthorizations
IngestTaxDeposits Bidirectional Stream

Stream deposits made against a tax obligation, by us or by the client (PAF-1765). Append-only and origination-agnostic; a settlement confirmation arrives as a NEW ROW reusing deposit_id with an advanced status, never as an update.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestTaxDeposits
IngestAgencyCredits Bidirectional Stream

Stream the AGENCY's own statements about a filer's credits (PAF-1913). The third corner of the reconciliation: tax_liability is our computation, tax_deposit is the client's assertion, and this is what the agency says it holds. Append-only; a restatement reuses credit_id with a later stated_at. Replaces DepositAdjustment, which never had a producer.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestAgencyCredits
IngestPaymentApplications Bidirectional Stream

Stream the agency's allocations of deposits (PAF-1913). The other half of the third corner: AgencyCredit is money the agency HOLDS, this is money it APPLIED. One deposit fans out to many of these, which is why it cannot be a field on TaxDeposit. Append-only; a re-allocation reuses application_id with a later stated_at.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestPaymentApplications
IngestCompanyContacts Bidirectional Stream

Stream company contact records for bulk ingestion (PAF-1606, Iceberg-only).

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestCompanyContacts
IngestEmployeeTaxProfiles Bidirectional Stream

Stream employee tax profile records for bulk ingestion (PAF-1606, Iceberg-only).

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestEmployeeTaxProfiles
IngestEmployeeTaxExemptions Bidirectional Stream

Stream employee tax exemption records for bulk ingestion (PAF-1606, Iceberg-only).

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestEmployeeTaxExemptions
IngestPEOs Bidirectional Stream

Stream PEO (Professional Employer Organization) records for bulk ingestion.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestPEOs
IngestServiceProviders Bidirectional Stream

Stream service provider records for bulk ingestion.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestServiceProviders
IngestAddresses Bidirectional Stream

Stream address records for bulk ingestion.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestAddresses
IngestWorksiteLocations Bidirectional Stream

Stream worksite location records for bulk ingestion.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestWorksiteLocations
IngestAchConfigurations Bidirectional Stream

Stream ACH configuration records for bulk ingestion.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestAchConfigurations
IngestAgencyDatas Bidirectional Stream

Stream agency-data records (agency-assigned EAV field values) for bulk ingestion. No PII. owner_id is expected to be the server-issued UUID7 (the batch client resolves owner_external_id -> owner_id before staging, same as bank_accounts/preparers); a non-UUID7 owner_id is logged but not rejected.

This is a streaming method. Use grpcurl or a native gRPC client to test it.
grpcurl -H "Authorization: Bearer $TOKEN" \
  -d '{ }' \
  api.symmetryfiling.com:443 \
  com.symmetry.datagrpc.IngestionService/IngestAgencyDatas
IngestBatch Unary

Ingest a batch of mixed record types in a single request. Supports multiple entity types: employees, companies, tax liabilities, etc.


              
IngestEmployee Unary

Ingest a single employee record with PII data (SSN, name, DOB, addresses).


              
IngestCompany Unary

Ingest a single company record with EIN and legal entity details.


              
IngestPayCalcSubmission Unary

Ingest a single PayCalc submission: one tax-calculation API call covering N employees. This is the protection boundary for exported calculations. The submission arrives with plaintext payloads and leaves as a protected envelope on the PayCalc stream, plus derived tax liabilities on the entity ingestion path. It is the only place payload plaintext meets key material — the producer holds plaintext without keys, and everything downstream holds protection's output without plaintext. Unlike the entity RPCs this one performs derivation as well as protection, because deriving tax liabilities requires reading the payload. Doing it anywhere downstream would mean shipping plaintext past this point, which is the thing the design exists to prevent. Unary only, deliberately: a submission is already a batch of N employees, so client-streaming would batch batches for no benefit while making partial failure harder to report.


              
IngestPreparer Unary

Ingest a single tax preparer record.


              
IngestBankAccount Unary

Ingest a single bank account record with routing and account numbers.


              
IngestEmployment Unary

Ingest a single employment relationship record.


              
IngestPEO Unary

Ingest a single PEO (Professional Employer Organization) record.


              
IngestServiceProvider Unary

Ingest a single service provider record.


              
IngestStateTaxAccount Unary

Ingest a single state tax account record.


              
IngestTaxCorrection Unary

Ingest a single correction declaration (append-only).


              
IngestReportingAgentAuthorization Unary

Ingest a single Form 8655 authority grant (append-only). One call per GRANTED FORM -- line 15 grants per-form start periods, so one signed instrument yields several of these.


              
IngestAgencyCredit Unary

Ingest a single agency credit statement (append-only). The REST/portal door — a person reading an agency notice keys it here; batch uses IngestAgencyCredits.


              
IngestPaymentApplication Unary

Ingest a single payment application (append-only). How the agency allocated one deposit to one (period, tax); batch uses IngestPaymentApplications.


              
IngestTaxDeposit Unary

Ingest a single deposit (append-only). The REST/dev-UI door; batch uses IngestTaxDeposits.


              
IngestCompanyTaxProfile Unary

Ingest a single company tax profile record (PAF-1616, append-only).


              
IngestTenantScheduleConfig Unary

Ingest a single tenant schedule config record (PAF-1921, append-only).


              
IngestTaxExemption Unary

Ingest a single tax exemption record (PAF-1616, append-only).


              
IngestCompanyContact Unary

Ingest a single company contact record (PAF-1606, Iceberg-only).


              
IngestEmployeeTaxProfile Unary

Ingest a single employee tax profile record (PAF-1606, Iceberg-only).


              
IngestEmployeeTaxExemption Unary

Ingest a single employee tax exemption record (PAF-1606, Iceberg-only).


              
IngestAddress Unary

              
IngestWorksiteLocation Unary

Ingest a single worksite location record.


              
IngestAchConfiguration Unary

Ingest a single ACH configuration record.


              
IngestAgencyData Unary

Ingest a single agency-data record (agency-assigned field value). No PII.


              
IngestFilingJobTransition Unary

Ingest a single filing-job lifecycle transition (scheduler merge). No PII. Append-only event; entity-grpc owns the local-first PG overlay write, this forwards the event to the data lake (Kinesis -> ingestion-stream -> Iceberg).


              
InsertTaxLiability Unary

Insert a single tax liability record. Tax liabilities are insert-only (immutable) - use this for payroll-generated tax obligations.


              
InsertAppliedBenefit Unary

Insert a single applied-benefit record. Append-only, like tax liabilities.


              
DeleteRecord Unary

Delete a record by entity type and ID. Creates a tombstone record in Iceberg for soft delete semantics.


              

Service ReportingQueryService

======================================================================================= ReportingQueryService — interactive, row-capped, synchronous. ======================================================================================= Bounded by MAX_INTERACTIVE_ROWS and by the workgroup's bytes-scanned cutoff. Anything larger needs narrowing by the caller. A result that hits the cap sets QueryResult.truncated silently returning a prefix, because a truncated reconciliation is not a smaller answer — it is a different one.

ListReportTemplates Unary

              
DescribeReportTemplate Unary

              
RunReport Unary

Surface 1: named, parameterised templates. The server owns the SQL.


              

Messages

HealthCheckRequest

Request message for health check operations.

Field Type Label Description
service string optional Service name to check. Empty string checks overall server health.
HealthCheckResponse

Response message containing health status.

Field Type Label Description
status ServingStatus required Current health status of the service.
ChangeMetadata

Client-provided change metadata for create/update requests Clients must provide this to track the origin of changes

Field Type Label Description
source ChangeSource Where the change originated
source_id string Client-generated correlation/request ID
actor_id string User or service account making the change
SyncTracking

Polymorphic sync tracking for any entity type One record per entity, tracks sync state across PostgreSQL/Flink/Iceberg

Field Type Label Description
tracking_id string Primary key (UUID)
tenant_id string Partition key
entity_type EntityType Polymorphic reference to any entity Type of entity being tracked
entity_id string FK to the actual entity
status SyncStatus Sync state Current sync status
error string Error message if FAILED
version int64 Optimistic locking version
synced_at google.protobuf.Timestamp When Flink confirmed/failed
source ChangeSource Change origin tracking Where the change originated
source_id string Correlation ID (request ID, job ID)
actor_id string User ID or service account
created_at google.protobuf.Timestamp Timestamps
updated_at google.protobuf.Timestamp
company_id string Company scope (for SP/PEO multi-company queries) NULL for SP/PEO-level entities; entity_id for COMPANY; company_id from entity for others
ACHConfiguration

ACH configuration for NACHA file generation

Field Type Label Description
ach_config_id string Primary key
tenant_id string
owner_id string
owner_type OwnerType
immediate_destination string NACHA file header fields Receiving bank routing (9 digits)
immediate_origin string Originating bank routing (9 digits)
company_name string Max 23 chars
company_identification string Tax ID (10 chars)
company_entry_description string Max 10 chars (e.g., "TAX PYMT")
company_discretionary_data string Max 20 chars (optional)
service_class_code ServiceClassCode 200=Mixed, 220=Credits, 225=Debits
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Optional sync tracking - populated by entity-grpc for API responses
Address

Address entity with block-level encryption and vector embedding support Two-layer access pattern: 1. Hash Layer: One-way hashes (street_line_1, street_line_2) for exact match queries 2. Encryption Layer: Actual sensitive values stored in encrypted_data_block (Base64-encoded JSON) Vector embeddings for fuzzy search are stored separately in PostgreSQL address_embeddings table. Fields marked with (embeddable) = true indicate which values are used to generate embeddings. Example encrypted_data_block content: {"street_line_1": "123 Main Street", "street_line_2": "Apt 4"}

Field Type Label Description
address_id string Primary key (UUID7, server-generated)
tenant_id string Partition key
street_line_1 string PII - stores one-way hash for exact queries; actual value in encrypted_data_block Marked for encryption and embedding in vector search
street_line_2 string
city string Geographic metadata - plaintext for analytics and tax jurisdiction determination Marked for embedding to support fuzzy address matching
state string Two-letter state code (e.g., "CA", "NY")
zip_code string 5 or 9 digit ZIP
country string Default 'USA'
address_type AddressType Address type classification BUSINESS, RESIDENTIAL, MAILING
validated bool Validation USPS address validation
validated_at google.protobuf.Timestamp
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
encrypted_data_block string Block-level encryption with session-based KMS Contains Base64-encoded encrypted JSON map of sensitive field values Format: {"street_line_1": "actual value", "street_line_2": "actual value"}
kms_session_id string Encrypted session ID for AWS KMS encryption/decryption Provides block-level isolation and tenant-specific security
sync com.symmetry.models.sync.SyncTracking optional Optional sync tracking - populated by entity-grpc for API responses
external_id string optional ── Client Reference ───────────────────────────────────────────────────────
source_company_id string optional
county_code string Geographic metadata for local tax jurisdiction resolution
county_name string
Agency

Tax agency entity (IRS, state departments, etc.) Identity is a Symmetry-minted, immutable `symmetry_uuid` (never rekeyed). `key` carries the payroll-CMS key ("AK - DOLWD") and is the unique association + refresh-match anchor back to ReferenceData.agency(key).

Field Type Label Description
key string payroll-CMS key (e.g., "AK - DOLWD"); unique association anchor (DB column cms_key)
name string Full agency name (e.g., "Department of Labor & Workforce Development")
short_name string Abbreviated name (e.g., "DOLWD")
state string State code (e.g., "AK") - empty for federal agencies
jurisdiction_type JurisdictionType FEDERAL, STATE, LOCAL, COUNTY
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
symmetry_uuid string ── Canonical identity + provenance (catalog) ─────────────────────────────── Minted canonical PK - immutable, never rekeyed
cms_uuid string payroll-CMS uuid - tracked attribute only, not identity (nullable)
provenance Provenance CMS | SYMMETRY | CMS+overlay
valid_from google.protobuf.Timestamp Effective-dating (merge-job written)
valid_to google.protobuf.Timestamp
AgencyData

Agency-specific data for employees, companies, and preparers Stores agency-specific field values that are required for certain tax filings. For example, Alaska requires a Geographic Code for employees. This is a separate entity (not embedded in Employee/Company/Preparer) to: 1. Allow independent lifecycle management 2. Support querying all agency data for a given owner 3. Avoid bloating parent entity messages

Field Type Label Description
agency_data_id string Primary key (UUID7, server-generated)
tenant_id string Partition key
owner_type OwnerType EMPLOYEE, COMPANY, PREPARER
owner_id string FK to employee_id, company_id, or preparer_id
agency_id string Agency identifier (e.g., "AK-DOLWD", "CA-EDD")
u_id string Symmetry unique identifier for this field type
field_name string Field name (e.g., "AK_GEO_CODE", "CA_SUI_RATE")
value string ENCRYPTED (PAF-1794) — hash here for exact-match lookup, plaintext in encrypted_data_block. Some agency values are secrets (the Reporting Agent PIN signs on the taxpayer's behalf) and a proto annotation cannot be per-row, so the column is encrypted for every row. Readers use a CARRY_FORWARD_PII reference; nothing resolves this column directly. Value assigned to this field for this owner
state_code string State code (may be derived from agency_id)
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Optional sync tracking - populated by entity-grpc for API responses
encrypted_data_block string Block-level encryption (same pattern as StateTaxAccount / BankAccount / Company). Required by the encryption mechanism, not an alternative value column: without these two fields PiiEncryptionService hashes `value` and has nowhere to put the plaintext, which DESTROYS it.
kms_session_id string
AgencyDeposit

Per-agency deposit overlay - from pufferfish DepositAkaAgent. No DepositDef exists in reference-data, so this is the deposit content type. ACH receiver routing is NOT duplicated here - it stays in TaxAgencyBankInfo.

Field Type Label Description
agency_deposit_id string Primary key (UUID)
agency_uuid string FK -> Agency.symmetry_uuid
deposit_key string ReferenceData::DepositKey
pay_to string Payee name
group_confirmation_code_required bool
payment_allocation_file_required bool
workflow_supported_deposit bool Capability
automated_workflow_supported_deposit bool Capability
amount_must_match_filing bool
only_deposit_whole_dollars bool
default_deposit_configuration DepositConfiguration JSONB column
other_deposit_configurations DepositConfiguration repeated JSONB column
check_address_override CheckAddressOverride JSONB column (nullable)
tax_coupon_form_name string TaxCouponAkaFormName (nullable)
provenance Provenance
valid_from google.protobuf.Timestamp
valid_to google.protobuf.Timestamp
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
AgencyEnrollment

Per-agency enrollment overlay - from pufferfish EnrollmentAkaFormName. POA / e-file-authorization / ACH-registration forms that authorize Gusto to file & pay for a company (the artifacts a StateTaxAccount registration reflects).

Field Type Label Description
agency_enrollment_id string Primary key (UUID)
agency_uuid string FK -> Agency.symmetry_uuid
enrollment_key string
pay_to string Payee name
form_name string
requires_signature bool
requires_transmission bool
provenance Provenance
valid_from google.protobuf.Timestamp
valid_to google.protobuf.Timestamp
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
AgencyFiling

Per-agency filing overlay - from pufferfish FilingAkaFormName.

Field Type Label Description
agency_filing_id string Primary key (UUID)
agency_uuid string FK -> Agency.symmetry_uuid
filing_key string ReferenceData::FilingKey (join to reference-data filings[])
pay_to string Payee name
is_annual_filing bool
workflow_supported_filing bool Capability: is an automated filing workflow available
amendment_only_workflow_supported_filing bool
associated_deposit_keys string repeated ReferenceData::DepositKey[]
provenance Provenance
valid_from google.protobuf.Timestamp
valid_to google.protobuf.Timestamp
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
forms AgencyFilingForm repeated Original + amendment form sub-structs (pufferfish original/amendment Filing).
AgencyFilingForm

Form-level detail for an AgencyFiling (one per ORIGINAL / AMENDMENT variant). Maps to the agency_filing_form table; config blobs are JSONB columns.

Field Type Label Description
agency_filing_form_id string Primary key (UUID)
agency_filing_id string FK -> AgencyFiling.agency_filing_id
variant FilingVariant ORIGINAL | AMENDMENT
form_name string
mt_form_codes string repeated MasterTax form codes
filing_configurations FilingConfiguration Portable config (code-class stripped; agent actions excluded). JSONB column filing_configurations
transmission_configuration TransmissionConfiguration JSONB column transmission_configuration
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
BankAccount

Bank account for ACH transactions

Field Type Label Description
bank_account_id string Primary key (UUID7, server-generated)
tenant_id string
owner_id string Company/PEO/ServiceProvider ID
owner_type OwnerType
routing_number string PII fields (hashes for lookup, actual values in encrypted_data_block) HMAC-SHA256 hash for exact-match lookup
account_number string HMAC-SHA256 hash for exact-match lookup
account_type AccountType Plaintext metadata CHECKING, SAVINGS
originating_dfi_id string First 8 digits of routing number
verified bool Micro-deposit verification status
status AccountStatus ACTIVE, INACTIVE, SUSPENDED
created_at google.protobuf.Timestamp
verified_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Optional sync tracking - populated by entity-grpc for API responses
external_id string optional ── Client Reference ───────────────────────────────────────────────────────
source_company_id string optional
encrypted_data_block string Block-level encryption (same pattern as Employee, Company, Address, etc.) Base64-encoded encrypted JSON containing routing_number, account_number
kms_session_id string
account_holder_name string
CheckAddressOverride

pufferfish deposit check_address_override (payee + mailing address for paper checks).

Field Type Label Description
payee_name string
address_line_1 string
address_line_2 string
city string
state string
zip_code string
Company

Company entity with block-level encryption and fuzzy search support Two-layer access pattern for legal_name: 1. Hash Layer: One-way hash for exact match queries 2. Encryption Layer: Actual value in encrypted_data_block Vector embeddings stored in company_embeddings table for fuzzy name search. Example encrypted_data_block: {"legal_name": "Acme Corporation Inc"}

Field Type Label Description
company_id string Primary key (UUID7, server-generated)
tenant_id string PEO/SP ID or company_id if DIRECT
legal_name string optional Hash of legal name; embeddable for fuzzy search
ein string optional Federal EIN (hashed for lookups)
filing_mode FilingMode DIRECT, PEO_MANAGED, SERVICE_PROVIDER_MANAGED
primary_address_id string optional FK to Address
created_at google.protobuf.Timestamp optional
encrypted_data_block string optional Block-level encryption with session-based KMS
kms_session_id string optional Encrypted session ID for AWS KMS encryption/decryption
sync com.symmetry.models.sync.SyncTracking optional Optional sync tracking - populated by entity-grpc for API responses
external_id string optional ── Client Reference ─────────────────────────────────────────────────────── Client's reference ID for this company (e.g., "COMP-001" in their system) Flink deduplicates on (tenant_id, external_id) and preserves original company_id
deleted_at google.protobuf.Timestamp optional Soft delete timestamp - null/unset means active, set means deleted Consumers should filter on this field if they only want active records
efin string optional IRS filing credentials (entity-level, not individual preparer) Electronic Filing Identification Number
etin string optional Electronic Transmitter Identification Number
taxpayer_type TaxpayerType Tax classification (from companyDetails.taxPayerType)
business_entity_type TaxpayerType
mailing_address_id string optional
phone string
trade_name string optional Trade name / DBA ("doing business as") Hash of trade name; plaintext in encrypted_data_block; embeddable for fuzzy search
CompanyContact

Company contact (payroll admin + signatory). Block-level encryption for PII. Dual-written to PostgreSQL (company_contacts) as well as Iceberg: the encrypted name, email and phone can only be shown through entity-grpc's decrypt path, which reads PostgreSQL and writes a pii_access_audit row. Decrypting elsewhere would bypass that.

Field Type Label Description
company_contact_id string
tenant_id string
company_id string
contact_type ContactType
first_name string
middle_name string
last_name string
suffix string
title string
email string
phone string
external_id string optional
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
encrypted_data_block string
kms_session_id string
DepositConfiguration

pufferfish DepositWorkflow::DepositConfiguration (code class stripped).

Field Type Label Description
deposit_method string Individual/Bulk x Ach/Check/EftDebit
group_criteria string repeated
group_max_size int32
Employee

Employee entity with block-level encryption and fuzzy search support Two-layer access pattern: 1. Hash Layer: One-way hashes for exact match queries 2. Encryption Layer: Actual sensitive values in encrypted_data_block Vector embeddings stored in employee_embeddings table for fuzzy name search. Example encrypted_data_block: {"ssn": "123-45-6789", "first_name": "John", "last_name": "Doe", "date_of_birth": "1990-01-01"}

Field Type Label Description
employee_id string Primary key (UUID7, server-generated)
tenant_id string Partition key
ssn string PII - stores one-way hash for exact queries; actual value in encrypted_data_block. (normalizer) canonicalizes the plaintext (strips hyphens/spaces) before hashing AND before it lands in encrypted_data_block, so a 9- or 11-char input always stores as 9 digits. Hash of SSN for exact lookups
first_name string Hash of first name; embeddable for fuzzy search
last_name string Hash of last name; embeddable for fuzzy search
date_of_birth string Hash of DOB for exact lookups
home_address_id string FK to Address - residential address for tax purposes
mailing_address_id string FK to Address - where to send documents (optional, if different from home)
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
encrypted_data_block string Block-level encryption with session-based KMS Contains Base64-encoded encrypted JSON map of all PII fields
kms_session_id string Encrypted session ID for AWS KMS encryption/decryption
sync com.symmetry.models.sync.SyncTracking optional Optional sync tracking - populated by entity-grpc for API responses
external_id string optional Client's reference ID for this employee (e.g., "EMP-001" in their system)
source_company_id string optional Company that this external_id is scoped to (for PEO/SP tenants with multiple companies) Required if external_id is provided for proper deduplication
middle_name string
suffix string
Employment

Employment relationship

Field Type Label Description
employment_id string Primary key (UUID7, server-generated)
tenant_id string Partition key
employee_id string FK to Employee
company_id string FK to Company
worksite_location_id string FK to Location (if applicable)
hire_date google.protobuf.Timestamp
termination_date google.protobuf.Timestamp Nullable
status EmploymentStatus ACTIVE, TERMINATED, ON_LEAVE
annual_salary_cents int64
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Optional sync tracking - populated by entity-grpc for API responses
external_id string optional ── Client Reference ─────────────────────────────────────────────────────── Client's reference ID for this employment record
source_company_id string optional Company scope for external_id deduplication
FilingConfiguration

pufferfish FilingWorkflow::FilingConfiguration (code class stripped).

Field Type Label Description
filing_method string Delivery channel (paper / e-file / ...) - reference data has no field for this
group_criteria string repeated Run-batching criteria
PEO

PEO (Professional Employer Organization) with block-level encryption Two-layer access pattern for legal_name: 1. Hash Layer: One-way hash for exact match queries 2. Encryption Layer: Actual value in encrypted_data_block Vector embeddings stored in peo_embeddings table for fuzzy name search. Example encrypted_data_block: {"legal_name": "ABC Professional Employer Organization"}

Field Type Label Description
peo_id string Primary key (UUID7, server-generated)
legal_name string Hash of legal name; embeddable for fuzzy search
ein string Federal EIN (plaintext)
primary_address_id string FK to Address
created_at google.protobuf.Timestamp
encrypted_data_block string Block-level encryption with session-based KMS
kms_session_id string Encrypted session ID for AWS KMS encryption/decryption
sync com.symmetry.models.sync.SyncTracking optional Optional sync tracking - populated by entity-grpc for API responses
deleted_at google.protobuf.Timestamp optional Soft delete timestamp - null/unset means active, set means deleted Consumers should filter on this field if they only want active records
external_id string optional ── Client Reference ─────────────────────────────────────────────────────── Client's reference ID for this PEO (e.g., "PEO-001" in their system) Used for deduplication: (external_id) - PEO is a top-level tenant entity
efin string optional IRS filing credentials (entity-level, not individual preparer) Electronic Filing Identification Number
etin string optional Electronic Transmitter Identification Number
Preparer

Tax preparer entity with block-level encryption and fuzzy search support Two-layer access pattern for PII fields: 1. Hash Layer: One-way hashes for exact match queries 2. Encryption Layer: Actual sensitive values in encrypted_data_block Vector embeddings stored in preparer_embeddings table for fuzzy name/firm search. Example encrypted_data_block: {"firm_name": "Smith Tax Services", "first_name": "Jane", "last_name": "Smith", "email": "jane@smithtax.com", "phone": "555-1234"}

Field Type Label Description
preparer_id string Primary key (UUID7, server-generated)
tenant_id string Owner's tenant ID
owner_id string FK to Company/PEO/ServiceProvider
owner_type OwnerType COMPANY, PEO, SERVICE_PROVIDER
firm_name string Hash of firm name; embeddable for fuzzy search
first_name string Hash of first name; embeddable for fuzzy search
last_name string Hash of last name; embeddable for fuzzy search
business_address_id string FK to Address
email string Hash of email for exact lookups
phone string Hash of phone for exact lookups
ptin string Preparer Tax Identification Number (individual credential)
naic_code string North American Industry Classification (plaintext)
preparer_type PreparerType CPA, EA, ATTORNEY, etc.
self_employed bool
status PreparerStatus ACTIVE, INACTIVE, SUSPENDED
created_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
encrypted_data_block string Block-level encryption with session-based KMS Contains all PII fields: firm_name, first_name, last_name, email, phone
kms_session_id string Encrypted session ID for AWS KMS encryption/decryption
sync com.symmetry.models.sync.SyncTracking optional Optional sync tracking - populated by entity-grpc for API responses
external_id string optional ── Client Reference ───────────────────────────────────────────────────────
source_company_id string optional Deliberately NOT wired up (no ingestion field, no repository query) — owner_id above is already the unambiguous scope for external_id on this entity, unlike Employee/Employment (which have no company link of their own and need this to disambiguate). Kept declared rather than removed so a future PEO-fanout redesign has the field if it turns out needed.
title string Free-text role/title used on the signature block of filed forms (e.g. "Owner", "Controller", "Tax Manager"). Distinct from preparer_type, which is the credential classification (CPA/EA/ATTORNEY). Plaintext — not PII.
role string Agent contact slot (officer / tax_return_preparer / technical_contact). Plaintext — not PII.
ReportingAgentAuthorization

============================================================================ REPORTING AGENT AUTHORIZATION (Form 8655) ============================================================================ Answers ONE question: was our signature authority in effect for the period being corrected? Amendments surfaced this first because they are the only case where the corrected period can predate the authorization — Form 8655 is explicit that "No authorization or authority is granted for periods prior to the period(s) indicated on Form 8655", and a 941-X corrects a PAST quarter. So a current client in good standing can still fail this for an old quarter. The question is NOT "is this client ours today". Form 8655 line 15 is headed "Authorization of Reporting Agent To Sign and File Returns", and the authority reaches amendments without a separate filing: "Where authority is granted for any form, it is also effective for related forms such as ... amended return (for example, Form 941 (sp), 941-X, or 941-X (sp))". So an 8655 covering Form 941 covers its 941-X. A REPORTING AGENT IS NOT A SECTION 3504 AGENT. Reporting-agent filings go under the CLIENT's EIN, one return per company, which is by definition not an aggregate return and checks none of the aggregate-filer boxes — see docs/forms/federal/rules/941.md R3. NO CREDENTIAL FIELDS, DELIBERATELY. This record carries dates and form codes only. The five-digit reporting-agent PIN is a SIGNATURE CREDENTIAL issued from the agent's own e-file application (Pub 3112), not from any client's 8655 — one PIN per agent, so storing it per company would be N copies of one secret. It is also 100,000 combinations, with no entropy to fall back on if exposed. Whether we need it at all depends on who transmits to MeF: if the service provider transmits, we hold nothing. If we ever do hold it, it belongs behind BankAccount's hash + encrypted_data_block pattern or a secrets-manager reference keyed by EFIN — never a plaintext column, and never AgencyData (which is a documented no-PII store with a plaintext `value`). Design: docs/forms/federal/design-note-correction-declaration.md D7 (the minimal slice). Form rule: docs/forms/federal/rules/941x.md R10.

Field Type Label Description
authorization_id string Primary key (UUID7, server-generated)
tenant_id string
agent_owner_id string WHO is authorized. owner_id + owner_type mirrors BankAccount because authority is AGENT-scoped: one authorization per (agent, client), and the agent is a ServiceProvider or PEO — not a Company. StateTaxAccount cannot host this: it is company-scoped only, with PEO/tenant ownership deferred (PAF-1624), and state-scoped besides.
agent_owner_type OwnerType SERVICE_PROVIDER | PEO
company_id string WHO it is authorized FOR.
form_code string WHAT, and FROM WHEN — ONE ROW PER GRANTED FORM. Form 8655 line 15 grants PER-FORM start periods: separate entries for 940, 941, 943, 945 and 1042, in "YYYY/MM" for quarterly returns and "YYYY" for annual. So the grain here is (agent, client, form_code) rather than one row per 8655 document. One instrument, several grants, and it is the grants we evaluate. Flat rather than a `repeated AuthorizedForm` sub-message, for the same reason TaxCorrection avoids EncryptedValue: LocalTableCreator's proto-derived schema maps a repeated MESSAGE to a list of opaque BINARY blobs, which the period check could not read. Flattening also makes that check a plain predicate instead of an UNNEST. form_code is the IRS code as printed on the form. The amendment variant is NOT a separate grant — authority for a form reaches its amended return.
effective_from google.protobuf.Timestamp The first period this grant covers. Day-grain, and compared against the CORRECTED period's start, never the filing period's. Nothing before it is authorized.
revoked_at google.protobuf.Timestamp Revocable at any time by either party. Null while in force. Authority must be evaluable AS OF the signing date, so this is a fact on an append-only record rather than a deletion.
filed_with_irs_at google.protobuf.Timestamp Provenance. Note that disclosure authority is effective on taxpayer signature AND IRS receipt, and the 8655 itself goes to the RAF team in Ogden — never attached to a return. Nothing in the filing path can therefore detect its absence, which is why this record exists.
declared_by string
submitted_at google.protobuf.Timestamp latest-wins tiebreaker on restatement
ingested_at google.protobuf.Timestamp server-set from the envelope
source_system_id string
ServiceProvider

Service Provider entity with block-level encryption Two-layer access pattern for legal_name: 1. Hash Layer: One-way hash for exact match queries 2. Encryption Layer: Actual value in encrypted_data_block Vector embeddings stored in service_provider_embeddings table for fuzzy name search. Example encrypted_data_block: {"legal_name": "XYZ Payroll Services LLC"}

Field Type Label Description
service_provider_id string Primary key (UUID7, server-generated)
legal_name string Hash of legal name; embeddable for fuzzy search
ein string Federal EIN (plaintext)
primary_address_id string FK to Address
provider_type ServiceProviderType
files_on_behalf bool True if files on behalf of companies
created_at google.protobuf.Timestamp
encrypted_data_block string Block-level encryption with session-based KMS
kms_session_id string Encrypted session ID for AWS KMS encryption/decryption
sync com.symmetry.models.sync.SyncTracking optional Optional sync tracking - populated by entity-grpc for API responses
deleted_at google.protobuf.Timestamp optional Soft delete timestamp - null/unset means active, set means deleted Consumers should filter on this field if they only want active records
external_id string optional ── Client Reference ─────────────────────────────────────────────────────── Client's reference ID for this ServiceProvider (e.g., "SP-001" in their system) Used for deduplication: (external_id) - ServiceProvider is a top-level tenant entity
efin string optional IRS filing credentials (entity-level, not individual preparer) Electronic Filing Identification Number
etin string optional Electronic Transmitter Identification Number
TaxAgencyBankInfo

Tax agency bank information for NACHA payments -- the agency's RECEIVING account, i.e. who a deposit is paid TO. The employer's PAYING side is BankAccount + ACHConfiguration, which are tenant-scoped and encrypted; this side is shared, because every tenant depositing to a given agency credits the same account. Keyed by `deposit_key`, matching AgencyDeposit -- see the field comment. `jurisdiction` and `form_type` are retained as a coarse fallback for rows that predate the key and for the hydration fan-out, which attributes rows to companies by jurisdiction.

Field Type Label Description
agency_bank_id string Primary key
jurisdiction string "USA", "CA", "NY", etc.
form_type string "941", "940", "DE9", etc.
receiving_dfi_routing string Agency receiving account 9-digit routing number
receiver_account_number string Agency account number
receiver_id_number string Agency tax ID
receiver_name string Agency name (max 22 chars)
addenda_payment_type string Addenda information "941", "940", etc.
status AgencyBankStatus ACTIVE, DEPRECATED
effective_date google.protobuf.Timestamp
deprecated_date google.protobuf.Timestamp
agency_uuid string FK -> Agency.symmetry_uuid
deposit_key string ReferenceData::DepositKey ("AZ - Withholding", "US - 941"). Simultaneously the CMS deposit definition, the TXP addenda record key and the tax scope -- the same key NachaDepositWalker walks and TxpRecordKeyDeriver derives from the filing job, which is why selection can use it directly instead of re-deriving a jurisdiction.
TransmissionConfiguration

pufferfish FilingWorkflow::TransmissionConfiguration. soap_client (a Ruby class) collapses to behavior_key + a flag.

Field Type Label Description
requires_separate_acknowledgement bool
behavior_key string Symmetry executor-registry key (replaces Gusto soap_client class)
WorksiteLocation

Worksite location for employees

Field Type Label Description
location_id string Primary key (UUID7, server-generated)
tenant_id string Partition key
company_id string FK to Company
location_name string Human-readable name (e.g., "San Francisco Office")
address_id string FK to Address
local_jurisdiction_code string Tax jurisdiction information For local taxes (e.g., NYC, SF)
subject_to_local_tax bool
status LocationStatus ACTIVE, CLOSED
created_at google.protobuf.Timestamp
closed_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Optional sync tracking - populated by entity-grpc for API responses
external_id string optional ── Client Reference ─────────────────────────────────────────────────────── Client's reference ID for this worksite location (e.g., "LOC-001" in their system) Used for deduplication: (tenant_id, company_id, external_id)
AgencyOverlay

Assembled agency + overlay graph.

Field Type Label Description
agency com.symmetry.models.tax.Agency
filings com.symmetry.models.tax.AgencyFiling repeated each carries its forms[]
deposits com.symmetry.models.tax.AgencyDeposit repeated
enrollments com.symmetry.models.tax.AgencyEnrollment repeated
GetAgencyByCmsKeyRequest
Field Type Label Description
cms_key string
GetAgencyOverlayRequest
Field Type Label Description
symmetry_uuid string
GetAgencyRequest
Field Type Label Description
symmetry_uuid string
GetTaxAgencyBankInfoRequest
Field Type Label Description
jurisdiction string Legacy key. Required only when deposit_key is empty.
form_type string
deposit_key string The natural key (migration 030). Preferred; when set, the pair above is ignored.
ListAgenciesRequest
Field Type Label Description
state string Optional filters; empty string means "no filter".
jurisdiction_type string STATE | FEDERAL | LOCAL | COUNTY
provenance string CMS | SYMMETRY | CMS+overlay
ListAgencyOverlayRequest
Field Type Label Description
agency_uuid string
ListTaxAgencyBankInfosRequest
Field Type Label Description
jurisdiction string Optional filter; empty string means "all jurisdictions".
StateTaxAccount

State tax account for a company Block-level encryption (mirrors BankAccount): account_number stores an HMAC-SHA256 hash for exact-match lookup; the plaintext value lives inside encrypted_data_block (Base64 Asherah ciphertext) keyed by kms_session_id. ste_tax_code is the canonical FK to libs/reference-data-models TaxDef (TaxDef.uniqueTaxId, format "XX-CCC-FFFFFF-TTT-VVV"). Agency/state/county metadata is resolved at read time via ReferenceData.tax(ste_tax_code); no agency_id column is stored to avoid drift when CMS publishes new snapshots. tax_type and status are STRINGs (not enums) to remain tolerant to CMS vocabulary growth (e.g., "ER_SUTA", "CITY", "OLF") — same rationale as AgencyDef.jurisdictionType in libs/reference-data-models. OWNERSHIP (company-scoped today): a StateTaxAccount belongs to exactly one company_id. This is correct for FILING_MODE_DIRECT and FILING_MODE_SERVICE_PROVIDER_MANAGED (the filer EIN belongs to the client company; the SP only remits). It is NOT sufficient for FILING_MODE_PEO_MANAGED consolidated returns, where the legal filer is the PEO (FILING_ENTITY_TYPE_PEO, id == tenant_id) filing under PEO-owned state registrations. Modeling PEO/tenant-level accounts (e.g. owner_id + owner_type like BankAccount) is DEFERRED until the PEO consolidated form-assembly path exists — see PAF-1624 and docs/architecture/state-tax-account-ingestion.md §7.

Field Type Label Description
state_tax_account_id string Primary key
tenant_id string Partition key
company_id string FK to Company. Company-scoped only today; PEO/tenant-level ownership is deferred (PAF-1624). Do NOT repurpose for PEO accounts without that work.
state string Two-letter state code
ste_tax_code string FK to TaxDef.uniqueTaxId, e.g. "AL-000-113277-CITY-000"
tax_type string CMS tax_type_code, e.g. "SIT", "SUI", "ER_SUTA", "CITY"
account_number string PII (hash for lookup, plaintext lives in encrypted_data_block) HMAC-SHA256 hash for exact-match lookup
status string "ACTIVE", "INACTIVE", "SUSPENDED"
registered_at google.protobuf.Timestamp
updated_at google.protobuf.Timestamp
encrypted_data_block string Block-level encryption (same pattern as Employee, Company, BankAccount) Base64-encoded encrypted JSON containing account_number
kms_session_id string
ACHConfigurationRaw

ACH configuration plaintext data

Field Type Label Description
ach_config_id string Primary key - required
tenant_id string Tenant ID - required
owner_id string Owner ID - required
owner_type com.symmetry.models.tax.OwnerType Owner type enum
immediate_destination string NACHA file fields
immediate_origin string
company_name string
company_identification string
company_entry_description string
company_discretionary_data string
service_class_code com.symmetry.models.tax.ServiceClassCode Service class code enum
created_at google.protobuf.Timestamp Timestamps
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Sync tracking - populated for API responses
ingested_at google.protobuf.Timestamp Ingestion metadata
source_system_id string
AddressRaw

Address plaintext data Supports both embedded address (ingestion) and address_id reference (API)

Field Type Label Description
address_id string Primary key - populated for API responses
tenant_id string Tenant ID - populated for API responses
street_line_1 string Street address line 1 - required for valid address, max 200 chars
street_line_2 string Street address line 2 (optional), max 200 chars
city string City name - max 100 chars
state string Two-letter state code (e.g., "CA", "NY")
zip_code string 5 or 9 digit ZIP code
country string Country code (default "USA"), 2-3 chars
address_type com.symmetry.models.tax.AddressType Address type enum
validated bool Validation status
validated_at google.protobuf.Timestamp
created_at google.protobuf.Timestamp Timestamps
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Sync tracking - populated for API responses
ingested_at google.protobuf.Timestamp Ingestion metadata - populated during ingestion
source_system_id string
county_code string Geographic metadata for local tax jurisdiction resolution
county_name string
AgencyCreditRaw
Field Type Label Description
credit_id string Optional; server generates UUID7 if empty. Deliberately NOT unique — a restatement reuses it and readers resolve latest-wins on stated_at, exactly as TaxDepositRaw does.
tenant_id string
company_id string
jurisdiction string USPS state code or "US". max_len 10 matches TaxLiabilityRaw deliberately: a 14-char STE location code is not a jurisdiction, and that mismatch is what let raw location codes into tax_liability.
ste_tax_code string The precise tax the credit sits against. Required — a credit that names no tax cannot be scoped to a form box, and admitting one would put it on EVERY box that asks for a prior credit.
tax_type com.symmetry.models.tax.TaxType
kind com.symmetry.models.tax.AgencyCreditKind Required, and validated service-side against UNSPECIFIED: a statement with no kind cannot be read as a credit or a refund, and defaulting either way is a money decision.
amount_cents int64 ALWAYS POSITIVE. The kind carries the direction; a signed amount would give two ways to say the same thing. Non-positive is rejected service-side.
origin_period_start google.protobuf.Timestamp The period the credit AROSE from. Optional: an agency may assert a credit without attributing it to a period, and refusing that would discard the agency's own statement.
origin_period_end google.protobuf.Timestamp
effective_date google.protobuf.Timestamp Required. This is the date a filing period is tested against — without it the credit either lands on every period or none, and both are wrong.
expiration_date google.protobuf.Timestamp
settled_date google.protobuf.Timestamp
agency_notice_number string
agency_confirmation_number string
source_filing_job_id string
stated_at google.protobuf.Timestamp When the AGENCY said it — the latest-wins tiebreaker. Required, because two notices about one credit are ordered by the agency's dates and an absent one makes the order arbitrary.
ingested_at google.protobuf.Timestamp Server-set (= envelope timestamp); ignored if supplied.
source_system_id string
AgencyDataRaw

Agency-specific data for employees, companies, and preparers This is a first-class entity sent separately via Kinesis (AGENCY_DATA entity type). Each record associates a specific agency field/value with an owner (employee, company, or preparer). Example: Alaska Geographic Code for an employee { "agency_data_id": "agd-001", "tenant_id": "tenant-001", "owner_type": "EMPLOYEE", "owner_id": "emp-001", "agency_id": "AK-DOLWD", "field_name": "AK_GEO_CODE", "value": "02-110" }

Field Type Label Description
agency_data_id string Primary key - optional, server generates UUID7 if empty
tenant_id string Tenant ID - required
owner_type com.symmetry.models.tax.OwnerType Owner type - EMPLOYEE, COMPANY, or PREPARER
owner_id string Owner ID - FK to employee_id, company_id, or preparer_id based on owner_type
agency_id string Agency identifier (e.g., "AK-DOLWD", "CA-EDD")
u_id string Symmetry unique identifier for this field type
field_name string Field name in the CMS (e.g., "AK_GEO_CODE", "CA_SUI_RATE")
value string Value assigned to this field for this owner. ENCRYPTED (PAF-1794). agency_data is the EAV bag for per-owner agency values, and some of them are SECRETS — the Reporting Agent PIN signs on the taxpayer's behalf. The column cannot be per-row selective, so it is encrypted for every row: the field holds an HMAC-SHA256 hash for exact-match lookup and the plaintext lives in encrypted_data_block, exactly as state_tax_account.account_number does. Consumers reach the value through a CARRY_FORWARD_PII reference; AGENCY_DATA_VALUE emits one rather than reading this column.
state_code string State code (optional, may be derived from agency_id)
created_at google.protobuf.Timestamp Timestamps
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Sync tracking - populated for API responses
ingested_at google.protobuf.Timestamp Ingestion metadata
source_system_id string
AppliedBenefitRaw

A benefit as APPLIED to an employee's wages for one pay date, in one jurisdiction (PAF-1820). Sibling of TaxLiabilityRaw at its own grain, not a nested field on it: benefits are per-employee while liabilities are per-employee-per-tax, so nesting would replicate each benefit N times. WHY THIS EXISTS. A pre-tax benefit reduces taxable wages, and today that reduction reaches the warehouse only implicitly, pre-netted into TaxLiability.subject_wages_cents. That arithmetic is correct and IRREVERSIBLE: from a liability row you cannot recover which benefit caused the reduction, only the net. No audit trail, and W-2 boxes 10 / 12a-d / 14a have no input at all. SOURCE-AGNOSTIC. Producers may or may not run STE. This is an ordinary ingested entity with its own RPCs and batch-CSV mapping; the PayCalc deriver is one producer among them, and the STE response shape is the reference for what a complete benefit record carries, not its author.

Field Type Label Description
benefit_id string Primary key. Application validator (EntityValidator.validateAppliedBenefit) enforces non-empty; the proto-level min_len is omitted for the same reason as TaxLiabilityRaw.liability_id, so a follow-up can enable server-side UUID7 synthesis when blank without a breaking proto change.
tenant_id string Partition key - required
company_id string FK to Company - required
employee_id string FK to Employee - required
pay_date google.protobuf.Timestamp Pay period - required
period_start google.protobuf.Timestamp
period_end google.protobuf.Timestamp
jurisdiction string "US" or a state code ("CA"), matching TaxLiabilityRaw.jurisdiction so the two tables join. NOT a raw STE location code. STE replicates each benefit across every locationCode the employee worked, carrying the FULL amount at each (verified: a 20.08 section-125 reduction appears at both 00-000-0000 and 49-035-1432728, and each jurisdiction's tax rows show exactly that reduction). So the fan-out is real data and must be PRESERVED per jurisdiction — but a 14-character location code also does not fit here, and would not join to the USPS codes every batch producer sends. Derive with SteTaxCode.jurisdiction(). Summing a category ACROSS jurisdictions double-counts by the number of jurisdictions worked. This is the reverse of liabilities, where each (jurisdiction, tax_type) is a distinct tax and cross-jurisdiction summing is legitimate.
benefit_category string The kind of plan: "125", "401_K", "HSA", "FSA_DEPENDENT_CARE", ... Canonicalised on the way in by BenefitCategories.canonical, which converges the four producer dialects in flight (the generated BenefitTypeValues name, STE's "Benefit401K" JSON, tax-data's "401K" benefitRules key, and a batch CSV's "ROTH_401K"). PART OF THE DEDUP KEY, and free-text with only a length bound for the same reason wage_type is: STE's tax-data authors 23 categories while its XSD enum has 17, and three of the extras are US categories reachable no other way (DependentCustodialAccount, effective 2026-07-04 under OBBBA, plus the two EducationalAssistance forms). An enum would fold all three onto UNRECOGNIZED. Blank is the alarm state, not a category: it means a producer's spelling was lost. Phase 3 gates on zero blank categories.
wage_type string Which wage classification this benefit was applied against. Canonicalised by WageTypes.canonical, and part of the dedup key, exactly as on TaxLiabilityRaw.
employee_benefit_cents int64 Amounts (in cents) - must be non-negative. These are what the engine APPLIED, not what the request elected. In STE's response that is calculatedAmt / employerCalculatedAmt, NOT benefitAmt / employerContribution, which merely echo the request and diverge from the applied figure whenever a percentage election or an annual limit binds. The elected figure is kept below as provenance. Summed across the producer's individual benefits within one category: an employee's medical, vision and dental deductions are three benefits to the employer and ONE section-125 wage reduction to the engine. Emitting them separately would collapse under latest-wins dedup — keeping one and discarding the rest, nondeterministically, since the tiebreak chain cannot separate them.
employer_benefit_cents int64
annual_limit_cents int64 Plan contribution limit in force for this category, and whether a catch-up limit applied. Zero means the producer declared no limit, which is common and not an error.
is_catch_up bool
employee_benefit_ytd_cents int64 Year-to-date figures as the PRODUCER reported them, for reconciliation against a YTD summary computed here. Not authoritative and not part of any key.
employer_benefit_ytd_cents int64
ee_pretax com.symmetry.models.tax.BenefitFlag TAXABILITY, AS THE PRODUCER ASSERTED IT — AUDIT PROVENANCE, NOT A FILING INPUT. No W-2 box needs these. Box 12 codes D/E/G/W/AA/BB/EE and box 10 are plan AMOUNTS; the one taxability distinction that reaches paper (traditional vs Roth) is already carried by benefit_category. The wage boxes are the already-reduced figures and come from the liability side. What these serve is reconstructing WHY subject wages differ from gross. Genuinely per (category, tax code) and effective-dated — it is not a federal-uniform rule. New Jersey treats 125/401K/HSA/Roth401K as fully taxable for SDI, FLI, SUI and ER_SUTA; Arkansas taxes 401K for ER_SUTA. STE authors this in its tax-engine repo's tax-data (7182 of 7561 tax-code files carry benefitRules), which has NO publish path into this platform, so nothing here resolves them — a producer either knows and says, or leaves them UNSPECIFIED. For a custom benefit the producer's assertion is the ONLY source: no reference data covers it (there is no "Custom" key in any benefitRules file), which is why it is worth storing at all.
er_taxable com.symmetry.models.tax.BenefitFlag
subject_wage_impact string The producer's own three-valued spelling of the pair above, verbatim, when it sends one. STE's CustomBenefitType.subject_wage_impact is "EmployeePretax" / "EmployerTaxable" / "EmployeePretaxEmployerTaxable". Kept unparsed alongside the decomposed flags so a producer vocabulary we mis-decompose is still recoverable.
benefit_reference_codes string repeated PROVENANCE — the producer's own labels for the individual benefits summed into this row, e.g. ["MEDICAL_INSURANCE", "VISION_INSURANCE", "DENTAL_INSURANCE"] for one section-125 row. Deliberately NOT in the key. These are customer-supplied free text: STE's benefitReferenceCode is whatever the caller sent, so keying on it would fork on spelling and, worse, would defeat the per-category summing above. Same treatment payroll_run_id gets.
elected_amount_cents int64 What the producer ELECTED, against which the applied amount above can be checked. A gap between them is normal and informative: it is where an annual limit or a percentage election bound.
ingested_at google.protobuf.Timestamp Metadata
source_system_id string
payroll_run_id string Re-submission semantics, identical in meaning to TaxLiabilityRaw's: payroll_run_id is the customer's external run identifier (provenance only, does not reach summary tables), and submitted_at is the customer-attested as-of timestamp and the primary latest-wins tiebreaker, falling back to ingested_at then benefit_id.
submitted_at google.protobuf.Timestamp
corrects_payroll_run_id string Restatement semantics, as on TaxLiabilityRaw. correction_cause is the authoritative marker (!= UNSPECIFIED implies a correction); LIABILITY_CORRECTION_CAUSE_BENEFIT_CORRECTION already exists for exactly this case. None of the three participates in the natural key — a restatement must COLLIDE with the row it corrects in order to supersede it rather than double it.
correction_cause com.symmetry.models.tax.LiabilityCorrectionCause
error_discovered_at google.protobuf.Timestamp
external_id string Optional, purely additive client reference for this one benefit line. Carried through to storage and to collision audit logs unchanged; does NOT participate in the natural key or any tiebreak. Same contract as TaxLiabilityRaw.external_id — see that field for why benefit_id and payroll_run_id cannot serve this purpose.
BankAccountRaw

Bank account plaintext data (HIGHLY SENSITIVE)

Field Type Label Description
bank_account_id string Primary key - required
tenant_id string Tenant ID - required
owner_id string Owner ID - required
owner_type com.symmetry.models.tax.OwnerType Owner type enum
routing_number string HIGHLY SENSITIVE - PLAINTEXT 9-digit routing number
account_number string Bank account number - 4-17 digits
account_type com.symmetry.models.tax.AccountType Account type enum
originating_dfi_id string First 8 digits of routing number
verified bool
status com.symmetry.models.tax.AccountStatus Account status enum
created_at google.protobuf.Timestamp Timestamps
verified_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Sync tracking - populated for API responses
ingested_at google.protobuf.Timestamp Ingestion metadata
source_system_id string
account_holder_name string Account holder name (from bankAccount.holderName)
CompanyContactRaw

Company contact (payroll admin + signatory). Iceberg-only; PII encrypted downstream.

Field Type Label Description
company_contact_id string Primary key - optional; server generates UUID7 if empty
tenant_id string
company_id string
contact_type com.symmetry.models.tax.ContactType
first_name string (embeddable) as well as (encrypted): once encrypted this column holds an HMAC-SHA256 hash, so a vector built from the PLAINTEXT raw is the only way to search a contact by name. MessageEmbedder reads the RAW descriptor, so the annotation has to be here -- carrying it only on the canonical message yields "CompanyContactRaw has 0 embeddable fields" and no vector is ever produced.
middle_name string
last_name string (embeddable) as well as (encrypted): once encrypted this column holds an HMAC-SHA256 hash, so a vector built from the PLAINTEXT raw is the only way to search a contact by name. MessageEmbedder reads the RAW descriptor, so the annotation has to be here -- carrying it only on the canonical message yields "CompanyContactRaw has 0 embeddable fields" and no vector is ever produced.
suffix string
title string
email string
phone string
external_id string
ingested_at google.protobuf.Timestamp
source_system_id string
CompanyRaw

Company plaintext data

Field Type Label Description
company_id string Primary key - IGNORED on ingestion, server always generates UUID7 Populated in API responses
tenant_id string Tenant ID - required
legal_name string Legal name (plaintext) - required
ein string Federal Employer Identification Number (FEIN) - format: XX-XXXXXXX (encrypted/hashed)
filing_mode com.symmetry.models.tax.FilingMode Filing mode enum
primary_address AddressRaw Primary business address - embedded for ingestion
primary_address_id string Primary address ID - for API responses
created_at google.protobuf.Timestamp Timestamps
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Sync tracking - populated for API responses
ingested_at google.protobuf.Timestamp Ingestion metadata
source_system_id string
external_id string ── Client Reference (REQUIRED) ────────────────────────────────────────── Client's reference ID for this company (e.g., "COMP-001" in their system) Used for deduplication: (tenant_id, external_id)
deleted_at google.protobuf.Timestamp Soft delete timestamp - null/unset means active, set means deleted
efin string IRS filing credentials (entity-level) Electronic Filing Identification Number
etin string Electronic Transmitter Identification Number
taxpayer_type com.symmetry.models.tax.TaxpayerType Tax classification (from companyDetails.taxPayerType)
business_entity_type com.symmetry.models.tax.TaxpayerType
mailing_address AddressRaw Mailing address — embedded for ingestion; separate ADDRESS envelope when set
mailing_address_id string
phone string Company phone (number + extension concatenated at ingest)
trade_name string Trade name / DBA ("doing business as") - optional (plaintext, encrypted/hashed + embeddable)
CompanyTaxProfileRaw
Field Type Label Description
record_id string Version id - optional; server generates UUID7 if empty
tenant_id string
company_id string
data_key string e.g. "US_WITHHOLDING_FILING_FORM" (open vocabulary; service-side allowlist)
data_value string e.g. "941" | "944" (service-side allowlist for the form-election key)
is_active bool
effective_from google.protobuf.Timestamp Valid time - required
ingested_at google.protobuf.Timestamp Transaction time - server-set (= envelope timestamp); ignored if supplied
source_system_id string
EmployeeRaw

Employee plaintext data

Field Type Label Description
employee_id string Primary key - IGNORED on ingestion, server always generates UUID7 Populated in API responses
tenant_id string Partition key - required, 1-255 chars
ssn string PII - PLAINTEXT (will be encrypted downstream) SSN format: XXX-XX-XXXX or XXXXXXXXX
first_name string First name - required, 1-100 chars
last_name string Last name - required, 1-100 chars
date_of_birth string Date of birth - ISO-8601: YYYY-MM-DD format
home_address AddressRaw Addresses - embedded for ingestion Residential address (optional)
mailing_address AddressRaw Mailing address (optional, if different from home)
home_address_id string Address IDs - for API responses (references stored addresses)
mailing_address_id string
created_at google.protobuf.Timestamp Timestamps
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Sync tracking - populated for API responses
ingested_at google.protobuf.Timestamp Ingestion metadata
source_system_id string
source_record_id string
external_id string ── Client Reference (REQUIRED) ────────────────────────────────────────── Client's reference ID for this employee (e.g., "EMP-001" in their system) Used for deduplication: (tenant_id, source_company_id, external_id)
source_company_id string Company scope for external_id (required for PEO/SP tenants)
middle_name string Middle name / suffix (W-2 and return name blocks)
suffix string
EmployeeTaxExemptionRaw

Employee-grain tax exemption (append-only, effective-dated). Iceberg-only; no PII.

Field Type Label Description
record_id string
tenant_id string
company_id string
employee_id string
ste_tax_id string
is_exempt bool
effective_from google.protobuf.Timestamp
ingested_at google.protobuf.Timestamp
source_system_id string
EmployeeTaxProfileRaw

W-2 Box 13 flags per employee per tax year. Iceberg-only; no PII.

Field Type Label Description
record_id string
tenant_id string
employee_id string
year int32
statutory_employee bool
retirement_plan bool
third_party_sick_pay bool
ingested_at google.protobuf.Timestamp
source_system_id string
state_wage_plan_codes map<EmployeeTaxProfileRaw.StateWagePlanCodesEntry> repeated State postal code (e.g. "CA") -> that state's wage plan code for the employee.
EmployeeTaxProfileRaw.StateWagePlanCodesEntry
Field Type Label Description
key string
value string
EmploymentRaw

Employment relationship plaintext data

Field Type Label Description
employment_id string Primary key - IGNORED on ingestion, server always generates UUID7 Populated in API responses
tenant_id string Tenant ID - required
employee_id string Employee ID - required
company_id string Company ID - required
worksite_location_id string Worksite location ID (optional)
hire_date google.protobuf.Timestamp Hire date - required
termination_date google.protobuf.Timestamp Termination date (Nullable)
status com.symmetry.models.tax.EmploymentStatus Employment status enum
annual_salary_cents int64 Annual salary in cents - must be non-negative
created_at google.protobuf.Timestamp Timestamps
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Sync tracking - populated for API responses
ingested_at google.protobuf.Timestamp Ingestion metadata
source_system_id string
external_id string ── Client Reference (REQUIRED) ────────────────────────────────────────── Client's reference ID for this employment (e.g., "EMPL-001" in their system) Used for deduplication: (tenant_id, source_company_id, external_id)
source_company_id string
FilingJobTransitionRaw

============================================================================ FILING-JOB LIFECYCLE TRANSITION RAW (scheduler merge) — no PII, append-only ============================================================================ Ingested via IngestionService.IngestFilingJobTransition. entity-grpc owns the local-first PG overlay write; this forwards the event to the data lake. transition_id is server-generated (UUID7) when empty; changed_at is server-set to the envelope timestamp. See infrastructure/persistent/sql/iceberg/filing_job_transition.sql.

Field Type Label Description
transition_id string Version id - optional; server generates UUID7 if empty
tenant_id string
job_id string
schedule_id string
deadline_id string
company_id string
tax_year int32
transition_kind com.symmetry.models.tax.FilingJobTransitionKind FilingJobTransitionKind enum value (required, must not be UNSPECIFIED)
from_status string
to_status string
artifact_status string
actor_id string
reason string
reason_code string
batch_id string
changed_at google.protobuf.Timestamp Event time - server-set (= envelope timestamp); ignored if supplied
source_system_id string
IngestionBatch

Batch ingestion wrapper for multiple records

Field Type Label Description
batch_id string Unique batch identifier - required
tenant_id string Tenant ID for all records in batch - required
batch_time google.protobuf.Timestamp
source_system_id string
total_records int32 Record counts - must be non-negative
processed_records int32
failed_records int32
employees EmployeeRaw repeated Records by type (use oneof for polymorphic batches or separate batches per type)
tax_liabilities TaxLiabilityRaw repeated
companies CompanyRaw repeated
bank_accounts BankAccountRaw repeated
PEORaw

PEO plaintext data

Field Type Label Description
peo_id string Primary key - IGNORED on ingestion, server always generates UUID7 Populated in API responses
tenant_id string Tenant ID - populated for API responses
legal_name string Legal name (plaintext) - required
ein string Federal Employer Identification Number (FEIN) - format: XX-XXXXXXX (encrypted/hashed) This is the IRS-issued federal tax ID. State-specific tax account numbers are captured separately in StateTaxAccountRaw linked by company_id.
primary_address AddressRaw Primary business address - embedded for ingestion
primary_address_id string Primary address ID - for API responses
created_at google.protobuf.Timestamp Timestamps
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Sync tracking - populated for API responses
ingested_at google.protobuf.Timestamp Ingestion metadata
source_system_id string
external_id string ── Client Reference (REQUIRED) ────────────────────────────────────────── Client's reference ID for this PEO (e.g., "PEO-001" in their system) Used for deduplication: (external_id) - PEO is a top-level tenant entity
efin string IRS filing credentials (entity-level) Electronic Filing Identification Number
etin string Electronic Transmitter Identification Number
PaymentApplicationRaw

───────────────────────────────────────────────────────────────────────────────────────────────── PaymentApplicationRaw — ingest shape for PaymentApplication. PAF-1913. deposit_id is required and NOT validated against tax_deposit: an agency reporting an application for a deposit we have no row for is a divergence to surface, not an integrity error to reject. Rejecting it here would discard the only evidence that the two sides disagree.

Field Type Label Description
application_id string
tenant_id string
company_id string
deposit_id string
jurisdiction string
ste_tax_code string
tax_type com.symmetry.models.tax.TaxType
applied_amount_cents int64 Positive: an application moves money TO a tax. A reversal restates the row rather than carrying a negative, so there is exactly one way to say a thing.
applied_period_start google.protobuf.Timestamp Required, and the reason the record exists -- the as-applied period is the quantity that cannot be inferred from anything the client asserted.
applied_period_end google.protobuf.Timestamp
applied_date google.protobuf.Timestamp
agency_notice_number string
agency_confirmation_number string
source_filing_job_id string
stated_at google.protobuf.Timestamp Required: it orders the append-only collapse, so a row without it cannot be resolved against its own restatements.
ingested_at google.protobuf.Timestamp
source_system_id string
PreparerRaw

Tax preparer plaintext data

Field Type Label Description
preparer_id string Primary key - IGNORED on ingestion, server always generates UUID7 Populated in API responses
tenant_id string Tenant ID - required
owner_id string Owner ID - required
owner_type com.symmetry.models.tax.OwnerType Owner type enum
firm_name string PII - PLAINTEXT
first_name string
last_name string
email string Email format validation
phone string Phone - flexible format
business_address AddressRaw Business address - embedded for ingestion
business_address_id string Business address ID - for API responses
ptin string
naic_code string
preparer_type com.symmetry.models.tax.PreparerType Preparer type enum
self_employed bool
status com.symmetry.models.tax.PreparerStatus Status enum
created_at google.protobuf.Timestamp Timestamps
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Sync tracking - populated for API responses
ingested_at google.protobuf.Timestamp Ingestion metadata
source_system_id string
title string Free-text role/title for the form signature block (e.g. "Owner"). Plaintext — not PII.
role string Agent contact slot (officer / tax_return_preparer / technical_contact). Plaintext — not PII.
external_id string ── Client Reference (REQUIRED) ────────────────────────────────────────── Client's reference ID for this preparer (e.g., "PREP-001" in their system) Used for deduplication: (tenant_id, owner_id, external_id). Unlike Employee/Employment, no separate source_company_id is needed here — owner_id (already required above) is itself the unambiguous scope: a preparer owned by a PEO/ServiceProvider has owner_id pointing at that PEO/SP directly, not at "one of its many client companies."
ReportingAgentAuthorizationRaw

============================================================================ ReportingAgentAuthorization ingestion — Form 8655 authority windows ============================================================================ One row per GRANTED FORM, not per 8655 document: line 15 of the form grants per-form start periods, so a single signed instrument yields several of these. Append-only. A revocation is a new version carrying revoked_at, never a delete — authority has to stay evaluable as of the signing date of a return filed while it was in force. Carries NO credential. The RA PIN is agent-scoped (one per agent, from Pub 3112), so holding it per client would be N copies of one secret; it belongs behind the BankAccount hash + encrypted_data_block pattern or a secrets-manager reference, and never here. This message therefore has no (encrypted) field at all.

Field Type Label Description
authorization_id string Optional; server generates UUID7 if empty. This record's own PK.
tenant_id string
agent_owner_id string WHO is authorized. Agent-scoped, mirroring BankAccount: one authorization per (agent, client, form). The agent is a ServiceProvider or PEO, never a Company — a company does not hold authority over itself.
agent_owner_type com.symmetry.models.tax.OwnerType
company_id string WHO it is authorized FOR.
form_code string WHAT. The IRS code as printed on the form (940, 941, 943, 945, 1042). The amendment variant is NOT a separate grant — authority for a form reaches its amended return — so "941-X" is not a value here.
effective_from google.protobuf.Timestamp FROM WHEN. Required: a grant with no start cannot be compared against a corrected period, and defaulting it to epoch would silently authorize everything ever filed.
revoked_at google.protobuf.Timestamp Null while in force.
filed_with_irs_at google.protobuf.Timestamp Provenance. The 8655 goes to the RAF team in Ogden and is never attached to a return, so nothing in the filing path can detect its absence — which is the whole reason this record exists.
declared_by string
submitted_at google.protobuf.Timestamp Latest-wins tiebreaker on restatement.
ingested_at google.protobuf.Timestamp Server-set (= envelope timestamp); ignored if supplied.
source_system_id string
ServiceProviderRaw

Service Provider plaintext data

Field Type Label Description
service_provider_id string Primary key - IGNORED on ingestion, server always generates UUID7 Populated in API responses
tenant_id string Tenant ID - populated for API responses
legal_name string Legal name (plaintext) - required
ein string Federal Employer Identification Number (FEIN) - format: XX-XXXXXXX (encrypted/hashed) This is the IRS-issued federal tax ID. State-specific tax account numbers are captured separately in StateTaxAccountRaw linked by company_id.
primary_address AddressRaw Primary business address - embedded for ingestion
primary_address_id string Primary address ID - for API responses
provider_type com.symmetry.models.tax.ServiceProviderType Provider type enum
files_on_behalf bool
created_at google.protobuf.Timestamp Timestamps
updated_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Sync tracking - populated for API responses
ingested_at google.protobuf.Timestamp Ingestion metadata
source_system_id string
external_id string ── Client Reference (REQUIRED) ────────────────────────────────────────── Client's reference ID for this ServiceProvider (e.g., "SP-001" in their system) Used for deduplication: (external_id) - ServiceProvider is a top-level tenant entity
efin string IRS filing credentials (entity-level) Electronic Filing Identification Number
etin string Electronic Transmitter Identification Number
StateTaxAccountRaw

State tax account raw data (UNENCRYPTED) State-level tax account information for a company. Unlike the Federal EIN (stored on Company, PEO, ServiceProvider), state tax accounts are state-specific identifiers used for state income tax (SIT), unemployment (SUI), disability (SDI), and local tax filings. ste_tax_code is the canonical FK to libs/reference-data-models TaxDef (TaxDef.uniqueTaxId, format "XX-CCC-FFFFFF-TTT-VVV"). entity-grpc soft-validates the code against the bundled CMS snapshot (warn-only); data-grpc accepts as-is. tax_type and status are open strings (no proto-level enum constraint) to remain tolerant to CMS vocabulary growth — same rationale as AgencyDef.jurisdictionType.

Field Type Label Description
state_tax_account_id string Primary key - required
tenant_id string Tenant ID - required
company_id string Company ID - required (links to CompanyRaw which holds the Federal EIN)
state string Two-letter state code (e.g., "CA", "NY", "TX")
tax_type string CMS-authoritative tax type code (e.g., "SIT", "SUI", "ER_SUTA", "CITY", "OLF"). Open string — service-side allowlist enforced by entity-grpc handler, not by proto.
account_number string State-assigned tax account number (encrypted/hashed) Format varies by state - this is NOT the Federal EIN
status string Account status: "ACTIVE", "INACTIVE", "SUSPENDED" (service-side enforcement)
ste_tax_code string STE Tax ID — canonical FK to TaxDef.uniqueTaxId, e.g. "AL-000-113277-CITY-000". Format: ----.
ingested_at google.protobuf.Timestamp
source_system_id string
TaxCorrectionRaw

Correction declaration — a producer-attested statement that liabilities restate a filed period. See TaxCorrection in transactions.proto for the full rationale. Ingestion posture mirrors CompanyTaxProfileRaw: append-only, Iceberg-only, record id server-generated when empty, ingested_at server-set from the envelope. Correlation to tax_liability rows is a COMPOSITE NATURAL KEY on scope, not a foreign key — nothing echoes correction_id onto a liability row, which is why server-generation is safe here.

Field Type Label Description
correction_id string Optional; server generates UUID7 if empty. This record's own PK — referenced by nothing.
tenant_id string
company_id string
jurisdiction string Scope — period AND taxes; both required. jurisdiction alone cannot identify an obligation (CA covers SIT/SUI/SDI) and tax_type cannot either (TAX_TYPE_LOCAL spans agencies).
corrected_period_label string
corrected_period_start google.protobuf.Timestamp
corrected_period_end google.protobuf.Timestamp
affected_ste_tax_codes string repeated FKs to reference-data TaxDef — the key TaxCodeKeyIndex routes on. At least one: an empty scope is not a permissive default, it is a declaration that can never be routed to a filing, and accepting one produces a correction nothing will ever amend.
correction_cause com.symmetry.models.tax.LiabilityCorrectionCause UNSPECIFIED is invalid on a DECLARATION (validated service-side), unlike on a liability row where it legitimately means "an ordinary payroll".
error_discovered_at google.protobuf.Timestamp Authoritative discovery date for the form; day-grain normalised server-side.
explanation_draft string Derived, de-identified — plain string, no encryption (see TaxCorrection.explanation_draft).
explanation_note string Human-authored free text. Producers send PLAINTEXT here; data-grpc encrypts it into TaxCorrection.encrypted_data_block on the way in, the same posture as every other PII field on the ingestion path. The (encrypted) option is what drives that — PiiEncryptionService discovers fields by this option, so without it the plaintext is silently dropped at the mapper and the note never reaches storage at all. NOT (embeddable): prose containing names must not feed a search vector.
amendment_process com.symmetry.models.tax.AmendmentProcess 941-X Part 1 process election + Part 2 certifications. Carried verbatim — the service must not supply a default for either; see the enum docs in common.proto for why deriving them is not an option. An UNSPECIFIED process and an empty certification list both mean "the filer has not answered", which is a blocking gap downstream, not something to fill in here.
amendment_certifications string repeated
declared_by string
declared_at google.protobuf.Timestamp
submitted_at google.protobuf.Timestamp
ingested_at google.protobuf.Timestamp Server-set (= envelope timestamp); ignored if supplied.
source_system_id string
TaxDepositRaw
Field Type Label Description
deposit_id string Optional; server generates UUID7 if empty. Deliberately NOT unique — a settlement confirmation or a correction reuses it, and readers resolve latest-wins on submitted_at.
tenant_id string
company_id string
jurisdiction string
deposit_key string FK to reference-data AgencyDeposit.deposit_key ("US - 941"). Required: it is the join to the agency's payment rules, and a deposit that names no program cannot be reconciled against one.
tax_types string repeated Canonical names in DepositScopes (models/lib); unknown tokens rejected service-side. At least one — an empty scope intersects no form line, so the deposit would be accepted and then silently never count toward any return.
liability_period_start google.protobuf.Timestamp Which period this pays down. Declared, never inferred from deposit_date — a late deposit routinely applies to an earlier period.
liability_period_end google.protobuf.Timestamp
deposit_date google.protobuf.Timestamp When the money moved. Required: without it deposit-schedule compliance cannot be evaluated at all.
amount_cents int64 Signed, but a deposit is money paid — negative is a returned/reversed amount and belongs in a RETURNED-status row, not a negative deposit. Validated service-side.
origination com.symmetry.models.tax.TaxDepositOrigination
status com.symmetry.models.tax.TaxDepositStatus
confirmation_number string
submitted_at google.protobuf.Timestamp
settled_at google.protobuf.Timestamp
supersedes_deposit_id string deposit_id of the row this replaces; empty for an ordinary deposit. See TaxDeposit.
source_filing_job_id string
source_artifact_id string
source_nacha_payment_id string
ingested_at google.protobuf.Timestamp Server-set (= envelope timestamp); ignored if supplied.
source_system_id string
TaxExemptionRaw
Field Type Label Description
record_id string Version id - optional; server generates UUID7 if empty
tenant_id string
company_id string
ste_tax_id string Tax identifier (same code space as StateTaxAccount.ste_tax_code / TaxDef.uniqueTaxId)
is_exempt bool
effective_from google.protobuf.Timestamp Valid time - required
ingested_at google.protobuf.Timestamp Transaction time - server-set (= envelope timestamp); ignored if supplied
source_system_id string
TaxLiabilityRaw

Tax liability from payroll system (mostly not PII, but includes employee reference)

Field Type Label Description
liability_id string Primary key. Application validator (EntityValidator.validateTaxLiability) enforces non-empty today. The proto-level min_len constraint is intentionally omitted so a future follow-up can enable server-side UUID7 synthesis when blank (mirrors EmployeeRaw.employee_id / CompanyRaw.company_id). Until that lands, clients MUST supply liability_id; the validator returns a structured error if absent.
tenant_id string Partition key - required
company_id string FK to Company - required
employee_id string FK to Employee - required
pay_date google.protobuf.Timestamp Pay period - required
period_start google.protobuf.Timestamp
period_end google.protobuf.Timestamp
jurisdiction string Jurisdiction - "USA" or state code (e.g., "CA")
tax_type string Tax type
ste_tax_code string STE Tax ID (e.g., "39-000-0000-schl-1234")
gross_wages_cents int64 1. TOTAL PAY for this (employee, pay_date, wage_type), before ANY reduction. Identical across every tax row for that check — it is a property of the paycheck, not of the tax.
gross_subject_wages_cents int64 2. THE WAGE BASE THIS TAX WAS COMPUTED ON, after the pre-tax reductions THIS tax honours, and before any cap. So it VARIES BY tax_type on the same paycheck: a §125 premium reduces both the FIT and the FICA base, a traditional 401(k) deferral reduces FIT and NOT FICA, and a Roth deferral reduces neither. W-2 box 1 is this column on the FIT row. Send it and box 1 is right; leave it equal to gross_wages_cents and box 1 reports GROSS PAY as federal taxable wages, overstated by every pre-tax deduction the employee has, with nothing on the form to show it. You already have this figure — it is the base your engine withheld on. We deliberately do NOT derive it: doing so would mean resolving benefit taxability per (category, jurisdiction, tax), which is genuinely not federal-uniform (New Jersey taxes 125/401K/HSA for SDI/FLI/SUI; Arkansas taxes 401K for ER_SUTA) and lives in STE's tax-data with no publish path here. See AppliedBenefitRaw.ee_pretax for why that stays audit provenance rather than a filing input. MEASURED 2026-09-07 on acme-payroll: identical to gross_wages_cents in 44,088 of 44,088 rows, which is exactly the state that makes box 1 wrong and is invisible without this comment.
subject_wages_cents int64 3. THE PORTION ACTUALLY TAXED, i.e. gross_subject after the annual wage base or exclusion is applied. Differs from gross_subject only where a cap bites — social security past the wage base, and taxes with their own ceiling. Uncapped taxes (Medicare, FIT) should equal gross_subject here. W-2 boxes 3 and 5 read this column on the FICA rows, which is why they DO show the benefit reduction while box 1 does not. Producers running STE: STE returns 0 here for income taxes (measured: 4,718 of 4,721 FIT rows), so this column cannot be the source for box 1 and gross_subject must carry it.
employee_liability_cents int64
employer_liability_cents int64
total_liability_cents int64
wage_base_cents int64 Wage base information
wage_base_remaining_cents int64
tax_rate double Tax calculation metadata - rate between 0 and 1
wage_type string
ingested_at google.protobuf.Timestamp Metadata
source_system_id string
payroll_run_id string Re-submission semantics (PAF-982 Phase 2 — pay-date pivot) payroll_run_id is the customer's external run identifier. Provenance for re-submission tracking; does not propagate to summary tables. submitted_at is the customer-attested "as-of" timestamp; primary tiebreaker in latest-wins natural-key dedup. Optional: dedup falls back to ingested_at then liability_id when omitted.
submitted_at google.protobuf.Timestamp
corrects_payroll_run_id string Restatement semantics — is this row a CORRECTION of an earlier one for the same natural key? correction_cause is the authoritative marker (!= UNSPECIFIED ⇒ a correction); a producer that cannot categorise the reason should send OTHER rather than leaving it unset. corrects_payroll_run_id is optional provenance naming the run being restated. Neither participates in the natural key — see TaxLiability.corrects_payroll_run_id for why putting them there would double liability instead of superseding it.
correction_cause com.symmetry.models.tax.LiabilityCorrectionCause
error_discovered_at google.protobuf.Timestamp When the producer discovered the error this row restates. Optional, and only meaningful alongside a correction_cause. NOT submitted_at (when they re-reported) and NOT ingested_at (when we received it) — Form 941-X needs the earliest DISCOVERY date across the corrected errors, and the adjustment-process deadline keys off the quarter of discovery. See TaxLiability.error_discovered_at for why it stays out of the natural key.
external_id string Optional, purely additive client reference for this one taxable line item — NOT required, and NOT the same thing as liability_id or payroll_run_id. liability_id is required but disposable: a producer sends a fresh one on every resubmission of the same business event (see payroll_run_id above; a restatement is a NEW message with a NEW liability_id). payroll_run_id names the RUN/BATCH a row arrived in, not this line item. Neither survives as a stable handle a client can use to recognize "the same taxable line" of theirs across a correction. external_id fills that gap for producers who want it: if sent, it is carried through to storage and to the natural-key-collision audit logs unchanged. It does NOT participate in NaturalKeys.taxLiabilityNaturalKey or any dedup/tiebreak logic — "same business event" is already recognized from the row's own business fields (employee_id, jurisdiction, tax_type, ste_tax_code, pay_date, wage_type), with no lookup and no client bookkeeping required. A producer that wants this field to mean something should resend the SAME value on a correction of the line it restates; nothing enforces that today.
tax_subdivision string Which sub-cell of ONE tax this row belongs to — ZONE_1 / ZONE_2 (NY MCTMT), RESIDENT / NON_RESIDENT, VOLUNTARY, ... Optional; blank means the tax is not subdivided. Canonicalised on the way in by TaxSubdivisions.canonical, exactly as wage_type is, because this field JOINS THE TAX-LIABILITY DEDUP KEY (see the field comment on the canonical TaxLiability). Two producers spelling one subdivision differently would fork the key and double the liability; two zones sharing a spelling would collapse and lose one. Free-text with only a length bound, for the same reason wage_type is: an enum would turn every subdivision a future agency invents into UNRECOGNIZED, and a key component that folds unknown values together is worse than one that carries them through untouched.
TenantScheduleConfigRaw

PAF-1921: the tenant-scoped sibling of CompanyTaxProfileRaw, minus company_id. Field numbers are renumbered contiguously (they are not a subset of the company message's) — this is a different message, not a projection of one.

Field Type Label Description
record_id string Version id - optional; server generates UUID7 if empty
tenant_id string
data_key string e.g. "LOOKBACK_SCHEDULING_ENABLED" (open vocabulary; service-side allowlist)
data_value string e.g. "true" | "false" (service-side allowlist for the lookback opt-in key)
is_active bool optional OPTIONAL, i.e. proto3 field presence, and that is load-bearing (Copilot review, PR #328). A boolean CSV cell has THREE states -- true, false, and MALFORMED -- while `bool` has two. With a plain bool, RecordToProtoMapper's Boolean.parseBoolean turns is_active="ture" into false, and false on THIS entity is a RETRACTION: it silently disables lookback scheduling for the tenant. EntityValidator could not tell that apart from a deliberate `false` once the information had been destroyed at the mapper. Presence restores the third state exactly where it is needed: the mapper leaves the field UNSET when the cell does not parse, and the validator rejects the record by name. An omitted column is rejected the same way, and for the same reason -- silence must not mean "retract". Wire-identical to `bool` on tag 5 (same encoding), so nothing downstream changes: the entity message keeps a plain `bool`, which is correct because by then the value has been validated and Iceberg needs a real boolean. Note common.proto's BenefitFlag comment explains why google.protobuf.BoolValue is the wrong tool for a three-valued boolean HERE -- LocalTableCreator maps MESSAGE to binary -- but that applies to ENTITY messages, which reach Iceberg. A *Raw message never does, and proto3 `optional` costs no schema surface at all.
effective_from google.protobuf.Timestamp Valid time - required
ingested_at google.protobuf.Timestamp Transaction time - server-set (= envelope timestamp); ignored if supplied
source_system_id string
WorksiteLocationRaw

Worksite location plaintext data

Field Type Label Description
location_id string Primary key - IGNORED on ingestion, server always generates UUID7 Populated in API responses
tenant_id string Tenant ID - required
company_id string Company ID - required
location_name string Location name
address AddressRaw Address - embedded for ingestion
address_id string Address ID - for API responses
local_jurisdiction_code string Local jurisdiction code (STE format)
subject_to_local_tax bool Subject to local tax
status com.symmetry.models.tax.LocationStatus Location status enum
created_at google.protobuf.Timestamp Timestamps
closed_at google.protobuf.Timestamp
sync com.symmetry.models.sync.SyncTracking optional Sync tracking - populated for API responses
ingested_at google.protobuf.Timestamp Ingestion metadata
source_system_id string
external_id string ── Client Reference (REQUIRED) ────────────────────────────────────────── Client's reference ID for this worksite location (e.g., "LOC-001" in their system) Used for deduplication: (tenant_id, company_id, external_id)
BatchCreateRequest
Field Type Label Description
address CreateAddressRequest
company CreateCompanyRequest
employee CreateEmployeeRequest
employment CreateEmploymentRequest
worksite_location CreateWorksiteLocationRequest
peo CreatePeoRequest
service_provider CreateServiceProviderRequest
preparer CreatePreparerRequest
bank_account CreateBankAccountRequest
ach_configuration CreateACHConfigurationRequest
state_tax_account CreateStateTaxAccountRequest
BatchError

Error detail for batch operations

Field Type Label Description
index int32 Index in the batch
entity_type string Type of entity that failed
entity_id string ID of entity (if available)
error_code string Machine-readable error code
error_message string Human-readable error message
BatchResponse

Response for batch operations

Field Type Label Description
total_processed int32
success_count int32
failure_count int32
errors BatchError repeated
BatchUpdateRequest
Field Type Label Description
address UpdateAddressRequest
company UpdateCompanyRequest
employee UpdateEmployeeRequest
employment UpdateEmploymentRequest
worksite_location UpdateWorksiteLocationRequest
peo UpdatePeoRequest
service_provider UpdateServiceProviderRequest
preparer UpdatePreparerRequest
bank_account UpdateBankAccountRequest
ach_configuration UpdateACHConfigurationRequest
state_tax_account UpdateStateTaxAccountRequest
CreateACHConfigurationRequest
Field Type Label Description
tenant_id string
owner_id string
owner_type com.symmetry.models.tax.OwnerType
immediate_destination string
immediate_origin string
company_name string
company_identification string
company_entry_description string
company_discretionary_data string
service_class_code com.symmetry.models.tax.ServiceClassCode
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
CreateAddressRequest
Field Type Label Description
tenant_id string
street_line_1 string
street_line_2 string
city string
state string
zip_code string
country string
address_type com.symmetry.models.tax.AddressType
encrypted_data_block string
kms_session_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required) - uses shared model
county_code google.protobuf.StringValue
county_name google.protobuf.StringValue
CreateAgencyDataRequest
Field Type Label Description
tenant_id string
owner_type com.symmetry.models.tax.OwnerType COMPANY / EMPLOYEE / PREPARER
owner_id string FK to company/employee/preparer
agency_id string e.g., "AK-DOLWD" (required, part of natural key)
field_name string e.g., "AK_GEO_CODE" (canonical natural key)
value string value for this owner
u_id string optional Symmetry field-type id (metadata)
state_code string optional 2-letter state (may be derived from agency_id)
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
CreateBankAccountRequest
Field Type Label Description
tenant_id string
owner_id string
owner_type com.symmetry.models.tax.OwnerType
routing_number string Plaintext PII (data-grpc encrypts)
account_number string Plaintext PII (data-grpc encrypts)
account_type com.symmetry.models.tax.AccountType
originating_dfi_id string
status com.symmetry.models.tax.AccountStatus
encrypted_data_block string
kms_session_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
account_holder_name string
CreateCompanyAddressRequest

Request to create an address and link it to a company (primary address)

Field Type Label Description
tenant_id string
company_id string
street_line_1 string Address details (plaintext - will be encrypted)
street_line_2 string
city string
state string
zip_code string
country string ISO 3-letter code, defaults to "USA"
address_type com.symmetry.models.tax.AddressType
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
CreateCompanyRequest
Field Type Label Description
tenant_id string
legal_name string
ein string
filing_mode com.symmetry.models.tax.FilingMode
primary_address_id string
state_tax_accounts string JSON string of state code to account ID mapping
encrypted_data_block string
kms_session_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
external_id string optional Client reference for deduplication
efin string
etin string
taxpayer_type com.symmetry.models.tax.TaxpayerType
business_entity_type com.symmetry.models.tax.TaxpayerType
mailing_address_id string
phone string
trade_name string Trade name / DBA (optional)
CreateEmployeeAddressRequest

Request to create an address and link it to an employee (home or mailing) This is an atomic operation that: 1. Decrypts employee's existing PII 2. Creates the address with encryption 3. Updates the employee with the new address_id

Field Type Label Description
tenant_id string
employee_id string
street_line_1 string Address details (plaintext - will be encrypted)
street_line_2 string
city string
state string
zip_code string
country string ISO 3-letter code, defaults to "USA"
address_type com.symmetry.models.tax.AddressType
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
CreateEmployeeRequest
Field Type Label Description
tenant_id string
ssn string
first_name string
last_name string
date_of_birth string
home_address_id string
mailing_address_id string
encrypted_data_block string
kms_session_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
external_id string optional Client reference for deduplication
source_company_id string optional
middle_name string
suffix string
CreateEmploymentRequest
Field Type Label Description
tenant_id string
employee_id string
company_id string
worksite_location_id string
hire_date google.protobuf.Timestamp
termination_date google.protobuf.Timestamp
status com.symmetry.models.tax.EmploymentStatus
annual_salary_cents int64
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
external_id string optional Client reference for deduplication
source_company_id string optional
CreatePeoAddressRequest

Request to create an address and link it to a PEO (primary address)

Field Type Label Description
tenant_id string
peo_id string
street_line_1 string Address details (plaintext - will be encrypted)
street_line_2 string
city string
state string
zip_code string
country string ISO 3-letter code, defaults to "USA"
address_type com.symmetry.models.tax.AddressType
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
CreatePeoRequest
Field Type Label Description
tenant_id string
legal_name string
ein string
primary_address_id string
encrypted_data_block string
kms_session_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
efin string
etin string
CreatePreparerRequest
Field Type Label Description
tenant_id string
owner_id string
owner_type com.symmetry.models.tax.OwnerType
firm_name string
first_name string
last_name string
email string
phone string
business_address_id string
ptin string
naic_code string
preparer_type com.symmetry.models.tax.PreparerType
self_employed bool
status com.symmetry.models.tax.PreparerStatus
encrypted_data_block string
kms_session_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
title string Free-text signature-block role (e.g. "Owner"). Plaintext, not PII.
role string
external_id string optional Client reference for deduplication — see GetPreparerRequest for the lookup side.
CreateServiceProviderAddressRequest

Request to create an address and link it to a ServiceProvider (primary address)

Field Type Label Description
tenant_id string
service_provider_id string
street_line_1 string Address details (plaintext - will be encrypted)
street_line_2 string
city string
state string
zip_code string
country string ISO 3-letter code, defaults to "USA"
address_type com.symmetry.models.tax.AddressType
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
CreateServiceProviderRequest
Field Type Label Description
tenant_id string
legal_name string
ein string
primary_address_id string
provider_type com.symmetry.models.tax.ServiceProviderType
files_on_behalf bool
encrypted_data_block string
kms_session_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
efin string
etin string
CreateStateTaxAccountRequest
Field Type Label Description
tenant_id string
company_id string
state string Two-letter state code (e.g., "CA")
ste_tax_code string FK to TaxDef.uniqueTaxId
tax_type string CMS tax-type code (open vocabulary)
account_number string Plaintext PII (data-grpc hashes + encrypts)
status string "ACTIVE" / "INACTIVE" / "SUSPENDED"
encrypted_data_block string
kms_session_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
CreateWorksiteLocationRequest
Field Type Label Description
tenant_id string
company_id string
location_name string
address_id string
local_jurisdiction_code string
subject_to_local_tax bool
status com.symmetry.models.tax.WorksiteStatus
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DecryptionAuditContext

Audit context for decrypted read operations (PII access). Required fields must be provided by the caller for compliance.

Field Type Label Description
requested_by string Who is requesting the decrypted data (user ID, email, or service account) REQUIRED - must identify the actual requestor, not just the service
requesting_service string Name of the calling service (e.g., "form-generation-service", "ui-backend")
requesting_role string Role or permission level of the requestor
business_justification string Explanation of why the data is needed (e.g., "Generating W-2 form for tax year 2024") REQUIRED - must provide meaningful business justification
ticket_reference string Support ticket, incident, or audit reference (e.g., "SUPPORT-12345", "AUDIT-2024-001")
correlation_id string Client-generated correlation ID for distributed tracing
client_ip string Original client IP address - should be passed by calling services when available If not provided, entity-grpc will attempt to extract from gRPC metadata (x-forwarded-for, x-real-ip) or fall back to the gRPC peer address
user_agent string Original client user-agent - should be passed by calling services when available
purpose AccessPurpose Categorized purpose for PII access - helps with compliance reporting and monitoring Valid values: CUSTOMER_SUPPORT, AUDIT, COMPLIANCE, DEBUG, MIGRATION, INVESTIGATION
DeleteACHConfigurationRequest
Field Type Label Description
tenant_id string
ach_config_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DeleteAddressRequest
Field Type Label Description
tenant_id string
address_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DeleteAgencyDataRequest
Field Type Label Description
tenant_id string
agency_data_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DeleteBankAccountRequest
Field Type Label Description
tenant_id string
bank_account_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DeleteCompanyRequest
Field Type Label Description
tenant_id string
company_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DeleteEmployeeRequest
Field Type Label Description
tenant_id string
employee_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DeleteEmploymentRequest
Field Type Label Description
tenant_id string
employment_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DeletePeoRequest
Field Type Label Description
tenant_id string
peo_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DeletePreparerRequest
Field Type Label Description
tenant_id string
preparer_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DeleteResponse

Response for delete operations

Field Type Label Description
success bool
message string
sync_status com.symmetry.models.sync.SyncStatus PENDING until Flink confirms
DeleteServiceProviderRequest
Field Type Label Description
tenant_id string
service_provider_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DeleteStateTaxAccountRequest
Field Type Label Description
tenant_id string
state_tax_account_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
DeleteWorksiteLocationRequest
Field Type Label Description
tenant_id string
location_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
EntitySearchCriterion

Single search criterion

Field Type Label Description
field_name string Field name matching proto field (e.g., "ssn", "first_name", "city")
value string Search value (plaintext - hashing/embedding handled internally)
boost float Optional: boost factor for this field in multi-field scoring (default 1.0). Used only when scoring_mode is SEARCH_SCORING_MODE_WEIGHTED. Higher boost values increase that field's influence on the final score. Formula: weighted_score = sum(score_i * boost_i) / sum(boost_i)
EntitySearchMatch

Individual match - ID and scores only

Field Type Label Description
entity_id string Entity identifier (use with Get{EntityType} RPC to fetch full entity)
entity_type string Entity type (echoed from request for convenience)
relevance_score float Combined relevance score (0.0-1.0)
field_scores map<EntitySearchMatch.FieldScoresEntry> repeated Per-field score breakdown (for debugging/transparency)
EntitySearchMatch.FieldScoresEntry
Field Type Label Description
key string
value FieldSearchScore
EntitySearchMetadata

Execution metadata

Field Type Label Description
criteria_processed int32
strategies_used map<EntitySearchMetadata.StrategiesUsedEntry> repeated
execution_time_ms int64
EntitySearchMetadata.StrategiesUsedEntry
Field Type Label Description
key string
value SearchStrategyType
EntitySearchOptions

Search options

Field Type Label Description
similarity_threshold float Similarity threshold for semantic fields (0.0-1.0, default 0.8)
limit int32 Maximum results to return (default 10, max 100)
include_deleted bool Include soft-deleted records (default false)
scoring_mode SearchScoringMode How to combine scores for multi-field searches
cursor string Pagination cursor (entity_id from last result)
EntitySearchRequest
Field Type Label Description
tenant_id string
entity_type string Entity type as string - validated against registered searchable entities Examples: "Employee", "Company", "Address", "Preparer" Case-insensitive, matched against FieldMetadataRegistry
criteria EntitySearchCriterion repeated Search criteria - each field auto-routes to appropriate strategy
options EntitySearchOptions Search options
EntitySearchResponse
Field Type Label Description
matches EntitySearchMatch repeated Scored matches (IDs only - fetch full entities via Get* RPCs)
total_count int32 Total matching count (may be approximate for large result sets)
next_cursor string Cursor for next page (empty if no more results)
metadata EntitySearchMetadata Execution metadata
FieldSearchScore

Per-field score with strategy info

Field Type Label Description
score float 0.0-1.0
strategy_used SearchStrategyType Which strategy was applied
GetACHConfigurationDecryptedRequest

Request for decrypted ACHConfiguration data

Field Type Label Description
tenant_id string
ach_config_id string
audit_context DecryptionAuditContext Required for PII access audit
GetACHConfigurationRequest
Field Type Label Description
tenant_id string
ach_config_id string
GetAddressDecryptedRequest

Request for decrypted Address data

Field Type Label Description
tenant_id string
address_id string
audit_context DecryptionAuditContext Required for PII access audit
GetAddressRequest
Field Type Label Description
tenant_id string
address_id string
GetAgencyDataRequest
Field Type Label Description
tenant_id string
agency_data_id string
GetBankAccountDecryptedRequest

Request for decrypted BankAccount data

Field Type Label Description
tenant_id string
bank_account_id string
audit_context DecryptionAuditContext Required for PII access audit
GetBankAccountRequest
Field Type Label Description
tenant_id string
bank_account_id string
GetCompanyContactDecryptedRequest
Field Type Label Description
tenant_id string
company_contact_id string
audit_context DecryptionAuditContext Required. Validated before the row is read, so a request without a justification never reaches the ciphertext.
GetCompanyContactRequest
Field Type Label Description
tenant_id string
company_contact_id string
GetCompanyDecryptedRequest

Request for decrypted Company data

Field Type Label Description
tenant_id string
company_id string
audit_context DecryptionAuditContext Required for PII access audit
GetCompanyRequest
Field Type Label Description
tenant_id string
company_id string optional Lookup by company_id (server-generated UUID7)
external_id string optional Lookup by external_id (client-provided reference) - alternative to company_id At least one of company_id or external_id must be provided
GetEmployeeDecryptedRequest

Request for decrypted Employee data

Field Type Label Description
tenant_id string
employee_id string
audit_context DecryptionAuditContext Required for PII access audit
GetEmployeeRequest
Field Type Label Description
tenant_id string
employee_id string optional Lookup by employee_id (server-generated UUID7)
external_id string optional Lookup by external_id (client-provided reference) - alternative to employee_id Note: external_id lookup also requires source_company_id for uniqueness
source_company_id string optional Source company ID - required when using external_id lookup Either employee_id OR (external_id + source_company_id) must be provided
GetEmploymentDecryptedRequest

Request for decrypted Employment data

Field Type Label Description
tenant_id string
employment_id string
audit_context DecryptionAuditContext Required for PII access audit
GetEmploymentRequest
Field Type Label Description
tenant_id string
employment_id string optional Lookup by employment_id (server-generated UUID7)
external_id string optional Lookup by external_id (client-provided reference) - alternative to employment_id Note: external_id lookup also requires source_company_id for uniqueness
source_company_id string optional Source company ID - required when using external_id lookup Either employment_id OR (external_id + source_company_id) must be provided
GetPeoDecryptedRequest

Request for decrypted PEO data

Field Type Label Description
tenant_id string
peo_id string
audit_context DecryptionAuditContext Required for PII access audit
GetPeoRequest
Field Type Label Description
tenant_id string
peo_id string
GetPreparerDecryptedRequest

Request for decrypted Preparer data

Field Type Label Description
tenant_id string
preparer_id string
audit_context DecryptionAuditContext Required for PII access audit
GetPreparerRequest
Field Type Label Description
tenant_id string
preparer_id string optional Lookup by preparer_id (server-generated UUID7)
external_id string optional Lookup by external_id (client-provided reference) - alternative to preparer_id Note: external_id lookup also requires owner_id for uniqueness (no source_company_id here — owner_id is already the unambiguous scope; see PreparerRaw.external_id)
owner_id string optional Owner ID - required when using external_id lookup Either preparer_id OR (external_id + owner_id) must be provided
GetReportingAgentAuthorizationRequest
Field Type Label Description
tenant_id string The VERSION id, not the grant. There is no "get the current grant" RPC because that answer depends on an as-of date, and baking today's date into a read would give a different result tomorrow for the same filed return.
authorization_id string
GetSearchableEntitiesRequest
Field Type Label Description
entity_type string Optional: filter to specific entity type
GetSearchableEntitiesResponse
Field Type Label Description
entities SearchableEntityDescriptor repeated
GetServiceProviderDecryptedRequest

Request for decrypted ServiceProvider data

Field Type Label Description
tenant_id string
service_provider_id string
audit_context DecryptionAuditContext Required for PII access audit
GetServiceProviderRequest
Field Type Label Description
tenant_id string
service_provider_id string
GetStateTaxAccountDecryptedRequest

Request for decrypted StateTaxAccount data (PAF-1420) Returns StateTaxAccountRaw with plaintext account_number unpacked from encrypted_data_block. ste_tax_code / tax_type / status are passed through as plaintext metadata.

Field Type Label Description
tenant_id string
state_tax_account_id string
audit_context DecryptionAuditContext Required for PII access audit
GetStateTaxAccountRequest
Field Type Label Description
tenant_id string
state_tax_account_id string
GetSyncTrackingRequest

Request to get the latest sync tracking for a specific entity entity_type is optional - if UNSPECIFIED, looks up by entity_id only

Field Type Label Description
tenant_id string
entity_type com.symmetry.models.sync.EntityType Optional - omit to lookup by entity_id only
entity_id string
GetSyncTrackingResponse

Response containing the latest sync tracking record

Field Type Label Description
sync_tracking com.symmetry.models.sync.SyncTracking
GetWorksiteLocationDecryptedRequest

Request for decrypted WorksiteLocation data

Field Type Label Description
tenant_id string
location_id string
audit_context DecryptionAuditContext Required for PII access audit
GetWorksiteLocationRequest
Field Type Label Description
tenant_id string
location_id string
ListACHConfigurationsRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
owner_id string Optional filters
owner_type com.symmetry.models.tax.OwnerType
ListAddressesRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
city string Optional filters
state string
address_type com.symmetry.models.tax.AddressType
ListAgencyDataRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
owner_type com.symmetry.models.tax.OwnerType Optional filters. owner_type + owner_id yields the per-owner collection.
owner_id string
agency_id string
field_name string
state_code string
ListBankAccountsRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
owner_id string Optional filters
owner_type com.symmetry.models.tax.OwnerType
status com.symmetry.models.tax.AccountStatus
ListCompaniesRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
filing_mode com.symmetry.models.tax.FilingMode Optional filters
ListCompanyContactsRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
company_id string Optional; blank means every company in the tenant.
ListEmployeesRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
last_name string Optional filters Hash for lookup
ListEmploymentsRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
employee_id string Optional filters
company_id string
status com.symmetry.models.tax.EmploymentStatus
ListFailedSyncTrackingRequest

Request to list failed sync records for a tenant

Field Type Label Description
tenant_id string
entity_type com.symmetry.models.sync.EntityType Optional filter by entity type
page_size int32
page_token string
ListPendingSyncTrackingRequest

Request to list pending sync records for a tenant

Field Type Label Description
tenant_id string
entity_type com.symmetry.models.sync.EntityType Optional filter by entity type
page_size int32
page_token string
ListPeosRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
ListPiiAccessAuditRequest

Request to list PII access audit records

Field Type Label Description
tenant_id string
record_type string Optional filter by entity type (EMPLOYEE, COMPANY, etc.)
requested_by string Optional filter by user who requested access
page_size int32 Max items per page (default: 50, max: 100)
ListPiiAccessAuditResponse

Response containing PII access audit records

Field Type Label Description
records PiiAccessAuditRecord repeated
total_count int32
ListPreparersRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
owner_id string Optional filters
owner_type com.symmetry.models.tax.OwnerType
status com.symmetry.models.tax.PreparerStatus
ListReportingAgentAuthorizationsRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
company_id string Optional filters. Together company_id + form_code yields every VERSION of one grant, which is what the history view needs -- several rows sharing them is the normal case, not a duplicate.
form_code string
agent_owner_id string
ListServiceProvidersRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
provider_type com.symmetry.models.tax.ServiceProviderType Optional filters
ListStateTaxAccountsRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
company_id string Optional filters
state string
tax_type string
status string
ste_tax_code string
ListSyncTrackingByCompanyRequest

Request to list sync tracking for all entities under a company Use this for SP/PEO tenants to view sync status for a specific managed company

Field Type Label Description
tenant_id string
company_id string Required - the company to query
entity_type com.symmetry.models.sync.EntityType Optional filter by entity type
page_size int32 Max items per page (default: 50, max: 100)
page_token string tracking_id for cursor-based pagination
ListSyncTrackingRequest

Request to list sync tracking history for an entity

Field Type Label Description
tenant_id string
entity_type com.symmetry.models.sync.EntityType
entity_id string
page_size int32 Max items per page (default: 50, max: 100)
page_token string tracking_id for cursor-based pagination
ListSyncTrackingResponse

Response containing a list of sync tracking records

Field Type Label Description
sync_tracking com.symmetry.models.sync.SyncTracking repeated
next_page_token string Empty if no more pages
total_count int32 Total count (if available)
ListWorksiteLocationsRequest
Field Type Label Description
tenant_id string
pagination PaginationOptions
company_id string Optional filters
status com.symmetry.models.tax.WorksiteStatus
PaginationOptions

Pagination options for list operations

Field Type Label Description
page_size int32 Max items per page (default: 100)
page_token string Token for next page
PiiAccessAuditRecord

A single PII access audit record

Field Type Label Description
audit_id string
tenant_id string
requested_by string
requesting_service string
requesting_role string
record_type string
record_id string
business_justification string
ticket_reference string
purpose string
request_timestamp google.protobuf.Timestamp
decryption_timestamp google.protobuf.Timestamp
completed_timestamp google.protobuf.Timestamp
status string PENDING, SUCCESS, FAILED, DENIED
failure_reason string
RestoreACHConfigurationRequest

Request to restore a soft-deleted ACHConfiguration

Field Type Label Description
tenant_id string
ach_config_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
RestoreAddressRequest

Request to restore a soft-deleted Address

Field Type Label Description
tenant_id string
address_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
RestoreAgencyDataRequest

Request to restore a soft-deleted AgencyData

Field Type Label Description
tenant_id string
agency_data_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
RestoreBankAccountRequest

Request to restore a soft-deleted BankAccount

Field Type Label Description
tenant_id string
bank_account_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
RestoreCompanyRequest

Request to restore a soft-deleted Company

Field Type Label Description
tenant_id string
company_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
RestoreEmployeeRequest

Request to restore a soft-deleted Employee

Field Type Label Description
tenant_id string
employee_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
RestoreEmploymentRequest

Request to restore a soft-deleted Employment

Field Type Label Description
tenant_id string
employment_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
RestorePeoRequest

Request to restore a soft-deleted PEO

Field Type Label Description
tenant_id string
peo_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
RestorePreparerRequest

Request to restore a soft-deleted Preparer

Field Type Label Description
tenant_id string
preparer_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
RestoreResponse

Response for restore operations (undoing soft delete)

Field Type Label Description
success bool
message string
sync_status com.symmetry.models.sync.SyncStatus PENDING until Flink confirms
RestoreServiceProviderRequest

Request to restore a soft-deleted ServiceProvider

Field Type Label Description
tenant_id string
service_provider_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
RestoreStateTaxAccountRequest

Request to restore a soft-deleted StateTaxAccount

Field Type Label Description
tenant_id string
state_tax_account_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
RestoreWorksiteLocationRequest

Request to restore a soft-deleted WorksiteLocation

Field Type Label Description
tenant_id string
location_id string
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
SearchACHConfigurationsRequest
Field Type Label Description
tenant_id string
page_size int32 Max 100, default 25
page_token string Cursor for next page (ach_config_id)
owner_id string Filters (all optional)
owner_type com.symmetry.models.tax.OwnerType
include_deleted bool Default false
sort_by ACHConfigurationSortField Sort options
sort_order SortOrder
SearchACHConfigurationsResponse
Field Type Label Description
ach_configurations com.symmetry.models.tax.ACHConfiguration repeated
next_page_token string Empty if no more pages
total_count int32 Total matching records
SearchAddressesRequest
Field Type Label Description
tenant_id string
page_size int32 Max 100, default 25
page_token string Cursor for next page (address_id)
city string Filters (all optional) - Note: street_line_1/2 are PII and cannot be filtered
state string
zip_code string
country string
address_type com.symmetry.models.tax.AddressType
validated google.protobuf.BoolValue Filter by validation status
include_deleted bool Default false
sort_by AddressSortField Sort options
sort_order SortOrder
SearchAddressesResponse
Field Type Label Description
addresses com.symmetry.models.tax.Address repeated
next_page_token string Empty if no more pages
total_count int32 Total matching records
SearchBankAccountsRequest
Field Type Label Description
tenant_id string
page_size int32 Max 100, default 25
page_token string Cursor for next page (bank_account_id)
owner_id string Filters (all optional) - Note: account/routing numbers are PII
owner_type com.symmetry.models.tax.OwnerType
account_type com.symmetry.models.tax.AccountType
status com.symmetry.models.tax.AccountStatus
include_deleted bool Default false
sort_by BankAccountSortField Sort options
sort_order SortOrder
SearchBankAccountsResponse
Field Type Label Description
bank_accounts com.symmetry.models.tax.BankAccount repeated
next_page_token string Empty if no more pages
total_count int32 Total matching records
SearchCompaniesRequest
Field Type Label Description
tenant_id string
page_size int32 Max 100, default 25
page_token string Cursor for next page (company_id)
filing_mode com.symmetry.models.tax.FilingMode Filters (all optional)
include_deleted bool Default false (exclude soft-deleted)
sort_by CompanySortField Sort options
sort_order SortOrder
SearchCompaniesResponse
Field Type Label Description
companies com.symmetry.models.tax.Company repeated
next_page_token string Empty if no more pages
total_count int32 Total matching records
SearchEmployeesRequest
Field Type Label Description
tenant_id string
page_size int32 Max 100, default 25
page_token string Cursor for next page (employee_id)
home_address_id string Filters (all optional) - Note: PII fields (ssn, first_name, last_name) cannot be filtered
mailing_address_id string
include_deleted bool Default false
sort_by EmployeeSortField Sort options
sort_order SortOrder
SearchEmployeesResponse
Field Type Label Description
employees com.symmetry.models.tax.Employee repeated
next_page_token string Empty if no more pages
total_count int32 Total matching records
SearchEmploymentsRequest
Field Type Label Description
tenant_id string
page_size int32 Max 100, default 25
page_token string Cursor for next page (employment_id)
employee_id string Filters (all optional)
company_id string
worksite_location_id string
status com.symmetry.models.tax.EmploymentStatus
include_deleted bool Default false
sort_by EmploymentSortField Sort options
sort_order SortOrder
SearchEmploymentsResponse
Field Type Label Description
employments com.symmetry.models.tax.Employment repeated
next_page_token string Empty if no more pages
total_count int32 Total matching records
SearchPeosRequest
Field Type Label Description
tenant_id string
page_size int32 Max 100, default 25
page_token string Cursor for next page (peo_id)
include_deleted bool Filters (all optional) - Note: legal_name, ein are PII and cannot be filtered Default false
sort_by PeoSortField Sort options
sort_order SortOrder
SearchPeosResponse
Field Type Label Description
peos com.symmetry.models.tax.PEO repeated
next_page_token string Empty if no more pages
total_count int32 Total matching records
SearchPreparersRequest
Field Type Label Description
tenant_id string
page_size int32 Max 100, default 25
page_token string Cursor for next page (preparer_id)
owner_id string Filters (all optional) - Note: name fields are PII and cannot be filtered
owner_type com.symmetry.models.tax.OwnerType
preparer_type com.symmetry.models.tax.PreparerType
status com.symmetry.models.tax.PreparerStatus
include_deleted bool Default false
sort_by PreparerSortField Sort options
sort_order SortOrder
SearchPreparersResponse
Field Type Label Description
preparers com.symmetry.models.tax.Preparer repeated
next_page_token string Empty if no more pages
total_count int32 Total matching records
SearchServiceProvidersRequest
Field Type Label Description
tenant_id string
page_size int32 Max 100, default 25
page_token string Cursor for next page (service_provider_id)
provider_type com.symmetry.models.tax.ServiceProviderType Filters (all optional) - Note: legal_name, ein are PII and cannot be filtered
files_on_behalf google.protobuf.BoolValue
include_deleted bool Default false
sort_by ServiceProviderSortField Sort options
sort_order SortOrder
SearchServiceProvidersResponse
Field Type Label Description
service_providers com.symmetry.models.tax.ServiceProvider repeated
next_page_token string Empty if no more pages
total_count int32 Total matching records
SearchStateTaxAccountsRequest
Field Type Label Description
tenant_id string
page_size int32 Max 100, default 25
page_token string Cursor for next page (state_tax_account_id)
company_id string Filters (all optional)
state string Two-letter state code
tax_type string CMS tax-type code (e.g., "SIT", "SUI")
status string "ACTIVE" / "INACTIVE" / "SUSPENDED"
ste_tax_code string FK to TaxDef.uniqueTaxId
include_deleted bool Default false
sort_by StateTaxAccountSortField Sort options
sort_order SortOrder
SearchStateTaxAccountsResponse
Field Type Label Description
state_tax_accounts com.symmetry.models.tax.StateTaxAccount repeated
next_page_token string Empty if no more pages
total_count int32 Total matching records
SearchWorksiteLocationsRequest
Field Type Label Description
tenant_id string
page_size int32 Max 100, default 25
page_token string Cursor for next page (location_id)
company_id string Filters (all optional)
status com.symmetry.models.tax.WorksiteStatus
include_deleted bool Default false
sort_by WorksiteLocationSortField Sort options
sort_order SortOrder
SearchWorksiteLocationsResponse
Field Type Label Description
worksite_locations com.symmetry.models.tax.WorksiteLocation repeated
next_page_token string Empty if no more pages
total_count int32 Total matching records
SearchableEntityDescriptor

Describes a searchable entity and its fields

Field Type Label Description
entity_type string e.g., "Employee"
get_rpc_name string e.g., "GetEmployee" (to fetch full entity)
fields SearchableFieldDescriptor repeated
SearchableFieldDescriptor

Describes a searchable field

Field Type Label Description
field_name string e.g., "ssn", "first_name"
default_strategy SearchStrategyType
description string Human-readable description
required bool Is this field typically required for search?
UpdateACHConfigurationRequest
Field Type Label Description
tenant_id string
ach_config_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
owner_id google.protobuf.StringValue
owner_type com.symmetry.models.tax.OwnerType
immediate_destination google.protobuf.StringValue
immediate_origin google.protobuf.StringValue
company_name google.protobuf.StringValue
company_identification google.protobuf.StringValue
company_entry_description google.protobuf.StringValue
company_discretionary_data google.protobuf.StringValue
service_class_code com.symmetry.models.tax.ServiceClassCode
UpdateAddressRequest
Field Type Label Description
tenant_id string
address_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
street_line_1 google.protobuf.StringValue Fields to update (null wrapper = no change)
street_line_2 google.protobuf.StringValue
city google.protobuf.StringValue
state google.protobuf.StringValue
zip_code google.protobuf.StringValue
country google.protobuf.StringValue
address_type com.symmetry.models.tax.AddressType
validated google.protobuf.BoolValue
encrypted_data_block google.protobuf.StringValue
kms_session_id google.protobuf.StringValue
county_code google.protobuf.StringValue
county_name google.protobuf.StringValue
UpdateAgencyDataRequest
Field Type Label Description
tenant_id string
agency_data_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
value google.protobuf.StringValue
u_id google.protobuf.StringValue
state_code google.protobuf.StringValue
field_name google.protobuf.StringValue mutating the natural key re-homes the value
agency_id google.protobuf.StringValue mutating the natural key re-homes the value
UpdateBankAccountRequest
Field Type Label Description
tenant_id string
bank_account_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
owner_id google.protobuf.StringValue
owner_type com.symmetry.models.tax.OwnerType
routing_number google.protobuf.StringValue Plaintext PII
account_number google.protobuf.StringValue Plaintext PII
account_type com.symmetry.models.tax.AccountType
originating_dfi_id google.protobuf.StringValue
verified google.protobuf.BoolValue
status com.symmetry.models.tax.AccountStatus
encrypted_data_block google.protobuf.StringValue
kms_session_id google.protobuf.StringValue
account_holder_name google.protobuf.StringValue
UpdateCompanyRequest
Field Type Label Description
tenant_id string
company_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
legal_name google.protobuf.StringValue
ein google.protobuf.StringValue
filing_mode com.symmetry.models.tax.FilingMode
primary_address_id google.protobuf.StringValue
state_tax_accounts google.protobuf.StringValue
encrypted_data_block google.protobuf.StringValue
kms_session_id google.protobuf.StringValue
external_id google.protobuf.StringValue Client reference for deduplication
efin google.protobuf.StringValue
etin google.protobuf.StringValue
taxpayer_type com.symmetry.models.tax.TaxpayerType
business_entity_type com.symmetry.models.tax.TaxpayerType
mailing_address_id google.protobuf.StringValue
phone google.protobuf.StringValue
trade_name google.protobuf.StringValue Trade name / DBA (optional; absent = preserve existing)
UpdateEmployeeRequest
Field Type Label Description
tenant_id string
employee_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
ssn google.protobuf.StringValue
first_name google.protobuf.StringValue
last_name google.protobuf.StringValue
date_of_birth google.protobuf.StringValue
home_address_id google.protobuf.StringValue
mailing_address_id google.protobuf.StringValue
encrypted_data_block google.protobuf.StringValue
kms_session_id google.protobuf.StringValue
external_id google.protobuf.StringValue Client reference for deduplication
source_company_id google.protobuf.StringValue
middle_name google.protobuf.StringValue
suffix google.protobuf.StringValue
UpdateEmploymentRequest
Field Type Label Description
tenant_id string
employment_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
employee_id google.protobuf.StringValue
company_id google.protobuf.StringValue
worksite_location_id google.protobuf.StringValue
hire_date google.protobuf.Timestamp
termination_date google.protobuf.Timestamp
status com.symmetry.models.tax.EmploymentStatus
annual_salary_cents google.protobuf.Int64Value
external_id google.protobuf.StringValue Client reference for deduplication
source_company_id google.protobuf.StringValue
UpdatePeoRequest
Field Type Label Description
tenant_id string
peo_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
legal_name google.protobuf.StringValue
ein google.protobuf.StringValue
primary_address_id google.protobuf.StringValue
encrypted_data_block google.protobuf.StringValue
kms_session_id google.protobuf.StringValue
efin google.protobuf.StringValue
etin google.protobuf.StringValue
UpdatePreparerRequest
Field Type Label Description
tenant_id string
preparer_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
owner_id google.protobuf.StringValue
owner_type com.symmetry.models.tax.OwnerType
firm_name google.protobuf.StringValue
first_name google.protobuf.StringValue
last_name google.protobuf.StringValue
email google.protobuf.StringValue
phone google.protobuf.StringValue
business_address_id google.protobuf.StringValue
ptin google.protobuf.StringValue
naic_code google.protobuf.StringValue
preparer_type com.symmetry.models.tax.PreparerType
self_employed google.protobuf.BoolValue
status com.symmetry.models.tax.PreparerStatus
encrypted_data_block google.protobuf.StringValue
kms_session_id google.protobuf.StringValue
title google.protobuf.StringValue Free-text signature-block role (e.g. "Owner"). Plaintext, not PII.
role google.protobuf.StringValue
external_id google.protobuf.StringValue Client reference for deduplication
UpdateServiceProviderRequest
Field Type Label Description
tenant_id string
service_provider_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
legal_name google.protobuf.StringValue
ein google.protobuf.StringValue
primary_address_id google.protobuf.StringValue
provider_type com.symmetry.models.tax.ServiceProviderType
files_on_behalf google.protobuf.BoolValue
encrypted_data_block google.protobuf.StringValue
kms_session_id google.protobuf.StringValue
efin google.protobuf.StringValue
etin google.protobuf.StringValue
UpdateStateTaxAccountRequest
Field Type Label Description
tenant_id string
state_tax_account_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
company_id google.protobuf.StringValue
state google.protobuf.StringValue
ste_tax_code google.protobuf.StringValue
tax_type google.protobuf.StringValue
account_number google.protobuf.StringValue Plaintext PII
status google.protobuf.StringValue
encrypted_data_block google.protobuf.StringValue
kms_session_id google.protobuf.StringValue
UpdateWorksiteLocationRequest
Field Type Label Description
tenant_id string
location_id string
sync_version int64 Required for optimistic locking
change com.symmetry.models.sync.ChangeMetadata Change tracking (required)
company_id google.protobuf.StringValue
location_name google.protobuf.StringValue
address_id google.protobuf.StringValue
local_jurisdiction_code google.protobuf.StringValue
subject_to_local_tax google.protobuf.BoolValue
status com.symmetry.models.tax.WorksiteStatus
ActorContext

Actor + audit metadata carried on every mutating request. actor_id is the reviewer/operator identity; reason is optional except where a request type marks it required; correlation_id is optional request tracing.

Field Type Label Description
actor_id string
reason string
correlation_id string
ApproveFilingRunRequest
Field Type Label Description
period_label string required
tenant_id string optional: approve only this tenant's jobs in the run
actor ActorContext
ApproveFilingRunResponse
Field Type Label Description
approved_count int32
skipped_count int32 ON_HOLD / EXCLUDED / not PENDING_REVIEW
CompanyActionRequest

Per-company transition request reused by Approve/Hold/Release/Reinclude/Recall.

Field Type Label Description
job_id string
company_id string
actor ActorContext
ExcludeCompanyRequest
Field Type Label Description
job_id string
company_id string
reason_code ExclusionReasonCode REQUIRED (must not be UNSPECIFIED)
actor ActorContext
ExcludeRecordsRequest
Field Type Label Description
period_label string required
company_id string required
job_id string optional; pin to a specific job
record_type string required: 'EMPLOYEE' | 'TAX_LIABILITY' | ...
record_ids string repeated required, non-empty
tenant_id string attribution
actor ActorContext
ExcludeRecordsResponse
Field Type Label Description
created RecordExclusion repeated
FilingJobRow

One filing_job row scoped to a company (the table PK is (job_id, company_id), so a PEO consolidated job_id may yield several rows).

Field Type Label Description
job_id string
company_id string
tenant_id string attribution only; filing_job is global
jurisdiction string
period_label string
status com.symmetry.models.tax.JobStatus
total_tax_amount_cents int64
employee_count int32
company_count int32
period_start google.protobuf.Timestamp
period_end google.protobuf.Timestamp
approved_at google.protobuf.Timestamp
approved_by string
exclusion_reason_code string set when status = JOB_STATUS_EXCLUDED
FilingRunSummary

Rollup for one run (period_label), aggregated across tenants.

Field Type Label Description
period_label string
job_count int32
company_count int32
total_tax_amount_cents int64
status_counts map<FilingRunSummary.StatusCountsEntry> repeated Count of company-jobs by JobStatus enum name (e.g. JOB_STATUS_PENDING_REVIEW).
FilingRunSummary.StatusCountsEntry
Field Type Label Description
key string
value int32
GetFilingRunRequest
Field Type Label Description
period_label string required
tenant_id string optional attribution filter
GetFilingRunResponse
Field Type Label Description
period_label string
rows FilingJobRow repeated
ListFilingJobsRequest
Field Type Label Description
period_label string optional
status com.symmetry.models.tax.JobStatus optional (UNSPECIFIED = any)
jurisdiction string optional
tenant_id string optional attribution filter
ListFilingRunsRequest
Field Type Label Description
period_label string optional exact-match filter
tenant_id string optional attribution filter
ListFilingRunsResponse
Field Type Label Description
runs FilingRunSummary repeated
ListRecordExclusionsRequest
Field Type Label Description
period_label string required
company_id string optional
RecordExclusion

Run-scoped record exclusion (mirrors filing_job_record_exclusion).

Field Type Label Description
exclusion_id string
tenant_id string
period_label string
company_id string
job_id string optional
record_type string 'EMPLOYEE' | 'TAX_LIABILITY' | ...
record_id string
reason string
excluded_by string
excluded_at google.protobuf.Timestamp
active bool
RejectFilingRunRequest
Field Type Label Description
period_label string required
tenant_id string optional: reject only this tenant's jobs in the run
actor ActorContext
RejectFilingRunResponse
Field Type Label Description
rejected_count int32 PENDING_REVIEW -> ON_HOLD
skipped_count int32 APPROVED / ON_HOLD / EXCLUDED / not PENDING_REVIEW
RemoveRecordExclusionRequest
Field Type Label Description
exclusion_id string
actor ActorContext
PayCalcSubmissionRaw

One PayCalc API call submitted for export. IMPORTANT: a submission covers N employees. PayCalcRequest contains a repeated PayCalcType, one entry per employee. Nothing in this message is per-employee, which is why there is no employee identifier here — employee identity lives inside the payloads, and leaves the protection service in the clear on the derived tax liabilities. See PayCalcLiabilityDeriver for why that is deliberate: the value is the customer's own identifier, not one we mint. ------------------------------------------------------------------------- IDENTITY - all server-resolved by the producer, never taken from a payload -------------------------------------------------------------------------

Field Type Label Description
trace_id string Unique identifier for this submission. Returned to the caller in the X-STE-Trace-Id response header and used as the correlation key across every system. A resubmitted identical calculation gets a NEW value: this identifies the submission, not the calculation.
tenant_id string Billing customer, resolved from the caller's API key. NOT the filing entity.
company_id string The EMPLOYER this calculation was performed for - the filing grain. Resolved from the caller's authentication profile, never accepted from the payload. Mandatory: a submission that cannot be attributed to an employer is rejected rather than exported, because filing it against the billing customer would silently commingle employers.
received_at google.protobuf.Timestamp When the producer received the calculation request.
source_system_id string Originating system, e.g. "STE-HOSTED".
schema_version string Schema version of the payload strings below. Set it deliberately; an unset version leaves no in-band way to tell shapes apart after a change.
request_json string Full PayCalc request as JSON, in the producer's native field naming. The protection service normalizes naming; the producer does not pre-transform. Contains a client-supplied employee identifier and wage aggregates per employee. Personal data.
response_json string Full PayCalc response as JSON: computed tax and wage amounts per employee. Personal data.
source_profile_id string Which of the producer's authentication profiles submitted this. WHY IT IS HERE: tenant_id is the billing CUSTOMER, and one customer can hold many profiles, each with its own API key and its own configured employer. Without this, a stored row says which customer and employer it was attributed to but not which key produced it — so a profile misconfigured with the wrong employer cannot have its rows identified and corrected, and a compromised key's records cannot be enumerated. PLAINTEXT, deliberately, and NOT marked encrypted. An earlier revision declared it encrypted so the generic mechanism would hash it into a tenant-scoped pseudonym on the envelope. That was removed for the same reason as the employee pseudonym: it is an operational reference for our own support and triage, not a personal identifier, and a readable value is what makes it useful in a query. Because it is no longer encrypted, the generic mechanism ignores it entirely — so PayCalcSubmissionProtector copies it onto the envelope explicitly, alongside the other metadata. Remove that copy and this field silently stops reaching the lake.
DeleteRequest

Request for deleting a record

Field Type Label Description
entity_type EntityType Type of entity to delete
entity_id string ID of the entity to delete
tenant_id string Tenant ID (required for partitioning)
source_system_id string Source system identifier
DeleteResponse

Response for delete operations

Field Type Label Description
success bool Whether the delete was successfully queued
entity_id string ID of the deleted entity
sequence_number string Kinesis sequence number for the delete record
error_message string Error message if success is false
IngestResponse

Response for single-record ingest operations

Field Type Label Description
success bool Whether the operation succeeded
entity_id string ID of the entity that was ingested
sequence_number string Kinesis sequence number (for tracking)
error_message string Error message if success is false
entity_type EntityType Entity type that was ingested
ingested_at google.protobuf.Timestamp Timestamp when the record was ingested
IngestionResponse

Response for streaming ingestion operations. On a streaming RPC the server may send this message multiple times: zero or more INTERIM messages (is_final = false) carrying cumulative progress counts while the batch is still draining, then exactly ONE TERMINAL message (is_final = true) carrying the authoritative totals and any per-record errors.

Field Type Label Description
batch_id string Unique batch identifier for tracking
successful_count int32 Number of records successfully queued to Kinesis (cumulative)
failed_count int32 Number of records that failed validation or streaming (cumulative)
errors RecordError repeated Details of failed records (validation errors, etc.). Only populated on the terminal response (final = true).
completed_at google.protobuf.Timestamp Timestamp when this response was produced
is_final bool True only for the terminal aggregate response; false for interim progress heartbeats. Clients should also treat the last response before stream completion as terminal regardless of this flag (back-compat safety).
RecordError

Error details for individual record failures

Field Type Label Description
record_id string ID of the failed record (from source_record_id or entity ID)
field string Field that caused the error (if applicable)
error_code string Error code for programmatic handling
error_message string Human-readable error description
AsOf

Audit-grade pinning, as a NARROWING of a pin that is always applied. When absent the service still pins the current snapshot of every referenced table at submit time and reports it back in QueryResult.pins, so a multi-table reconciliation cannot straddle a Flink checkpoint commit and disagree with itself. NOTE: pinning is under review. It is what makes taxfiling_dev.tax_liability unqueryable whenever a column has been added by DDL since the last data commit (ALTER creates no snapshot), and an operator asking "what does this look like now" wants the current state. The reproducibility argument for an unconditional pin belonged to the export path.

Field Type Label Description
timestamp google.protobuf.Timestamp
snapshot_id int64
ColumnDescriptor
Field Type Label Description
name string
type ValueType
description string
hashed bool True when the column holds a HASH rather than a plaintext value. employee.{ssn,first_name,last_name,date_of_birth} and company.{legal_name,trade_name,phone} are keyed HMAC-SHA256 MACs with HKDF-derived per-field keys from an Asherah master key (libs/encryption KeyedFieldHasher) — not reversible, and not equal to the plaintext. A consumer that does not know this prints a MAC where a name belongs. These columns are excluded from every client-facing projection; the flag exists so an internal caller that can select them cannot misread them.
DescribeReportTemplateRequest
Field Type Label Description
template_id string
ListReportTemplatesRequest
Field Type Label Description
audience_filter TemplateAudience
ListReportTemplatesResponse
Field Type Label Description
templates ReportTemplate repeated
QueryResult
Field Type Label Description
columns ColumnDescriptor repeated
rows Row repeated
next_page_token string Opaque; wraps the Athena NextToken together with the QueryExecutionId. NEVER an OFFSET. Trino has no server-side cursor, so LIMIT/OFFSET re-executes and re-scans the whole query for every page — O(pages) executions and O(pages) billing — and over an append-only table it is not even a stable window between pages.
truncated bool More rows exist beyond this page. Normally set TOGETHER with next_page_token: pass it to continue. Set WITHOUT a token when the whole result exceeded max-result-rows -- paging stops there by design, and the caller must narrow the query. Never total a truncated page: a partial sum is a different answer, not a smaller one.
pins SnapshotPin repeated
stats QueryStats
warnings string repeated Non-fatal advisories about how the result was produced. Empty when there is nothing to say.
QueryStats
Field Type Label Description
athena_query_execution_id string
bytes_scanned int64
engine_execution_millis int64
result_reused bool an Athena result-reuse hit, i.e. $0 for this execution
ReportTemplate
Field Type Label Description
template_id string e.g. "liability_detail_by_period"
title string
description string
audience TemplateAudience
tables string repeated every one of these gets a snapshot pin
parameters ReportTemplateParameter repeated
columns ColumnDescriptor repeated output shape; a stable contract
collapse_note string The collapse rule this template applies, in words. Present because "the totals are right" is not self-evident on this warehouse and a consumer cannot check it: mapped_field_output is append-only with a full row set per run, the 9 tax_liability_summary_* and 4 applied_benefit_summary_* tables are append-only forward tables, and applied_benefit is replicated at every jurisdiction carrying the FULL amount. Stating the rule lets a reader see that it WAS applied instead of assuming.
ReportTemplateParameter
Field Type Label Description
name string
type ParameterType
required bool
description string
default_value string
Row
Field Type Label Description
values Value repeated
RunReportRequest
Field Type Label Description
template_id string
parameters map<RunReportRequest.ParametersEntry> repeated Bound as TYPED literals against the template's declared parameter types. Never interpolated as text — see sql/SqlLiterals.
as_of AsOf
tenant_scope TenantScope internal principals only
max_rows int32 rows per PAGE; clamped to max-interactive-rows
page_token string A previous QueryResult.next_page_token. Resend the same request with it set. Signed and bound to the principal and tenant it was issued to, and valid for a limited time; one presented by anyone else is PERMISSION_DENIED, and an invalid or expired one is INVALID_ARGUMENT.
RunReportRequest.ParametersEntry
Field Type Label Description
key string
value string
SnapshotPin

What was actually read. One entry per referenced table, always populated.

Field Type Label Description
table string
snapshot_id int64
committed_at google.protobuf.Timestamp
TenantScope

Cross-tenant NARROWING for an internal operator. Not an identity claim. Ignored-and-refused for CLIENT principals; required for INTERNAL_READER and INTERNAL_ADMIN, and the tenant must be active in the tenant registry before it reaches a predicate.

Field Type Label Description
tenant_id string Exactly one tenant. `repeated` is deliberately omitted in v1: a multi-tenant result set has no safe default shaping (whose column order? whose collapse?) and no caller has asked for one.
Value
Field Type Label Description
is_null bool Explicit, because a typed zero and SQL NULL are different answers and a money column must not report 0 for "no row".
string_value string
int64_value int64
double_value double
bool_value bool
timestamp_value google.protobuf.Timestamp
date_value string ISO yyyy-MM-dd

Enums

ServingStatusEnum

Health status values for gRPC health checking protocol.

Name Number Description
UNKNOWN 0 Status unknown (should not be returned by a healthy server)
SERVING 1 Service is healthy and accepting requests
NOT_SERVING 2 Service is unhealthy and not accepting requests
SERVICE_UNKNOWN 3 Service name is not known (Watch RPC only)
AccountStatusEnum

Account status

Name Number Description
ACCOUNT_STATUS_UNSPECIFIED 0
ACCOUNT_STATUS_ACTIVE 1
ACCOUNT_STATUS_INACTIVE 2
ACCOUNT_STATUS_SUSPENDED 3
AccountTypeEnum

Account type

Name Number Description
ACCOUNT_TYPE_UNSPECIFIED 0
ACCOUNT_TYPE_CHECKING 1
ACCOUNT_TYPE_SAVINGS 2
AddressTypeEnum

Address type classification

Name Number Description
ADDRESS_TYPE_UNSPECIFIED 0
ADDRESS_TYPE_BUSINESS 1 Company or preparer business address
ADDRESS_TYPE_RESIDENTIAL 2 Employee home address
ADDRESS_TYPE_MAILING 3 Mailing address if different from physical
AgencyBankStatusEnum

Agency bank status

Name Number Description
AGENCY_BANK_STATUS_UNSPECIFIED 0
AGENCY_BANK_STATUS_ACTIVE 1 Currently accepting payments
AGENCY_BANK_STATUS_DEPRECATED 2 No longer in use, historical record
AgencyCreditKindEnum

NACHA payment status WHAT THE AGENCY SAID ABOUT A CREDIT — the only axis that matters, because every kind here is AGENCY-ASSERTED. This is deliberately NOT a "type of adjustment": DepositAdjustmentType mixed client-asserted prepayments (PREPAID_LIABILITY) with agency-asserted credits (PRIOR_CREDIT) and derivable ones (OVERPAYMENT) in one flat enum, so a consumer could never tell who was claiming what. One party per record, several kinds of statement from that party. The amount is ALWAYS POSITIVE; the kind carries the direction. A signed amount plus a kind gives two ways to say the same thing and they eventually disagree — DepositAdjustment's "positive = credit" comment against an unsigned ADJUSTMENT type is exactly that trap.

Name Number Description
AGENCY_CREDIT_KIND_UNSPECIFIED 0
AGENCY_CREDIT_KIND_CREDIT_HELD 1 The agency holds a credit for this filer. The ONLY kind that reduces tax owed.
AGENCY_CREDIT_KIND_CREDIT_APPLIED 2 The agency applied the credit to a period. It is spent: the return for that period shows the benefit, and the credit must not also be claimed on a later one.
AGENCY_CREDIT_KIND_CREDIT_EXPIRED 3 The credit lapsed unused. Distinct from APPLIED because the filer got nothing for it, which is a support conversation rather than an accounting entry.
AGENCY_CREDIT_KIND_REFUND_ISSUED 4 The agency PAID THE MONEY BACK. Reduces nothing on any return — the filer has the cash. This is why refunds are modelled here rather than ignored: a refund EXTINGUISHES a credit. An overpayment that was refunded must not also carry forward, and with no record of the refund there is nothing to stop it doing both. DepositAdjustmentType had a REFUND value that no consumer read at all, so a refunded overpayment stayed claimable forever.
AmendmentProcessEnum

Which of the two mutually-exclusive processes a 941-X amendment uses — Part 1, lines 1 and 2. DECLARED BY THE FILER, never derived. Line 1 (adjustment) credits or debits the correction against a future 941; line 2 (claim) asks for a refund or abatement. Where both are legally available the choice is a cash-flow decision that only the filer can make. The IRS constrains, but does not determine, the choice: line 2 is permissible ONLY when every corrected amount is OVERreported. If any line is underreported, line 1 is mandatory. The platform cannot settle this from a single figure either — a "mixed" correction can net to zero, so the sign of line 27 is not the test; the test is whether ANY line moved up. Contradiction between a declared CLAIM and an underreported line is therefore an ANOMALY to detect and block, not a value to compute.

Name Number Description
AMENDMENT_PROCESS_UNSPECIFIED 0
AMENDMENT_PROCESS_ADJUSTMENT 1 941-X Part 1 line 1 — adjusted employment tax return
AMENDMENT_PROCESS_CLAIM 2 941-X Part 1 line 2 — claim for refund or abatement
BenefitFlagEnum

A three-valued boolean: yes, no, or "the producer did not say". Used for the taxability flags on AppliedBenefit, where the distinction matters: a benefit whose pre-tax treatment is UNKNOWN is not the same as one known not to be pre-tax, and a plain bool cannot express the difference (proto3 has no field presence for scalars without `optional`). An enum rather than google.protobuf.BoolValue on purpose. LocalTableCreator maps MESSAGE to Timestamp/Duration and EVERYTHING ELSE TO BINARY, so a BoolValue would land as an unusable `binary` Iceberg column and ProtoTimestampConverter would take its ROW case. An enum maps ENUM -> String, exactly as tax_type and correction_cause already do. A closed vocabulary, so an enum is right here — the opposite of wage_type / tax_subdivision / benefit_category, which stay open strings because a future agency or engine can invent values.

Name Number Description
BENEFIT_FLAG_UNSPECIFIED 0 The producer did not assert either way
BENEFIT_FLAG_YES 1
BENEFIT_FLAG_NO 2
ContactTypeEnum

Company contact role (payroll admin vs signatory on filed returns)

Name Number Description
CONTACT_TYPE_UNSPECIFIED 0
CONTACT_TYPE_PAYROLL_ADMIN 1
CONTACT_TYPE_SIGNATORY 2
EmploymentStatusEnum

Employment status

Name Number Description
EMPLOYMENT_STATUS_UNSPECIFIED 0
EMPLOYMENT_STATUS_ACTIVE 1 Currently employed
EMPLOYMENT_STATUS_TERMINATED 2 Employment ended
EMPLOYMENT_STATUS_ON_LEAVE 3 Temporary leave (FMLA, etc.)
FilingJobTransitionKindEnum

Category of a filing-job lifecycle event (scheduler merge). filing_job is an immutable creation record in Iceberg; lifecycle changes are appended as FilingJobTransition events of one of these kinds. See entities.proto.

Name Number Description
FILING_JOB_TRANSITION_KIND_UNSPECIFIED 0
FILING_JOB_TRANSITION_KIND_APPROVAL 1 approve-for-generation gate (-> APPROVED)
FILING_JOB_TRANSITION_KIND_ARTIFACT 2 artifact generated / artifact-review gate
FILING_JOB_TRANSITION_KIND_DISTRIBUTION 3 distribution lifecycle
FILING_JOB_TRANSITION_KIND_EXCLUSION 4 company/records excluded from the run
FILING_JOB_TRANSITION_KIND_REGENERATE 5 re-approve after include/exclude => rebuild artifacts
FilingModeEnum

Filing mode

Name Number Description
FILING_MODE_UNSPECIFIED 0
FILING_MODE_DIRECT 1 Company files directly
FILING_MODE_PEO_MANAGED 2 PEO files under PEO's EIN
FILING_MODE_SERVICE_PROVIDER_MANAGED 3 Service provider files under company's EIN
FilingVariantEnum

Filing form variant for the agency_filing_form overlay child. Mirrors pufferfish's original/amendment Filing sub-structs.

Name Number Description
FILING_VARIANT_UNSPECIFIED 0
FILING_VARIANT_ORIGINAL 1 Original return form
FILING_VARIANT_AMENDMENT 2 Amended/corrected return form
JobStatusEnum

Job status

Name Number Description
JOB_STATUS_UNSPECIFIED 0
JOB_STATUS_CREATED 1 Job created, awaiting processing
JOB_STATUS_DRAFT 9 Provisional manual/preview job for an open (not-yet-closed)
JOB_STATUS_PENDING_REVIEW 2 period; partial amount. Does not block the canonical CREATED job produced when the period closes (anti-join counts >= CREATED). Awaiting manual review/approval
JOB_STATUS_APPROVED 3 Approved for submission
JOB_STATUS_PROCESSING 4 Currently processing
JOB_STATUS_SUBMITTED 5 Submitted to IRS/state
JOB_STATUS_CONFIRMED 6 Confirmed by IRS/state
JOB_STATUS_IRS_REJECTED 7 Rejected by IRS/state
JOB_STATUS_FAILED 8 System failure
JOB_STATUS_ON_HOLD 11 Paused for re-review; filing obligation still OPEN (chase it)
JOB_STATUS_EXCLUDED 10 (9 reassigned to JOB_STATUS_DRAFT on main; this moved to 11 on merge) Intentionally omitted from this run; obligation CLOSED for the run (don't chase it)
JurisdictionTypeEnum

Jurisdiction type for tax agencies

Name Number Description
JURISDICTION_TYPE_UNSPECIFIED 0
JURISDICTION_TYPE_FEDERAL 1 Federal agency (e.g., IRS)
JURISDICTION_TYPE_STATE 2 State agency
JURISDICTION_TYPE_LOCAL 3 Local/municipal agency
JURISDICTION_TYPE_COUNTY 4 County-level agency
LiabilityCorrectionCauseEnum

Why a TaxLiability row restates an earlier one for the same natural key. A restatement is a row that re-reports the SAME business event (same employee, tax, ste_tax_code and pay_date) with corrected figures — a recon or auto wage correction, not a second payroll. It shares the natural key with what it corrects, so latest-wins dedup supersedes the earlier version (NaturalKeys.latestOf). A non-UNSPECIFIED value is the AUTHORITATIVE marker that a row is a correction. Producers that cannot categorise the reason should send OTHER rather than leaving it unset — UNSPECIFIED means "an ordinary payroll", and two same-key rows that BOTH claim to be ordinary payrolls but carry different money is the ambiguous case ingestion alarms on (see TaxLiability.corrects_payroll_run_id). This describes the CAUSE (why the figures changed). It is deliberately NOT the amendment trigger_type vocabulary (total_tax_withheld_changed, ...), which describes the EFFECT (what changed) and is derived downstream by the amendment evaluator from the diff itself.

Name Number Description
LIABILITY_CORRECTION_CAUSE_UNSPECIFIED 0 Not a correction — an ordinary payroll run
LIABILITY_CORRECTION_CAUSE_WAGE_CORRECTION 1 Wages restated (misclassified/late/voided earnings)
LIABILITY_CORRECTION_CAUSE_RATE_CHANGE 2 Rate restated retroactively (e.g. a SUI rate notice)
LIABILITY_CORRECTION_CAUSE_BENEFIT_CORRECTION 3 Pre-tax benefit restated, moving subject wages
LIABILITY_CORRECTION_CAUSE_EXEMPTION_CHANGE 4 Exemption/withholding election applied retroactively
LIABILITY_CORRECTION_CAUSE_TAX_RECALCULATION 5 Tax miscomputed on correct wages (e.g. FICA)
LIABILITY_CORRECTION_CAUSE_OTHER 6 A correction whose cause is not categorised
LIABILITY_CORRECTION_CAUSE_WAGE_REVERSAL 7 Wages paid in error, reversed and recouped from the employee
LocationStatusEnum

Location status

Name Number Description
LOCATION_STATUS_UNSPECIFIED 0
LOCATION_STATUS_ACTIVE 1 Currently operating location
LOCATION_STATUS_CLOSED 2 Location closed/discontinued
OwnerTypeEnum

Owner type - identifies the parent entity for child entities like BankAccount, Preparer, AgencyData

Name Number Description
OWNER_TYPE_UNSPECIFIED 0
OWNER_TYPE_COMPANY 1
OWNER_TYPE_PEO 2
OWNER_TYPE_SERVICE_PROVIDER 3
OWNER_TYPE_EMPLOYEE 4
OWNER_TYPE_PREPARER 5
PreparerStatusEnum

Preparer status

Name Number Description
PREPARER_STATUS_UNSPECIFIED 0
PREPARER_STATUS_ACTIVE 1
PREPARER_STATUS_INACTIVE 2
PREPARER_STATUS_SUSPENDED 3
PreparerTypeEnum

Preparer type

Name Number Description
PREPARER_TYPE_UNSPECIFIED 0
PREPARER_TYPE_CPA 1 Certified Public Accountant
PREPARER_TYPE_EA 2 Enrolled Agent
PREPARER_TYPE_ATTORNEY 3 Tax attorney
PREPARER_TYPE_NON_CREDENTIALED 4 Non-credentialed preparer
ProvenanceEnum

Provenance of a shared agency catalog/overlay row (who owns the data). Stored in the DB as the human string: 'CMS' | 'SYMMETRY' | 'CMS+overlay'.

Name Number Description
PROVENANCE_UNSPECIFIED 0
PROVENANCE_CMS 1 Sourced from payroll-CMS; CMS authoritative
PROVENANCE_SYMMETRY 2 Net-new, Symmetry is system of record
PROVENANCE_CMS_OVERLAY 3 CMS base row decorated with Symmetry overlay fields
ServiceClassCodeEnum

Service class code for NACHA

Name Number Description
SERVICE_CLASS_CODE_UNSPECIFIED 0
SERVICE_CLASS_CODE_MIXED 200 Mixed debits and credits
SERVICE_CLASS_CODE_CREDITS_ONLY 220 Credits only
SERVICE_CLASS_CODE_DEBITS_ONLY 225 Debits only
ServiceProviderTypeEnum

Service provider type

Name Number Description
SERVICE_PROVIDER_TYPE_UNSPECIFIED 0
SERVICE_PROVIDER_TYPE_PAYROLL_SERVICE_PROVIDER 1 Full-service payroll
SERVICE_PROVIDER_TYPE_REPORTING_AGENT 2 IRS Form 8655
SERVICE_PROVIDER_TYPE_ACCOUNTING_FIRM 3 CPA/accounting firm
SERVICE_PROVIDER_TYPE_THIRD_PARTY_ADMINISTRATOR 4 TPA for benefits/payroll
TaxDepositOriginationEnum

WHO MOVED THE MONEY — the axis NACHAPaymentStatus cannot express. NACHAPayment describes an ACH payment SYMMETRY originated: it is keyed to a filing_job_id and carries bank_account_id, agency_bank_id and trace_number. Under the client-files model Symmetry is not the payer — the client deposits via EFTPS on their own and nothing in the platform observes it. A deposit stopped being something we EMIT and became something we must INGEST, and the ledger has to record one whoever made it. See TaxDeposit in transactions.proto.

Name Number Description
TAX_DEPOSIT_ORIGINATION_UNSPECIFIED 0
TAX_DEPOSIT_ORIGINATION_SYMMETRY_ACH 1 We generated the NACHA file (source_nacha_payment_id set)
TAX_DEPOSIT_ORIGINATION_CLIENT_EFTPS 2 Client paid EFTPS directly — the common federal case
TAX_DEPOSIT_ORIGINATION_CLIENT_CHECK 3 Client mailed a paper check/coupon
TAX_DEPOSIT_ORIGINATION_CLIENT_OTHER 4 Client paid by some other channel (agency portal, wire)
TAX_DEPOSIT_ORIGINATION_AGENCY_CREDIT_APPLIED 5 Agency applied an existing credit as a deposit
TaxDepositStatusEnum

WHERE THE MONEY IS in its lifecycle. RETURNED IS NOT FAILED, and the distinction is the whole point of having both. FAILED is a payment that never left — submission was rejected, nothing moved. RETURNED is an ACH return that arrives DAYS LATER, after the money appeared to have settled and the period looked closed: line 13 must drop, line 14 must reappear, and any rollup already computed for that period is stale. A naive "did we get a confirmation" check treats the two alike and silently keeps a reopened period closed. VOID is neither — it is a deposit that should never have been counted at all (mis-keyed entry, duplicate). Prefer superseding via TaxDeposit.supersedes_deposit_id, which preserves what was believed and when; VOID is for a row with no replacement.

Name Number Description
TAX_DEPOSIT_STATUS_UNSPECIFIED 0
TAX_DEPOSIT_STATUS_SCHEDULED 1 Intended, not yet sent
TAX_DEPOSIT_STATUS_SUBMITTED 2 Sent; awaiting settlement confirmation
TAX_DEPOSIT_STATUS_SETTLED 3 Confirmed by the agency/bank — money has moved
TAX_DEPOSIT_STATUS_FAILED 4 Submission rejected; the money never left
TAX_DEPOSIT_STATUS_RETURNED 5 Settled, then reversed (ACH return) — reopens a closed period
TAX_DEPOSIT_STATUS_VOID 6 Should never have counted; no replacement row
TaxTypeEnum

Tax type

Name Number Description
TAX_TYPE_UNSPECIFIED 0
TAX_TYPE_FIT 1 Federal Income Tax
TAX_TYPE_FICA_SS 2 Social Security (6.2%)
TAX_TYPE_FICA_MED 3 Medicare (1.45%)
TAX_TYPE_FICA_MED_ADDL 4 Additional Medicare (0.9%)
TAX_TYPE_FUTA 5 Federal Unemployment Tax
TAX_TYPE_SIT 6 State Income Tax
TAX_TYPE_SDI 7 State Disability Insurance
TAX_TYPE_SUI 8 State Unemployment Insurance
TAX_TYPE_LOCAL 9 Local/city taxes
TAX_TYPE_OTHER 10 A tax we recognise and deliberately do NOT fold into one of the buckets above. This is not a parse failure — that is TAX_TYPE_UNSPECIFIED, which means "nobody told us" or "we did not recognise the segment". OTHER means the opposite: the tax is known, and no coarse bucket describes it without over-selecting. State UI surcharges (`ER_SUTA_SC`), paid family leave (`FLI`), Oregon transit districts (`ER_TRANS`), workers' comp (`WC`), and the employer payroll-expense taxes (NY `ER_ECET`, NM `ER_EHT`, MA `ER_EMAC`, VT `ER_CCC`) are all here. WHY NOT FOLD THEM INTO THE NEAREST BUCKET. Each of those is reported on its OWN line of a state return, so bucketing a UI surcharge as SUI or a transit district as LOCAL makes two different taxes answer to one `taxTypes` selector and the figures over-report. Measured on the binding tables at the time this was added: 1 live binding selects SUI and 3 select LOCAL, so folding ~1,300 surcharge rows into SUI would have silently widened a rendered cell. That is the same defect as the 941 5a/5b tips bleed and the Oregon transit bleed. Losing nothing by bucketing them together is safe here in a way it would NOT be for tax_subdivision: the FINE identity is `ste_tax_code`, which is already in the liability natural key, so two OTHER taxes never collide. `taxTypes` is a coarse pre-filter, not an identity. Anything that must distinguish these taxes selects on `steTaxCodes`. Added because `TaxLiabilityRaw.tax_type`'s validation allowlist has always accepted the string "OTHER" while no enum value existed to receive it, so `TaxLiabilityMapper.toTaxType` fell to its default and every such row landed UNSPECIFIED — silently. Verified in the local warehouse: 288/288 NY `ER_ECET` rows, and ~4,000 rows across 10 tax-type segments in the fixture.
TaxpayerTypeEnum

Company legal/tax classification (from companyDetails.taxPayerType in artifact JSON)

Name Number Description
TAXPAYER_TYPE_UNSPECIFIED 0
TAXPAYER_TYPE_C_CORPORATION 1
TAXPAYER_TYPE_S_CORPORATION 2
TAXPAYER_TYPE_LLC 3
TAXPAYER_TYPE_NON_PROFIT 4
TAXPAYER_TYPE_CO_OWNERSHIP 5
TAXPAYER_TYPE_SOLE_PROPRIETOR 6
TAXPAYER_TYPE_GENERAL_PARTNERSHIP 7
WorksiteStatusEnum

Worksite location status (alias for LocationStatus, used by entity-grpc)

Name Number Description
WORKSITE_STATUS_UNSPECIFIED 0
WORKSITE_STATUS_ACTIVE 1 Currently operating location
WORKSITE_STATUS_CLOSED 2 Location closed/discontinued
ChangeSourceEnum

Source of entity changes for audit tracking

Name Number Description
CHANGE_SOURCE_UNSPECIFIED 0
CHANGE_SOURCE_UI 1 Web application user action
CHANGE_SOURCE_API 2 Direct API client call
CHANGE_SOURCE_BATCH_IMPORT 3 Bulk data import job
CHANGE_SOURCE_FLINK 4 Flink processing (derived data, corrections)
CHANGE_SOURCE_MIGRATION 5 Data migration script
CHANGE_SOURCE_ADMIN 6 Admin tool/console
CHANGE_SOURCE_SYSTEM 7 System-initiated (scheduled job, trigger)
EntityTypeEnum

Entity types that can be tracked

Name Number Description
ENTITY_TYPE_UNSPECIFIED 0
ENTITY_TYPE_ADDRESS 1
ENTITY_TYPE_COMPANY 2
ENTITY_TYPE_EMPLOYEE 3
ENTITY_TYPE_EMPLOYMENT 4
ENTITY_TYPE_WORKSITE_LOCATION 5
ENTITY_TYPE_PEO 6
ENTITY_TYPE_SERVICE_PROVIDER 7
ENTITY_TYPE_PREPARER 8
ENTITY_TYPE_BANKING_ACCOUNT 9
ENTITY_TYPE_ACH_CONFIGURATION 10
ENTITY_TYPE_STATE_TAX_ACCOUNT 11
ENTITY_TYPE_FILING_JOB_TRANSITION 12 scheduler merge: filing-job lifecycle event
SyncStatusEnum

Synchronization status for optimistic write pattern

Name Number Description
SYNC_STATUS_UNSPECIFIED 0
SYNC_STATUS_PENDING 1 Written to PostgreSQL, awaiting Flink processing
SYNC_STATUS_CONFIRMED 2 Flink confirmed, written to Iceberg
SYNC_STATUS_FAILED 3 Flink rejected, see error field for details
SYNC_STATUS_STALE 4 Iceberg has newer version (conflict)
ACHConfigurationSortFieldEnum
Name Number Description
ACH_CONFIGURATION_SORT_FIELD_UNSPECIFIED 0 Default: created_at DESC
ACH_CONFIGURATION_SORT_FIELD_CREATED_AT 1
ACH_CONFIGURATION_SORT_FIELD_UPDATED_AT 2
AccessPurposeEnum

Categorized purposes for PII access (for compliance and audit reporting)

Name Number Description
ACCESS_PURPOSE_UNSPECIFIED 0 Default/unset value
ACCESS_PURPOSE_CUSTOMER_SUPPORT 1
ACCESS_PURPOSE_AUDIT 2
ACCESS_PURPOSE_COMPLIANCE 3
ACCESS_PURPOSE_DEBUG 4
ACCESS_PURPOSE_MIGRATION 5
ACCESS_PURPOSE_INVESTIGATION 6
AddressSortFieldEnum
Name Number Description
ADDRESS_SORT_FIELD_UNSPECIFIED 0 Default: created_at DESC
ADDRESS_SORT_FIELD_CREATED_AT 1
ADDRESS_SORT_FIELD_UPDATED_AT 2
ADDRESS_SORT_FIELD_CITY 3
ADDRESS_SORT_FIELD_STATE 4
BankAccountSortFieldEnum
Name Number Description
BANK_ACCOUNT_SORT_FIELD_UNSPECIFIED 0 Default: created_at DESC
BANK_ACCOUNT_SORT_FIELD_CREATED_AT 1
BANK_ACCOUNT_SORT_FIELD_UPDATED_AT 2
CompanySortFieldEnum
Name Number Description
COMPANY_SORT_FIELD_UNSPECIFIED 0 Default: created_at DESC
COMPANY_SORT_FIELD_CREATED_AT 1
COMPANY_SORT_FIELD_UPDATED_AT 2
EmployeeSortFieldEnum
Name Number Description
EMPLOYEE_SORT_FIELD_UNSPECIFIED 0 Default: created_at DESC
EMPLOYEE_SORT_FIELD_CREATED_AT 1
EMPLOYEE_SORT_FIELD_UPDATED_AT 2
EmploymentSortFieldEnum
Name Number Description
EMPLOYMENT_SORT_FIELD_UNSPECIFIED 0 Default: created_at DESC
EMPLOYMENT_SORT_FIELD_CREATED_AT 1
EMPLOYMENT_SORT_FIELD_UPDATED_AT 2
EMPLOYMENT_SORT_FIELD_HIRE_DATE 3
EMPLOYMENT_SORT_FIELD_TERMINATION_DATE 4
PeoSortFieldEnum
Name Number Description
PEO_SORT_FIELD_UNSPECIFIED 0 Default: created_at DESC
PEO_SORT_FIELD_CREATED_AT 1
PEO_SORT_FIELD_UPDATED_AT 2
PreparerSortFieldEnum
Name Number Description
PREPARER_SORT_FIELD_UNSPECIFIED 0 Default: created_at DESC
PREPARER_SORT_FIELD_CREATED_AT 1
PREPARER_SORT_FIELD_UPDATED_AT 2
SearchScoringModeEnum

Score combination modes for multi-field searches

Name Number Description
SEARCH_SCORING_MODE_UNSPECIFIED 0 Default: AVERAGE
SEARCH_SCORING_MODE_AVERAGE 1 Simple arithmetic mean of all field scores
SEARCH_SCORING_MODE_MINIMUM 2 Minimum score (all fields must match well)
SEARCH_SCORING_MODE_MAXIMUM 3 Maximum score (any field match counts)
SEARCH_SCORING_MODE_WEIGHTED 4 Weighted average using boost factors: sum(score * boost) / sum(boost)
SearchStrategyTypeEnum

Search strategies (auto-detected from field metadata)

Name Number Description
SEARCH_STRATEGY_TYPE_UNSPECIFIED 0
SEARCH_STRATEGY_TYPE_HASH_EXACT 1 HMAC-SHA256 hash exact match (encrypted fields)
SEARCH_STRATEGY_TYPE_SEMANTIC 2 Vector embedding similarity (embeddable fields)
SEARCH_STRATEGY_TYPE_PLAINTEXT 3 Direct SQL equality (non-encrypted fields)
ServiceProviderSortFieldEnum
Name Number Description
SERVICE_PROVIDER_SORT_FIELD_UNSPECIFIED 0 Default: created_at DESC
SERVICE_PROVIDER_SORT_FIELD_CREATED_AT 1
SERVICE_PROVIDER_SORT_FIELD_UPDATED_AT 2
SortOrderEnum

Common sort order for all search operations

Name Number Description
SORT_ORDER_UNSPECIFIED 0 Default: DESC
SORT_ORDER_ASC 1
SORT_ORDER_DESC 2
StateTaxAccountSortFieldEnum
Name Number Description
STATE_TAX_ACCOUNT_SORT_FIELD_UNSPECIFIED 0 Default: registered_at DESC
STATE_TAX_ACCOUNT_SORT_FIELD_REGISTERED_AT 1
STATE_TAX_ACCOUNT_SORT_FIELD_UPDATED_AT 2
WorksiteLocationSortFieldEnum
Name Number Description
WORKSITE_LOCATION_SORT_FIELD_UNSPECIFIED 0 Default: created_at DESC
WORKSITE_LOCATION_SORT_FIELD_CREATED_AT 1
WORKSITE_LOCATION_SORT_FIELD_UPDATED_AT 2
WORKSITE_LOCATION_SORT_FIELD_LOCATION_NAME 3
ExclusionReasonCodeEnum

Mandatory reason code when excluding a company from a run (design §4.1). The enum NAME is persisted to filing_job.exclusion_reason_code.

Name Number Description
EXCLUSION_REASON_CODE_UNSPECIFIED 0
EXCLUSION_REASON_CODE_OFFBOARDED 1 Company no longer active
EXCLUSION_REASON_CODE_FILED_ELSEWHERE 2 Filed outside this platform
EXCLUSION_REASON_CODE_DUPLICATE 3 Duplicate job for the period
EXCLUSION_REASON_CODE_ZERO_NO_FILE 4 Zero liability, no filing required
EXCLUSION_REASON_CODE_DEFERRED_TO_AMENDED 5 Deferred to a later amended return
EntityTypeEnum

Entity types for routing and delete operations

Name Number Description
ENTITY_UNSPECIFIED 0
EMPLOYEE 1
COMPANY 2
TAX_LIABILITY 3
EMPLOYMENT 4
BANK_ACCOUNT 5
PREPARER 6
STATE_TAX_ACCOUNT 7
PEO 8
SERVICE_PROVIDER 9
ADDRESS 10
WORKSITE_LOCATION 11
ACH_CONFIGURATION 12
AGENCY_DATA 13
COMPANY_TAX_PROFILE 14 PAF-1616
TAX_EXEMPTION 15 PAF-1616
FILING_JOB_TRANSITION 16 scheduler merge
COMPANY_CONTACT 17 PAF-1606
EMPLOYEE_TAX_PROFILE 18 PAF-1606
EMPLOYEE_TAX_EXEMPTION 19 PAF-1606
TAX_CORRECTION 20 correction declaration (append-only)
PAYCALC_SUBMISSION 21 A PayCalc submission: one tax-calculation API call covering N employees. Not an entity in the CRUD sense — it is an immutable event that gets protected and published — but it flows through the same ingestion surface, so it needs a value to report in IngestResponse.
TAX_DEPOSIT 22 PAF-1765 deposit ledger (append-only)
APPLIED_BENEFIT 23 PAF-1820 benefit ledger (append-only)
REPORTING_AGENT_AUTHORIZATION 24 Form 8655 authority window (append-only)
AGENCY_CREDIT 25 PAF-1913 agency-asserted credit/refund (append-only)
PAYMENT_APPLICATION 26 PAF-1913 agency-asserted deposit allocation (append-only)
TENANT_SCHEDULE_CONFIG 27 PAF-1921 per-tenant schedule-orchestration settings (append-only). 27 is THIS enum's next free value. It deliberately does not match kinesis_envelope.proto's TENANT_SCHEDULE_CONFIG = 28: the two numberings diverged at 16 (COMPANY_CONTACT is 17 here and 18 there) and have never been kept in lockstep past COMPANY_TAX_PROFILE = 14.
ParameterTypeEnum
Name Number Description
PARAMETER_TYPE_UNSPECIFIED 0
PARAMETER_TYPE_STRING 1
PARAMETER_TYPE_INT64 2
PARAMETER_TYPE_DOUBLE 3
PARAMETER_TYPE_BOOL 4
PARAMETER_TYPE_DATE 5 ISO-8601 yyyy-MM-dd
PARAMETER_TYPE_TIMESTAMP 6 ISO-8601 instant
TemplateAudienceEnum
Name Number Description
TEMPLATE_AUDIENCE_UNSPECIFIED 0
TEMPLATE_AUDIENCE_CLIENT 1 visible to CLIENT principals
TEMPLATE_AUDIENCE_INTERNAL 2 INTERNAL_READER / INTERNAL_ADMIN only
ValueTypeEnum
Name Number Description
VALUE_TYPE_UNSPECIFIED 0
VALUE_TYPE_STRING 1
VALUE_TYPE_INT64 2
VALUE_TYPE_DOUBLE 3
VALUE_TYPE_BOOL 4
VALUE_TYPE_TIMESTAMP 5
VALUE_TYPE_DATE 6