# Calculate 401k paycheck Source: https://docs.symmetry.com/cbs/api-reference/401k-calculator/calculate-401k-paycheck /cbs/api-reference/cbs-api.yaml post /calculators/401k Performs paycheck calculation with 401k retirement contributions # Calculate 401k retirement projections Source: https://docs.symmetry.com/cbs/api-reference/401k-calculator/calculate-401k-retirement-projections /cbs/api-reference/cbs-api.yaml post /calculators/401k/data Calculates multi-year 401k retirement savings projections based on contribution rates and return assumptions. Returns array of yearly projection data (30 years). # Get 401k calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/401k-calculator/get-401k-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/401k Returns the 401k calculator model or field definitions for modeling retirement contribution paychecks # Get 401k data calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/401k-calculator/get-401k-data-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/401k/data Returns the 401k retirement savings planning data model or field definitions # Calculate 403b paycheck Source: https://docs.symmetry.com/cbs/api-reference/403b-calculator/calculate-403b-paycheck /cbs/api-reference/cbs-api.yaml post /calculators/403b Performs paycheck calculation with 403b retirement contributions # Calculate 403b retirement projections Source: https://docs.symmetry.com/cbs/api-reference/403b-calculator/calculate-403b-retirement-projections /cbs/api-reference/cbs-api.yaml post /calculators/403b/data Calculates multi-year 403b retirement savings projections based on contribution rates and return assumptions. Returns array of yearly projection data (30 years). # Get 403b calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/403b-calculator/get-403b-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/403b Returns the 403b calculator model or field definitions for modeling retirement contribution paychecks # Get 403b data calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/403b-calculator/get-403b-data-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/403b/data Returns the 403b retirement savings planning data model or field definitions # Calculate aggregate bonus paycheck Source: https://docs.symmetry.com/cbs/api-reference/aggregate-bonus-calculator/calculate-aggregate-bonus-paycheck /cbs/api-reference/cbs-api.yaml post /calculators/agbonus Performs paycheck calculation for aggregate bonus amounts # Get aggregate bonus calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/aggregate-bonus-calculator/get-aggregate-bonus-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/agbonus Returns the aggregate bonus calculator model or field definitions for calculating aggregate bonus paychecks # Get OpenAPI specification in YAML format Source: https://docs.symmetry.com/cbs/api-reference/api-specification/get-openapi-specification-in-yaml-format /cbs/api-reference/cbs-api.yaml get /docs/config Returns the complete OpenAPI 3.1 specification for CBS API in YAML format. This file can be imported into tools like Postman or used with OpenAPI code generators. The specification is alphabetically sorted for consistent output. # Get list of available calculators Source: https://docs.symmetry.com/cbs/api-reference/calculators/get-list-of-available-calculators /cbs/api-reference/cbs-api.yaml get /calculators Returns a list of all available paycheck calculators with HATEOAS links # Process batch calculator requests Source: https://docs.symmetry.com/cbs/api-reference/data/process-batch-calculator-requests /cbs/api-reference/cbs-api.yaml post /data/batch POST's multiple calculator calculations to the STE for async queue processing. Returns an array of calculation results with tax details and deductions. # Process batch calculator requests with PDF report generation Source: https://docs.symmetry.com/cbs/api-reference/data/process-batch-calculator-requests-with-pdf-report-generation /cbs/api-reference/cbs-api.yaml post /data/batch/print POST's multiple calculator calculations to the STE for async queue processing and generates a PDF report for all calculations. Returns base64-encoded PDF reports. The calculator property must be in all caps. # Get deduction object Source: https://docs.symmetry.com/cbs/api-reference/deductions/get-deduction-object /cbs/api-reference/cbs-api.yaml get /deductions Returns the deduction object for a specified deduction type. Supports custom, HSA, and 401k deduction types. Response format can be controlled via the format parameter (model, fields, or schema). # Calculate final pay paycheck Source: https://docs.symmetry.com/cbs/api-reference/final-pay-calculator/calculate-final-pay-paycheck /cbs/api-reference/cbs-api.yaml post /calculators/finalpay Performs final paycheck calculation with tips, severance, and multiple pay codes # Get final pay calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/final-pay-calculator/get-final-pay-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/finalpay Returns the final pay calculator model or field definitions for calculating final paychecks with tips and severance # Calculate flat bonus paycheck Source: https://docs.symmetry.com/cbs/api-reference/flat-bonus-calculator/calculate-flat-bonus-paycheck /cbs/api-reference/cbs-api.yaml post /calculators/flatbonus Performs paycheck calculation for flat bonus amounts # Get flat bonus calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/flat-bonus-calculator/get-flat-bonus-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/flatbonus Returns the flat bonus calculator model or field definitions for calculating flat bonus paychecks # Calculate grossup paycheck Source: https://docs.symmetry.com/cbs/api-reference/grossup-calculator/calculate-grossup-paycheck /cbs/api-reference/cbs-api.yaml post /calculators/grossup Performs reverse paycheck calculation to determine gross pay needed for desired net pay # Get grossup calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/grossup-calculator/get-grossup-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/grossup Returns the grossup calculator model or field definitions for reverse paycheck calculations # Calculate hourly paycheck Source: https://docs.symmetry.com/cbs/api-reference/hourly-calculator/calculate-hourly-paycheck /cbs/api-reference/cbs-api.yaml post /calculators/hourly Performs paycheck calculation for hourly-based employees # Get hourly calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/hourly-calculator/get-hourly-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/hourly Returns the hourly calculator model or field definitions for modeling hourly-based employee paychecks # CBS API overview Source: https://docs.symmetry.com/cbs/api-reference/overview Base URLs, authentication, and the tools (live Swagger and a Postman collection) for working with the Calculators by Symmetry API. The Calculators by Symmetry (CBS) API runs the same paycheck calculations as the hosted widgets, without the UI. Send a calculator request and receive the calculated withholding, deductions, and net pay as JSON. The endpoint reference in this section is generated from the CBS OpenAPI specification. > [!NOTE] > > New to the calculators API? Start with [Quickstart: Call the calculators API](/cbs/getting-started/call-api) for a complete first request, then use this reference for full endpoint and schema details. ## Environments and base URLs | Environment | Base URL | | - | - | | Production | `https://calculators.symmetry.com/api` | | Staging | `https://calculators-staging.symmetry.com/api` | Calculator endpoints sit under `/calculators`. For example, `https://calculators.symmetry.com/api/calculators/salary`. CBS runs across standard deployment tiers: **local**, **test**, **staging**, and **prod**. Production is the default target for the URLs above. If your integration needs a non-production tier, request the corresponding endpoint from Symmetry. > [!NOTE] > > The CBS API Postman environment sets its `endpointURL` to the current deployment tier on import, so you can switch tiers without hand-editing each request. Set your `apiKey` in Postman after importing. The hosted widget scripts load from a different host. See [Widget catalog](/cbs/widgets/catalog). ## Authentication Every request is authenticated with a single API key sent in the `pcc-api-key` header. There is no OAuth flow and no token exchange. ```text theme={null} pcc-api-key: yourKey ``` The widgets and the API use the same credential. See [Authentication model](/cbs/core-concepts/authentication-model) for validation rules and optional domain restrictions. ## Explore in Swagger API clients can access our Swagger documentation to test and explore each endpoint, and see a comprehensive overview of all available features. Our Swagger docs are available for both our production and staging environments. * [Production CBS API Swagger](https://calculators.symmetry.com/api/docs) * [Staging CBS API Swagger](https://calculators-staging.symmetry.com/api/docs) ### Authorize access to Swagger docs When accessing our Swagger docs, you will need to authorize to send a request to one of the CBS endpoints. To authorize, access the Swagger page and click the "Authorize" button to the right of the screen. Enter your API key and click "Authorize". ![Authorize Button.png](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/cbs/assets/images/43716369802516.png?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=8b3323022301b865c7f48f6a02adc055) ![Available Authorizations.png](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/cbs/assets/images/43716361727892.png?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=d02c6bb6ebaa0bcd83dc0471aebcb22e) Once authorized successfully, you'll see the lock symbol go from gray to black on each of the endpoints. This is your indication that you can send the sample requests to each endpoint. ![Lock Symbol.png](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/cbs/assets/images/43733592808980.png?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=3b10b0e7487241960ed2e5070bbbbc6c) Click into the desired endpoint, select "try it out," and then "execute." ![Try it out.png](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/cbs/assets/images/43733766695316.png?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=8a75d4566d27917964eac59c57b1e14d) ![Execute.png](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/cbs/assets/images/43733766696084.png?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=70a0356bc87149746a9e7616988a8ca0) You'll then receive the response from the endpoint. ## OpenAPI specification The CBS API serves its own specification at `/docs/config`. This endpoint requires no API key. ```bash theme={null} curl https://calculators.symmetry.com/api/docs/config ``` The endpoint pages in this section are generated from a committed snapshot of that specification. ## Next steps > **[Postman collection](/cbs/api-reference/postman-collection)** > > Download the CBS Postman collection and environment directly from the API. > **[Endpoints](/cbs/api-reference/calculators/get-list-of-available-calculators)** > > Full reference for every calculator, data, print, and utility endpoint. # Postman collection and environment for CBS API Source: https://docs.symmetry.com/cbs/api-reference/postman-collection Download the CBS Postman collection and environment directly from the API, set your apiKey, and send sample requests to every calculator endpoint. A Postman collection has been established to make testing the CBS API endpoints simple and intuitive. Symmetry serves the Postman files from the API itself rather than as static downloads, so the collection always reflects the current endpoints. ## Download from Swagger Both files come from the **Postman** endpoints, and both require authorization. | Endpoint | What it returns | | - | - | | `GET /postman/collection` | Sample requests for all CBS API endpoints. | | `GET /postman/environment` | The environment variables used across those requests. | > **[Postman endpoints in Swagger](https://calculators.symmetry.com/api/docs#/Postman)** > > Jump to the Postman section of the Swagger UI to execute both endpoints and save each response. > [!NOTE] > > **Both endpoints require your API key** > > `/postman/collection` and `/postman/environment` are authenticated with the `pcc-api-key` header. Requests without a valid key return HTTP 401. See [Authentication model](/cbs/core-concepts/authentication-model). ## Import into Postman **1. Authorize in Swagger and download both files** Authorize in the Swagger UI with your `pcc-api-key`, then execute `GET /postman/collection` and `GET /postman/environment` and save each response as a file. **2. Import both files into Postman** In Postman, select **Import**, then add the collection file and the environment file you downloaded. **3. Select the environment and set your credentials** Activate the environment, then supply your own `apiKey`. ## Environment variables There are two variables in the environment. | Variable | Value | | - | - | | `apiKey` | Provided by Symmetry's Client Success team. If you are unsure of your company's `apiKey`, please reach out to Client Success within the [Client Support Center](https://support.symmetry.com). | | `endpointURL` \* | `https://calculators.symmetry.com/api/calculators/` for production. | \* Set automatically on download. `/postman/environment` returns `endpointURL` already set for the deployment tier you download it from, so a staging download comes preconfigured for staging. The only value you need to enter by hand is `apiKey`. # Postman collection Source: https://docs.symmetry.com/cbs/api-reference/postman/postman-collection /cbs/api-reference/cbs-api.yaml get /postman/collection Returns the CBS API Postman collection. Import this URL into Postman to get all calculator request examples. Set apiKey in the environment after import. Requires pcc-api-key. # Postman environment Source: https://docs.symmetry.com/cbs/api-reference/postman/postman-environment /cbs/api-reference/cbs-api.yaml get /postman/environment Returns the CBS API Postman environment with endpointURL set for the current deployment tier (local/test/staging/prod). Set apiKey in Postman after import. Requires pcc-api-key. # Generate PDF report for calculator Source: https://docs.symmetry.com/cbs/api-reference/print/generate-pdf-report-for-calculator /cbs/api-reference/cbs-api.yaml post /print POST's a single calculator calculation to the STE and generates a PDF report. Returns base64-encoded PDF documents based on the specified report type. Calculator value in query parameter should match the calculator type in the request body. # Get print object with calculator example Source: https://docs.symmetry.com/cbs/api-reference/print/get-print-object-with-calculator-example /cbs/api-reference/cbs-api.yaml get /print Returns the print object structure with a salary calculator object added as an example. Used to understand the print data model structure for generating paycheck reports. # Calculate salary paycheck Source: https://docs.symmetry.com/cbs/api-reference/salary-calculator/calculate-salary-paycheck /cbs/api-reference/cbs-api.yaml post /calculators/salary Performs paycheck calculation for salary-based employees # Get salary calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/salary-calculator/get-salary-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/salary Returns the salary calculator model or field definitions for modeling salary-based employee paychecks # Get state-specific parameters Source: https://docs.symmetry.com/cbs/api-reference/state-parameters/get-state-specific-parameters /cbs/api-reference/cbs-api.yaml get /stateparms Returns all possible state parameters for the given state and calculator type. Used to help build out CBS-Widgets UI and calculate paychecks with the STE. Different states have different required fields and validations. # Calculate stock option paycheck Source: https://docs.symmetry.com/cbs/api-reference/stock-option-calculator/calculate-stock-option-paycheck /cbs/api-reference/cbs-api.yaml post /calculators/stockoption Performs paycheck calculation for stock option exercise income # Get stock option calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/stock-option-calculator/get-stock-option-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/stockoption Returns the stock option calculator model or field definitions for calculating stock option exercise income # Calculate tax tip paycheck Source: https://docs.symmetry.com/cbs/api-reference/tax-tip-calculator/calculate-tax-tip-paycheck /cbs/api-reference/cbs-api.yaml post /calculators/taxtip Performs paycheck calculation for hourly employees with reported tips # Get tax tip calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/tax-tip-calculator/get-tax-tip-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/taxtip Returns the tax tip calculator model or field definitions for calculating taxes on tips # Calculate tuition paycheck Source: https://docs.symmetry.com/cbs/api-reference/tuition-calculator/calculate-tuition-paycheck /cbs/api-reference/cbs-api.yaml post /calculators/tuition Performs paycheck calculation for tuition reimbursement income # Get tuition calculator configuration Source: https://docs.symmetry.com/cbs/api-reference/tuition-calculator/get-tuition-calculator-configuration /cbs/api-reference/cbs-api.yaml get /calculators/tuition Returns the tuition calculator model or field definitions for calculating tuition reimbursement income # API returns 401 Source: https://docs.symmetry.com/cbs/api/401-unauthorized Why the CBS API rejects a request with 401, and how to fix it. The CBS API returns **HTTP 401** for every authentication and key problem (there is no `403`). The body is `{ "message": "…" }`. | Message | Cause | Fix | | - | - | - | | `No api key found` | The `pcc-api-key` header is missing or blank | Send your key in the header on every request (the root/listing endpoint requires it too). | | `Invalid api key` | The key isn't recognized | Double-check the value. Need one? See [Getting support](/symmetry/support/getting-support). | | `Profile has been disabled` | The key is disabled | Contact Symmetry. | | `Profile does not have access to this product` | The key isn't entitled to CBS | Ask Symmetry to enable CBS for the key. | | `Failed security check` | The request origin isn't on the key's allowed domains | Add your domain to the key, or call from an allowed origin. | | `API rate limit has been exceeded.` | A trial key is over its cap | See [Rate limit exceeded](/cbs/api/rate-limit-exceeded). | > [!NOTE] > > Validation problems are **not** 401. A bad or missing body field returns **400**, and malformed JSON or an invalid state parameter returns **422**. See [Error codes and fixes](/cbs/api/error-codes). Authentication details: [Authentication model](/cbs/core-concepts/authentication-model). # Build a custom salary calculator UI Source: https://docs.symmetry.com/cbs/api/build-calc-ui Use the fields endpoint to render your own salary form, then POST inputs for results. The API lets you build your own UI while CBS does the math. The pattern is **discover the fields → render your form → POST for results**. ## 1. Get the field definitions `GET` the calculator with `format=fields` to receive the input fields, each with a name, label, default value, validation regex, and help text, so you can render a form dynamically: ```bash theme={null} curl "https://calculators.symmetry.com/api/calculators/salary?format=fields" \ -H "pcc-api-key: yourKey" ``` See [Request and response structure](/cbs/api/request-and-response) for the `model` vs `fields` shapes. ## 2. POST the inputs Send the collected values to the calculator endpoint: ```bash cURL theme={null} curl -X POST https://calculators.symmetry.com/api/calculators/salary \ -H "pcc-api-key: yourKey" \ -H "Content-Type: application/json" \ -d '{"state":"AZ","grossPay":1000,"grossPayType":"PAY_PER_PERIOD","payFrequency":"WEEKLY","grossPayYTD":0,"federalFilingStatusType":"SINGLE","federalAllowances":0,"additionalFederalWithholding":0}' ``` ```javascript JavaScript (fetch) theme={null} const res = await fetch("https://calculators.symmetry.com/api/calculators/salary", { method: "POST", headers: { "pcc-api-key": "yourKey", "Content-Type": "application/json" }, body: JSON.stringify({ state: "AZ", grossPay: 1000, grossPayType: "PAY_PER_PERIOD", payFrequency: "WEEKLY", grossPayYTD: 0, federalFilingStatusType: "SINGLE", federalAllowances: 0, additionalFederalWithholding: 0, }), }); const { content } = await res.json(); ``` ```python Python (requests) theme={null} import requests r = requests.post( "https://calculators.symmetry.com/api/calculators/salary", headers={"pcc-api-key": "yourKey", "Content-Type": "application/json"}, json={"state":"AZ","grossPay":1000,"grossPayType":"PAY_PER_PERIOD","payFrequency":"WEEKLY", "grossPayYTD":0,"federalFilingStatusType":"SINGLE","federalAllowances":0,"additionalFederalWithholding":0}, ) content = r.json()["content"] ``` ## 3. Render the results The response `content` holds `grossPay`, `federal`, `fica` (Social Security), `medicare`, `state`, `netPay`, and any `voluntaryDeductions`. Map those into your UI. Required fields are `grossPay`, `grossPayYTD`, `federalAllowances`, and `additionalFederalWithholding`; send `state` for a meaningful result. For every field, see [Object model and default properties](/cbs/api/object-model); for per-state inputs, see [State field reference](/cbs/api/state-fields). # Calculate bonus withholding Source: https://docs.symmetry.com/cbs/api/calc-bonus-withholding Choose between the percent (flat) method and the aggregate method for bonus withholding. CBS offers two bonus calculators. Pick based on how you want supplemental wages withheld. ## Percent (flat) method: `flatbonus` Withholds using the supplemental flat rate. POST to `flatbonus`: ```bash theme={null} curl -X POST https://calculators.symmetry.com/api/calculators/flatbonus \ -H "pcc-api-key: yourKey" -H "Content-Type: application/json" \ -d '{"state":"CO","bonus":5000,"payFrequency":"WEEKLY","grossPayYTD":0,"federalFilingStatusType":"SINGLE","federalAllowances":0,"additionalFederalWithholding":0}' ``` > [!WARNING] > > The percent method is not available in every state. For states that don't support it, the API returns HTTP **422** with a message like *"CALIFORNIA does not support this type of calculation. Please select a different state."* See [Handle states with no supplemental rate](/cbs/api/handle-no-supplemental-rate). ## Aggregate method: `agbonus` Combines the bonus with regular wages from the last paycheck to apply the correct withholding rates. POST to `agbonus` with the bonus plus the current pay context. Use this when the percent method isn't available or isn't appropriate. ## Choosing * **Percent/flat**: simplest; a fixed supplemental rate on the bonus (where supported). * **Aggregate**: more accurate for the employee's actual bracket; works in all states. For which method each calculator uses, see [Calculation methods by calculator](/cbs/core-concepts/calc-methods). # Calculate a final paycheck Source: https://docs.symmetry.com/cbs/api/calc-final-paycheck Handle termination pay with current and prior pay-period data using the final pay calculator. The `finalpay` calculator computes a termination payout, combining current-period pay with prior-period and additional amounts (accrued balances, severance, and so on). ## Pay codes Final pay is driven by a list of **pay codes**, each typed by when it applies: | `payCodes[n][type]` | Meaning | | - | - | | `CURRENT` | Current pay-period earnings. | | `PRIOR` | A prior pay period (include with `includePrior`). | | `ADDITIONAL` | Extra amounts such as severance. | Each pay code carries rates and hours (regular, overtime, double time, vacation, sick, holiday), plus optional `tipAmount`, `severanceAmount`, and an `override` flag to use custom overtime/double-time rates instead of the standard 1.5×/2×. See the full field list in [Object model and default properties](/cbs/api/object-model). ## Request POST to `finalpay` with the wage/tax inputs and a `payCodes` array. `includePrior` defaults to `true`, so prior pay codes are included in the calculation unless you set it `false`. ```bash theme={null} curl -X POST https://calculators.symmetry.com/api/calculators/finalpay \ -H "pcc-api-key: yourKey" -H "Content-Type: application/json" \ -d '{"state":"AZ","payFrequency":"WEEKLY","grossPayYTD":0,"federalFilingStatusType":"SINGLE","federalAllowances":0,"additionalFederalWithholding":0,"includePrior":true,"payCodes":[{"type":"CURRENT","rate":25,"hours":40}]}' ``` The response returns the combined gross, taxes, and net for the final check. # Generate a printable pay stub Source: https://docs.symmetry.com/cbs/api/generate-pay-stub Use the print object and report endpoint to produce a pay stub or check report. Beyond calculating a paycheck, the API can generate predefined reports. Check tops, pay stubs, earnings summaries, as a **base64-encoded PDF** you render on your side. ## Two ways to get a report * **On a calculation**: add `report=` to a calculator `POST`; the response includes the report(s) under `reporting.reports` as base64-encoded PDFs. * **Directly**: `GET`/`POST` the print endpoint: ```bash theme={null} curl "https://calculators.symmetry.com/api/print" \ -H "pcc-api-key: yourKey" ``` ## Report types `type` accepts: `all`, `checktop`, `checkmiddle`, `checkbottom`, `earnings`, `paystub` (for the final pay calculator), or omitted. ## The print object Populate the `print` object on your request to control what appears on the report: employee and company name/address, check number and date, remarks, and `emailReports`. See the full list in [Object model and default properties](/cbs/api/object-model). ## Rendering The report arrives **base64-encoded inside the JSON response** (not raw bytes). Decode it to bytes and write a `.pdf` (or stream it to the browser as a Blob). > [!NOTE] > > Widgets can also print or email reports directly. Those settings are enabled by Symmetry in the admin console. See [Special features](/cbs/widgets/special-features). # Migrate between widget and API Source: https://docs.symmetry.com/cbs/api/migrate-widget-to-api Move from a widget embed to a custom API integration, or back. Widgets and the API share the same key and the same calculators, so moving between them is mostly a UI change. The calculations stay consistent. ## Widget → API You'd move to the API when you need a custom UI, server-side calculations, or to store/report on results. 1. **Reuse your key.** The value in the widget's `?key=` is the same credential the API expects in the `pcc-api-key` header. See [Authentication model](/cbs/core-concepts/authentication-model). 2. **Map your widget defaults to a request body.** Any defaults you set via `data-defaults` become fields in the calculator model. See [Object model and default properties](/cbs/api/object-model). 3. **Render your own UI.** Use `format=fields` to drive a form; see [Build a custom salary calculator UI](/cbs/api/build-calc-ui). 4. **Move the key server-side** if you can. Unlike a widget key (visible in page source), API keys should stay on your server. ## API → widget Going the other way (to reduce build effort) is just embedding the widget script with the same key and moving your default values into [widget configuration](/cbs/widgets/configuration-methods). > [!NOTE] > > Results are consistent across both paths for the same inputs, because both run the same calculator. See [How calculators work](/cbs/core-concepts/how-calcs-work). # Model 401(k) and 403(b) contribution changes Source: https://docs.symmetry.com/cbs/api/model-401k-403b-contributions Show the paycheck impact of changing a retirement contribution. The `401k` and `403b` calculators show how a change in retirement contribution affects take-home pay (and, in the widget, retirement projections). ## Request POST to `401k` (or `403b`) with the wage inputs plus the contribution fields: ```bash theme={null} curl -X POST https://calculators.symmetry.com/api/calculators/401k \ -H "pcc-api-key: yourKey" -H "Content-Type: application/json" \ -d '{"state":"AZ","grossPay":2000,"grossPayType":"PAY_PER_PERIOD","payFrequency":"BI_WEEKLY","grossPayYTD":0,"federalFilingStatusType":"SINGLE","federalAllowances":0,"additionalFederalWithholding":0,"employeeContribution":6,"employeeContributionType":"PERCENT_OF_GROSS"}' ``` ## Contribution fields | Field | Meaning | | - | - | | `employeeContribution` / `employeeContributionType` | The employee's contribution amount and whether it's `PERCENT_OF_GROSS` or `FIXED_AMOUNT`. | | `employerContribution` / `employerContributionType` | Employer match amount and type. | | `contributionLimit` | The limit up to which the employer matches. | | `olderThan50` | Enables catch-up contributions. | To show a "before vs after," run the calculation twice, once at the current contribution and once at the proposed one, then compare `netPay`. For all fields and valid values, see [Object model and default properties](/cbs/api/object-model). > [!NOTE] > > A `457` deferred-comp calculator exists in the API model (mirrors 401(k)) but has no dedicated endpoint or widget. See [Available calculators](/cbs/overview/available-calcs). # Rate limits Source: https://docs.symmetry.com/cbs/api/rate-limits The CBS API usage-limit response headers and what happens when a trial key reaches its cap. The CBS API reports your usage on every response and enforces a calculation cap on trial keys. ## Limit-status headers Every API response includes these headers: | Header | Meaning | | - | - | | `X-Pcc-Api-Calc-Limit` | Calculations allowed for the key (`0` means unlimited). | | `X-Pcc-Api-Calc-Remaining` | Calculations remaining (`N/A` when unlimited). | | `X-Pcc-Api-Exp-Date` | The key's expiration date. | Monitor `X-Pcc-Api-Calc-Remaining` to avoid interruptions as you approach the cap. ## When you hit the limit The cap is checked on **calculation requests** (`POST`). When a trial key exceeds its limit, the API returns HTTP **401 Unauthorized** with: ```json theme={null} { "message": "API rate limit has been exceeded." } ``` > [!NOTE] > > The calculation cap applies to **trial keys**. Standard (paid) keys are not blocked by this limit. The headers still report status, but production usage isn't capped by this mechanism. Confirm your key's limits with Symmetry. For how keys are authenticated, see [Authentication model](/cbs/core-concepts/authentication-model). # Request and response structure Source: https://docs.symmetry.com/cbs/api/request-and-response The CBS API envelope: content plus _links, and the model, fields, and calculation response shapes. All CBS API traffic is JSON over HTTPS, and requests and responses share a consistent envelope. ## The response envelope Every response wraps its payload in a `content` object and a `_links` object (HATEOAS): ```json theme={null} { "content": { }, "_links": { "self": { "href": "https://calculators.symmetry.com/api/calculators/salary" } } } ``` `content` holds the requested data; `_links` gives the URL of the current resource plus related actions (such as a `calculate` link). ## GET a calculator: model vs. fields A `GET` on a calculator resource returns its definition. The `format` query parameter controls the shape: | `format` | Returns | | - | - | | `model` (default) | The calculator's model object, the input fields and their defaults. | | `fields` | An array of field descriptors: name, label, default value, validation regex, and help text. | ```bash theme={null} curl "https://calculators.symmetry.com/api/calculators/salary?format=fields" \ -H "pcc-api-key: yourKey" ``` Use `model` to see the object you'll POST; use `fields` to build a form dynamically. ## POST to calculate A `POST` to the calculator resource runs a calculation. The request body is the calculator's model (see [Object model and default properties](/cbs/api/object-model)); the response `content` holds the results: ```json theme={null} { "content": { "grossPay": 1000.00, "federal": 102.86, "fica": 49.60, "medicare": 11.60, "state": 21.06, "netPay": 494.88, "voluntaryDeductions": [] }, "_links": { "self": { "href": "https://calculators.symmetry.com/api/calculators/salary" } } } ``` `fica` is Social Security. Optional query params extend the response: `itd=true` adds a detailed tax breakdown, `report` returns a PDF report, and `showcalc` echoes the submitted inputs. See the [API quickstart](/cbs/getting-started/call-api) for an end-to-end example and the [endpoint reference](/cbs/api-reference/salary-calculator/calculate-salary-paycheck) for full request and response schemas. # Run a gross-up calculation Source: https://docs.symmetry.com/cbs/api/run-gross-up Determine the gross pay needed to hit a target net pay with the gross-up calculator. The gross-up calculator works backward from a target **net** pay to the **gross** wages required so that, after taxes and withholdings, the employee nets the target amount. ## When to use it Reach for the gross-up calculator whenever the net is fixed and the gross is flexible: * Net bonuses (for example, an employee should take home exactly \$5,000) * Relocation payments * Incentive or spot awards promised as a net amount ## Request POST to the `grossup` endpoint with the target net pay in `netPay`: ```bash theme={null} curl -X POST https://calculators.symmetry.com/api/calculators/grossup \ -H "pcc-api-key: yourKey" \ -H "Content-Type: application/json" \ -d '{"state":"AZ","netPay":1500,"payFrequency":"WEEKLY","grossPayYTD":0,"federalFilingStatusType":"SINGLE","federalAllowances":0,"additionalFederalWithholding":0}' ``` The response `content` returns the solved `grossPay` plus the resulting taxes and `netPay`. ## Example With `federalSupplementalFlat` set and a 2.5% Arizona withholding election, a \$1,500 target net for a Single filer paid weekly in Arizona solves to a gross of **\$2,210.77**. For the full breakdown and a hand check, see [How the gross-up calculation works](/cbs/core-concepts/gross-up-calc#worked-example). ## Behaviors to know * **Additional federal withholding is added on top** of the grossed-up amount, not solved into it, so `grossPay − additionalFederalWithholding` reconstructs the base gross-up. * **Supplemental settings change the result.** Setting `federalSupplementalFlat` (or a state supplemental flag) switches the method to flat; under flat supplemental, federal allowances don't affect the result. California has specific handling when a `SUPPLEMENTAL` state parameter is `BONUS` or `COMMISSION`. * **Results can differ by a cent** from a hand calculation, because intermediate sums are rounded to two decimals only at the end. See [Known API behaviors](/cbs/api/known-behaviors). For the concept behind this, see [How the gross-up calculation works](/cbs/core-concepts/gross-up-calc), and for the withholding method, see [Calculation methods by calculator](/cbs/core-concepts/calc-methods). # Test calculations against known values Source: https://docs.symmetry.com/cbs/api/test-known-values Validate your integration's output against expected results. To verify your integration, compare the API's output for a fixed set of inputs against values you expect. This checks your request wiring, not the tax math itself, which is maintained by Symmetry. ## Approach 1. **Pin your inputs.** Use a fixed request, including an explicit `checkDate`, so results don't shift as the current date advances. 2. **Capture the baseline.** Record the response `content` (`grossPay`, `federal`, `fica`, `medicare`, `state`, `netPay`) for that request. 3. **Assert on the fields you care about.** Compare each returned amount to your expected value in your test suite. ## What to watch for * **Pin the `checkDate`.** Tax tables change over time; without a fixed date, expected values drift with each tax update. * **Match the method.** The same wages produce different results across calculators and supplemental settings. Compare like-for-like. See [Calculation methods by calculator](/cbs/core-concepts/calc-methods). * **Display rounding.** Monetary results are returned to two decimals (cents). If results differ from what you expect, see [Calculation differs from expected value](/cbs/api/calc-differs). # Authentication model Source: https://docs.symmetry.com/cbs/core-concepts/authentication-model How CBS authenticates: one API key used by both the widget and the API, and how it compares to Symmetry's other products. CBS authenticates every request with a single **API key** tied to your account. There's no OAuth flow and no token exchange. ## One key, used two ways The widget key and the API key are the **same credential**: * **Widget**: pass the key in the script `src`: `…/salary.js?key=yourKey`. The widget reads it and forwards it to the API. * **API**: send that same value in the `pcc-api-key` request header. ```text theme={null} pcc-api-key: yourKey ``` > [!NOTE] > > A widget key is visible in page source by nature of client-side embedding. Keep API keys server-side and never commit them to source control. ## How this compares to other Symmetry products CBS uses a plain API key, not a JWT. Symmetry's products don't all authenticate the same way, so if you've integrated another one, note the difference: | Product | Authentication | | - | - | | Calculators by Symmetry | API key (`pcc-api-key` header) | | Symmetry Payroll Forms | JWT bearer token | | Symmetry Payroll Point | JWT bearer token | | Symmetry Tax Engine | API key (`Authorization` header; no bearer/JWT) | ## Key validation and restrictions The API validates your key on every request and enforces: * **Validity**: missing, invalid, or disabled keys are rejected with HTTP 401. * **Product access**: the key must be entitled to CBS. * **Domain restriction (optional)**: a key can be limited to specific allowed origins; requests from other domains are rejected. * **Expiration**: keys carry an expiration date, surfaced in the `X-Pcc-Api-Exp-Date` response header. Usage caps are covered separately in [Rate limits](/cbs/api/rate-limits). ## Getting a key To request a key or get help with an existing one, contact your Symmetry Client Success representative or reach out through the [Client Support Center](https://support.symmetry.com). See [Prerequisites](/cbs/getting-started/prerequisites) for details. # Calculation methods by calculator Source: https://docs.symmetry.com/cbs/core-concepts/calc-methods How each CBS calculator withholds federal and state tax: annualized, flat, or current aggregation, mapped per calculator (salary, bonus, gross-up, 401k). CBS supports multiple pay types, including regular salary, hourly wages, bonuses, and tips. The withholding calculation method depends on the calculator used. Each calculator applies a specific method for federal and state withholding. The following calculation methods are used by CBS: * Annualized: Annualizes the gross pay, calculates tax on the annualized amount, and then converts the tax amount back to a per pay period withholding amount. * Flat: Calculates withholding on special wage payments, such as bonuses, by using supplemental tax rates. * Current aggregation: Uses the current period paycheck amount to apply the correct withholding rates to special wage payments, such as bonuses. Use the following table to identify which calculation method applies to a specific calculator.
CalculatorFederal Calculation MethodState Calculation Method
Salary, Hourly, 401(k), 403(b), Final pay, Stock option, and TuitionAnnualizedAnnualized
Flat bonusFlatFlat
Aggregate bonusFlat or current aggregation for bonus amounts\ Annualized for gross pay amountsCurrent aggregation for bonus amounts\ Annualized for gross pay amounts
Gross-upFlat or current aggregation\ Annualized, for gross pay YTD if providedFlat or current aggregation\ Annualized, for gross pay YTD if provided
Tax tipAnnualizedAnnualized
# How calculators work Source: https://docs.symmetry.com/cbs/core-concepts/how-calcs-work A CBS calculator is one REST resource and one widget running the same gross-to-net calculation. Every CBS calculator is the same thing exposed two ways, a **REST resource** and a **widget**, both running the **same calculation**. ## One calculator, two front doors * **REST resource**, each calculator is an endpoint under `/api/calculators/` (for example `/api/calculators/salary`). A `GET` returns the calculator's field model; a `POST` runs a calculation. * **Widget**: the hosted widget for that calculator renders a UI and, under the hood, calls that same REST endpoint with your key. Because both paths run the same calculator, the inputs and results are identical whichever you use. For the list of calculators and which paths support each, see [Available calculators](/cbs/overview/available-calcs). ## The gross-to-net calculation A calculator takes wages, jurisdictions, and filing details and computes federal, state, and local withholding plus payroll taxes. Each one decides which inputs to collect and which method to apply, then returns the result through the widget or the REST endpoint. > [!NOTE] > > Symmetry maintains the tax rules behind the calculators, so results stay current with tax changes without any work on your side. ## From inputs to results **1. Collect inputs** Wages or rates, pay frequency, filing status, work and resident jurisdictions, and any calculator-specific fields (bonus amount, contribution percentage, and so on). **2. Apply the calculation method** Each calculator uses a specific withholding method: annualized, flat (supplemental), or current aggregation. See [Calculation methods by calculator](/cbs/core-concepts/calc-methods). **3. Run the calculation** The calculator computes federal, state, and local withholding plus Social Security and Medicare. **4. Return results** Gross pay, itemized taxes, deductions, and net pay, ready to display, store, or report on. See [Request and response structure](/cbs/api/request-and-response). > [!NOTE] > > The same wages can produce different taxes and net pay across calculators, because each calculator uses a different method. This is expected. # Quickstart: Call the calculators API Source: https://docs.symmetry.com/cbs/getting-started/call-api Authenticate, discover the calculators, and run your first CBS calculation. The calculators API lets you send inputs from your own interface and receive calculation results to display, store, or report on. This quickstart takes you from your first authenticated request to a live calculation. First, check the [prerequisites](/cbs/getting-started/prerequisites). Not sure the API is the right path? See [Widgets vs. API](/cbs/overview/choose-path). All requests use HTTPS and JSON and **require your key** in the `pcc-api-key` header. There's no anonymous access to the calculator endpoints. Every response wraps its data in a `content` object plus a `_links` object of related URLs (HATEOAS-style navigation). > [!NOTE] > > **Running these examples** > > The snippets below are [`curl`](https://curl.se) commands. Paste one into a terminal and replace `yourKey` with your key. > > * **Prefer a GUI?** Import the ready-made [Postman collection](/cbs/api-reference/postman-collection), set your key once, and run the requests there instead of using curl. > * **Readable output:** pipe a response through [`jq`](https://jqlang.github.io/jq/), e.g. `curl … | jq`. > * **On Windows:** curl's line-continuation (`\`) and the single-quoted `-d` body in step 4 don't work in Command Prompt. Use PowerShell, WSL, Git Bash, or Postman. ## 1. Authenticate Send your key in the `pcc-api-key` header on every request: ```bash theme={null} curl https://calculators.symmetry.com/api/calculators \ -H "pcc-api-key: yourKey" ``` ## 2. Discover the calculators The call above lists every calculator the API supports, as links under `_links`: ```json theme={null} { "content": "Calculators", "_links": { "self": { "href": "https://calculators.symmetry.com/api/calculators" }, "salary": { "href": "https://calculators.symmetry.com/api/calculators/salary" }, "hourly": { "href": "https://calculators.symmetry.com/api/calculators/hourly" } } } ``` It returns 11 calculators: `salary`, `hourly`, `grossup`, `bonus-percent`, `bonus-agregate`, `401k`, `403b`, `finalpay`, `stockoption`, `tuition`, and `taxtip`. Two are listed under names that differ from their endpoint paths: `bonus-percent` maps to `/flatbonus`, and `bonus-agregate` maps to `/agbonus`. ## 3. Inspect a calculator Before building a request, follow a calculator's link to retrieve its accepted fields, defaults, and options: ```bash theme={null} curl https://calculators.symmetry.com/api/calculators/salary \ -H "pcc-api-key: yourKey" ``` Use the response to see which inputs the calculator accepts and their defaults, then supply the ones you need in the next step. ## 4. Run your first calculation `POST` inputs to a calculator endpoint. A minimal salary calculation: ```bash theme={null} curl -X POST https://calculators.symmetry.com/api/calculators/salary \ -H "pcc-api-key: yourKey" \ -H "Content-Type: application/json" \ -d '{ "state": "AZ", "grossPay": 1000, "grossPayType": "PAY_PER_PERIOD", "payFrequency": "WEEKLY", "grossPayYTD": 0, "federalFilingStatusType": "SINGLE", "federalAllowances": 0, "additionalFederalWithholding": 0 }' ``` Required fields are `grossPay`, `grossPayYTD`, `federalAllowances`, and `additionalFederalWithholding`; send `state` for a meaningful result. The response returns the calculated taxes and net pay (shape below; values illustrative): ```json theme={null} { "content": { "grossPay": 1000.00, "federal": 102.86, "fica": 49.60, "medicare": 11.60, "state": 21.06, "netPay": 494.88, "voluntaryDeductions": [] }, "_links": { "self": { "href": "https://calculators.symmetry.com/api/calculators/salary" } } } ``` `fica` is Social Security. For every field and per-state inputs, see [Object model and default properties](/cbs/api/object-model) and [State field reference](/cbs/api/state-fields). ## Next steps > **[API how-tos](/cbs/api/build-calc-ui)** > > Call patterns, language examples, and reports. > **[API overview](/cbs/api-reference/overview)** > > Base URLs, authentication, and the full endpoint reference. Usage limits are returned in response headers. See [Rate limits](/cbs/api/rate-limits). # Quickstart: Embed a widget Source: https://docs.symmetry.com/cbs/getting-started/embed-widget Add a CBS widget to your page with a single script tag. CBS widgets are the fastest way to add a paycheck calculator to your site. Symmetry hosts and maintains the UI, and you embed it with one script tag. First, check the [prerequisites](/cbs/getting-started/prerequisites). Not sure widgets are the right path? See [Widgets vs. API](/cbs/overview/choose-path). ## 1. Add the script Copy this into a page served by your web server, replacing `yourKey` with your key. This example uses the **salary** calculator: ```html theme={null} ``` A minimal test page: ```html theme={null} Widget example
``` ## 2. Verify it renders Widgets can't run from a `file://` page; they must load over `http(s)://`. To view your test page: 1. Save the HTML above as `index.html`. 2. Open a terminal, `cd` into the folder that contains `index.html`, and start a local web server with one of these: * **Python:** `python3 -m http.server 8000` * **Node:** `npx serve` 3. Open the URL it prints (for example, `http://localhost:8000`) in your browser. The calculator should render and be ready to accept inputs. By default, it fills the width of its container; to set its size, see [Make a widget responsive](/cbs/widgets/make-responsive). > [!NOTE] > > If the key is missing or invalid, the widget shows an error instead of rendering the calculator (for example, *"Invalid api key"*). Double-check your key. See [Prerequisites](/cbs/getting-started/prerequisites). ## 3. Swap in a different calculator Change the script filename to any calculator type. For example `hourly.js`, `grossup.js`, or `flatbonus.js`: ```html theme={null} ``` See [Available calculators](/cbs/overview/available-calcs) for the full list. ## Next steps > **[Available calculators](/cbs/overview/available-calcs)** > > Every calculator you can embed as a widget. > **[How calculators work](/cbs/core-concepts/how-calcs-work)** > > The model behind every calculation, and what drives the results. More references: * [Configure your widget](/cbs/widgets/configuration-methods) * [Object model and default properties](/cbs/api/object-model) * [Widget catalog](/cbs/widgets/catalog) * [Customize styling](/cbs/widgets/customize-styling) * [Make a widget responsive](/cbs/widgets/make-responsive) * [Multi-calculator](/cbs/widgets/multi-calc) * [Examples](/cbs/widgets/examples) # Prerequisites Source: https://docs.symmetry.com/cbs/getting-started/prerequisites What you need before embedding a CBS widget or calling the calculators API: your key, supported browsers, and hosting. Before you start with [widgets](/cbs/getting-started/embed-widget) or the [calculators API](/cbs/getting-started/call-api), make sure you have the following. ## Your key CBS uses a **single key** for both integration paths: * **Widgets:** pass the key in the script tag's `src`: ```html theme={null} ``` * **Calculators API:** send the *same* value in the `pcc-api-key` request header: ```http theme={null} pcc-api-key: yourKey ``` It's one credential: the widget reads the key from its own script tag and forwards it to the API as `pcc-api-key`. To request a key or retrieve an existing one, contact your Symmetry Client Success representative or reach out through the [Client Support Center](https://support.symmetry.com). ## Supported browsers (widgets) CBS widgets run in current versions of the major browsers (Chrome, Edge, Firefox, Safari). **Internet Explorer is not supported**: the widget shows an unsupported-browser message instead of loading. > [!NOTE] > > There is no formal minimum-version matrix; any modern, evergreen browser works. ## Hosting * **Widgets:** must load from a web server over `http(s)://`, not opened directly from the local file system (`file://`). A widget reads its host from its own script URL, so it needs a live page URL to render. * **Calculators API:** always accessed over **HTTPS**. ## Key limits and restrictions * **Domain restriction:** a key can be limited to specific domains, so it only works on sites you control. See [Authentication model](/cbs/core-concepts/authentication-model). * **Trial key cap:** trial keys have a calculation limit. Once it's reached, the API returns a 401 error ("API rate limit has been exceeded"). See [Rate limits](/cbs/api/rate-limits). ## Next > **[Quickstart: Embed a widget](/cbs/getting-started/embed-widget)** > > Add a calculator to a page with one script tag. > **[Quickstart: Call the calculators API](/cbs/getting-started/call-api)** > > Authenticate and run your first calculation. # Available calculators Source: https://docs.symmetry.com/cbs/overview/available-calcs Every calculator offered by Calculators by Symmetry (CBS), with a one-line description and the integration paths that support it. This is the full list of CBS calculators. Most are available on both [integration paths](/cbs/overview/choose-path) (as an embeddable widget and through the API); exceptions are noted. ## Calculator types | Calculator | Description | Widget | API | | - | - | :-: | :-: | | **Salary** | Net ("take-home") pay from a per-period or annual salary. | ✓ | ✓ | | **Hourly** | Take-home pay from up to six hourly pay rates. | ✓ | ✓ | | **Gross-up** | Work backward from a target net pay to the required gross wages. | ✓ | ✓ | | **Flat bonus** | Withhold on a bonus using supplemental (flat) tax rates. | ✓ | ✓ | | **Aggregate bonus** | Withhold on a bonus using the aggregate method (combined with regular wages). | ✓ | ✓ | | **401(k)** | Show how 401(k) contributions affect a paycheck and retirement savings. | ✓ | ✓ | | **403(b)** | Show how 403(b) contributions affect a paycheck and retirement savings. | ✓ | ✓ | | **457** | 457(b) deferred-comp calculator (mirrors 401(k)). | ✗ | model only¹ | | **Final pay** | Termination payout using current and prior pay-period information. | ✓ | ✓ | | **Stock option** | Net gain or loss from exercising or selling stock, and taxes owed. | ✓ | ✓ | | **Tuition** | Tax impact of a tuition-reimbursement amount. | ✓ | ✓ | | **Tax tip** | Like the hourly calculator, with a tip amount added to compute taxes. | ✓ | ✓ | ¹ **457** has no dedicated widget and is not a listed API endpoint. It's reachable only through the API's model, print, and state-parameter flows when a 457 calculator type is supplied. > [!NOTE] > > In the API's `/calculators` listing, the two bonus calculators are named `bonus-percent` (flat bonus) and `bonus-agregate` (aggregate bonus); the widget and URL names are `flatbonus` and `agbonus`. > [!NOTE] > > Supplemental bonus methods are state-by-state compliant. Some states do not support the flat bonus (percent) method. For example: AZ, CT, DE, HI, KY, LA, MA, MS, NJ, UT, WY, DC, and PR. ## Multi-calculator In CBS, **multi-calculator** is a **widget-only** layout feature, not a calculation type. It places up to four calculators side by side on one page and includes a copy button to reuse inputs across them. It has no API endpoint. See [Multi-calculator](/cbs/widgets/multi-calc). ## Calculation methods The withholding method varies by calculator (annualized, flat, or current aggregation). For the per-calculator breakdown, see [Calculation methods by calculator](/cbs/core-concepts/calc-methods). # Widgets vs. API Source: https://docs.symmetry.com/cbs/overview/choose-path Decide between Calculators by Symmetry (CBS) widgets and the calculators API based on what you're trying to build. Calculators by Symmetry (CBS) has two integration paths: embeddable **widgets** and the **calculators API**. Both use the same Symmetry tax data and return the same compliant results; the difference is how much of the UI and hosting you own. ## What are you trying to do? > **Embed a calculator fast, with no UI work** > > Use **widgets**. Add one script tag and Symmetry hosts and renders the calculator UI. Configure defaults, theme, and help text inline, by URL, or in the admin console. > **Own the UI or run calculations server-side** > > Use the **API**. Send inputs from your own interface (or backend) and receive results to display, store, or report on. Pick by intent: * **"I just want a working calculator on a page."** → widgets * **"Fastest possible launch and a standard UI is fine."** → widgets * **"It needs to match my product's look exactly."** → API * **"I need calculations on my server or in batch."** → API * **"I want to store or report on results."** → API * **"Not sure, or want both?"** → Start with widgets and add the API later. They share the same calculators, so results stay consistent. ## At a glance | | Widgets | API | | - | - | - | | **Setup effort** | Lowest, add one script tag | Higher, build your own UI and requests | | **User interface** | Symmetry-managed, themeable | Fully custom, built by you | | **Where it runs** | In the browser, hosted by Symmetry | Your client or server | | **Configuration** | Inline, by URL, or admin console | Request parameters | | **Best for** | Fast launch, standard calculator UI | Custom UX, server-side use, reporting | > [!NOTE] > > Both paths stay current with federal, state, and local tax changes automatically, so your choice comes down to control and integration depth, not accuracy. ## Next steps > **[Widgets quickstart](/cbs/getting-started/embed-widget)** > > Embed your first calculator in minutes. > **[API quickstart](/cbs/getting-started/call-api)** > > Make your first calculators API call. # Data and accuracy Source: https://docs.symmetry.com/cbs/overview/data-and-accuracy How CBS handles calculation data across widgets and the API, and where the accuracy of its results comes from. Widgets and the API run the same calculation against the same tax data, so everything on this page applies to both [integration paths](/cbs/overview/choose-path). ## Stateless calculations Calculations are **stateless**: CBS takes your inputs, runs the calculation, and returns the result. It does **not persist calculation inputs or results to a database**, and it holds no session state between requests. A widget calls the same API, so the same is true whichever path you use. ## Where accuracy comes from CBS tax calculations are performed by the Symmetry Tax Engine against Symmetry's maintained tax data, so a CBS result matches what the engine returns for the same inputs. Monetary results are returned to the cent (two decimal places). Because tax tables change over time, pin an explicit `checkDate` when you need a repeatable result. See [Test calculations against known values](/cbs/api/test-known-values). # What is Calculators by Symmetry (CBS)? Source: https://docs.symmetry.com/cbs/overview/what-is-cbs What Calculators by Symmetry (CBS) is: accurate, compliant paycheck calculators you embed as a widget or call as a REST API, and how the two paths differ. Calculators by Symmetry (CBS) lets you add accurate, compliant paycheck calculators to your website or application. Using Symmetry's tax data, CBS calculates federal, state, and local withholding so your users can estimate take-home pay, gross-up amounts, bonuses, retirement contributions, and more. Symmetry maintains the underlying tax data, so results reflect the latest federal, state, and local rules without you maintaining tax logic yourself. ## What you can do with CBS * Estimate net ("take-home") pay from salary or hourly wages * Reverse-engineer the gross pay needed to hit a target net (gross-up) * Model bonuses using flat or aggregate supplemental methods * Show the paycheck impact of 401(k) and 403(b) contributions * Calculate final pay, stock option, tuition, and tax tip scenarios See [Available calculators](/cbs/overview/available-calcs) for the full list. ## The two integration paths CBS offers two integration paths. Use either on its own, or combine them. > **Widgets** > > Symmetry-managed calculators you embed with a single script tag. The fastest way to launch. Configure defaults, theme, and help text inline, by URL, or through the admin console. > **API** > > Send calculator inputs from your own interface and receive results to display, store, or report on. Use it when you need a custom UI or server-side calculations. Not sure which fits your use case? See [Widgets vs. API](/cbs/overview/choose-path). ## What CBS is built for CBS produces paycheck **estimates**, figures you show someone so they can understand or plan around their pay. It fits a marketing site, an employee self-service portal, an onboarding flow, or an offer-letter tool. It isn't a payroll system of record. CBS doesn't run an actual pay run, file, or remit. If you need production withholding at scale, talk to your Symmetry representative about the right product. For how a calculation is put together, see [How calculators work](/cbs/core-concepts/how-calcs-work). ## Where to go next > **[Widgets quickstart](/cbs/getting-started/embed-widget)** > > Embed your first calculator widget. > **[Calculation methods by calculator](/cbs/core-concepts/calc-methods)** > > Understand how each calculator computes withholding. # Configuration methods Source: https://docs.symmetry.com/cbs/widgets/configuration-methods The three ways to configure a CBS widget: inline JSON, an external URL, and the admin console, and how they combine. A widget can be configured three ways. Use one, or combine all three; the same `data-defaults` object (a `model` of field values, plus `style` and `helptext`) applies to each method. ## Inline JSON Pass a JSON object in the `data-defaults` attribute of the script tag. Self-contained, with nothing to host. ```html theme={null} ``` ## External URL (JSONP) Point `data-defaults` at a hosted file that returns the object wrapped in `jsonCallback(...)`. Best for reusing configuration across pages. See [Load widget defaults from a URL](/cbs/widgets/defaults-from-url). ```html theme={null} ``` ## Admin console Set property/value pairs centrally, tied to your key, with no attribute needed. See [Manage widgets from the admin console](/cbs/widgets/admin-console). ## What you can configure The `data-defaults` object accepts three kinds of content: | Key | Sets | Reference | | - | - | - | | `model` | Prefilled calculator inputs, field values like `grossPay`, `payFrequency`, `voluntaryDeductions` | [Object model and default properties](/cbs/api/object-model) | | `style` | Colors, fonts, layout per region | [Styling reference](/cbs/widgets/styling) | | `helptext` | Custom field help text | [Help text customization](/cbs/widgets/customize-helptext) | For the complete list of configurable field names and accepted values, see [Object model and default properties](/cbs/api/object-model). ## How the methods combine When more than one method sets the same property, they resolve together. Use **inline** values for page-specific overrides on top of **URL** or **admin console** defaults. # Customize widget help text Source: https://docs.symmetry.com/cbs/widgets/customize-helptext Override the popup help text a widget shows when a field receives focus, or turn help text off entirely. Each calculator field can show popup help text on focus. You can override the text per field with an inline `helptext` object in the widget's [`data-defaults`](/cbs/widgets/configuration-methods). ## Custom help text Key the `helptext` object by field name: ```html theme={null} ``` Help text is set inline only. Unlike field values and styling, it isn't read from a [hosted URL](/cbs/widgets/defaults-from-url). ## Disable all help text Turn off every help-text popup by setting `helptext` to `false`: ```html theme={null} ``` ## Field names Help text can be set for any form field. For the list of field names, see [Object model and default properties](/cbs/api/object-model). # Load widget defaults from a URL Source: https://docs.symmetry.com/cbs/widgets/defaults-from-url Host a JSON file of widget default values and styling and point the widget at it via JSONP. Instead of embedding configuration in every script tag, host it in one file and point the widget at it. The widget fetches the file on load via AJAX using **JSONP** (a `jsonCallback` wrapper), so you can update default values and styling in one place. ## Point the widget at a URL Pass a `url` inside `data-defaults`: ```html theme={null} ``` ## Host the file as JSONP Wrap the object in `jsonCallback(...)`. Put field values under a `model` key; `style` sits at the top level: ```javascript theme={null} jsonCallback({ "model": { "grossPay": 2500, "payFrequency": "biweekly" }, "style": { "body": { "background-color": "#2f4f4f" }, "labels": { "color": "#fff" } } }); ``` This is the easiest way to set richer defaults such as multiple deductions. Help text can't be loaded this way. The URL file is read for field values (`model`) and `style` only. Set help text [inline](/cbs/widgets/customize-helptext). > [!NOTE] > > The widget still loads if the URL is unreachable or the JSON is malformed. It silently falls back to defaults rather than showing an error. Test your file before relying on it. For the full attribute list, see [Configuration methods](/cbs/widgets/configuration-methods). To manage defaults without hosting a file, see [Manage widgets from the admin console](/cbs/widgets/admin-console). # Embed a widget in common layouts Source: https://docs.symmetry.com/cbs/widgets/examples Recipes for embedding CBS widgets: employee self-service portals, popups, and multi-deduction setups. These recipes cover common ways to embed a widget. All use the salary widget, but any [calculator type](/cbs/widgets/catalog) works. ## Prefill multiple deductions from a URL Setting several deductions is easiest by loading them from a hosted file: ```html theme={null} ``` See [Load widget defaults from a URL](/cbs/widgets/defaults-from-url). ## Embed in an employee self-service portal When the calculator loads after login, the employee is known. Fetch their values from your database, serve them by URL, and apply branding inline at the same time: ```html theme={null} ``` ## Open the widget in a popup ```html jQuery UI dialog theme={null} ``` ```html Native JavaScript theme={null} ``` > [!TIP] > > For portals, combine URL-based [default values](/cbs/widgets/configuration-methods) with inline [theming](/cbs/widgets/customize-styling) so per-employee data and site branding apply together. # Make a widget responsive Source: https://docs.symmetry.com/cbs/widgets/make-responsive Fit a CBS widget into a fixed-width or fluid container. CBS widgets are **responsive**: a widget stretches to fill the width of its parent element. You control the size by controlling the container. ## Fluid (fill available width) Placed directly in the page or a full-width element, the widget expands to the viewport width: ```html theme={null} ``` ## Fixed width Wrap the widget in a container with a set width and it fits that width: ```html theme={null}
``` ## Tips * Set the width on the **parent element**, not the script tag. The widget reads its width from the container. * For side-by-side calculators, see [Multi-calculator](/cbs/widgets/multi-calc). If a widget isn't sizing the way you expect, see [Widget won't resize in my layout](/cbs/widgets/wont-resize). # Show calculators side by side Source: https://docs.symmetry.com/cbs/widgets/multi-calc Place up to four calculators next to each other with the multi-calculator widget. Use the **multi-calculator** widget to show up to four calculators side by side on one page, handy for comparing scenarios (for example, the same wages at different pay frequencies). ## Add the multi-calculator Use the `multi.js` script and set how many calculators and which type: ```html theme={null} ``` ## Attributes | Attribute | Description | Default | | - | - | - | | `data-calculator` | The calculator type to display. Accepts any [calculator type](/cbs/widgets/catalog). | `salary` | | `data-count` | Number of calculators to display (1–4). Values above four or non-numbers fall back to the default. | `2` | | `data-defaults` | Prefills fields, exactly as with a single widget. See [Configuration methods](/cbs/widgets/configuration-methods). | None | ## Copy inputs across calculators The multi-calculator includes a **copy button** that takes the inputs from the leftmost (first) calculator and applies them to the others, so you can set shared inputs once and vary just one field per column. > [!TIP] > > Give the container enough width for the number of calculators you show; each still follows the responsive rules in [Make a widget responsive](/cbs/widgets/make-responsive). # Enable optional widget features Source: https://docs.symmetry.com/cbs/widgets/special-features Turn on imputed income, calculation summation, and report printing or emailing. Widgets have several optional features you can turn on. Field-level features (imputed income, summation) are set inline in `data-defaults`; report printing and emailing are enabled by Symmetry in the admin console. ## Add imputed income Set `imputed` to `true` to add an **Add Other Income** button, letting users include imputed income in the calculation: ```html theme={null} ``` ## Enable running totals (summation) Set `sum` to `true` to add an **Add to memory** button that keeps a running total across calculations: ```html theme={null} ``` ## Print or email reports These are configured by Symmetry in the admin console. [Log a ticket](/symmetry/support/getting-support) to enable them: * **Disable report printing**: restrict the print options to `none`. * **Email reports**: email a PDF of each report to a designated address (usually your payroll department). Once enabled, an `email report` toggle in the print object lets the client turn it on or off. > [!NOTE] > > Because report printing/emailing is set in the admin console, include the intended behavior (and any delivery email address) in your request. See [Manage widgets from the admin console](/cbs/widgets/admin-console). # Quickstart: Look up a tax rate and filing instructions Source: https://docs.symmetry.com/guides/getting-started/quickstart Get productive in Guides fast: log in, Ask AI on Search, filter Taxes for rates, then open Filing Tax Program tabs for step-by-step instructions. This quickstart walks you through the fastest path to value in Symmetry Guides: logging in, asking a question, looking up a tax rate, and finding filing instructions for a tax program. ## 1. Log in to Symmetry Guides Symmetry Guides authenticates using Auth0. Access Guides through the tile on your Client Support Center home page, or go directly to [guides.symmetry.com](https://guides.symmetry.com/search). ## 2. Ask your first question From the **Search** page, type a question in plain language into the search field, for example a question about a local rate or a state's withholding filing rules. Click the **Ask AI** button (or press Enter) to get a summarized answer along with its sources. > [!TIP] > > Not sure what to ask? Example prompts appear below the search box to help you get started. ## 3. Look up a tax rate Click **Taxes** in the left navigation to search and filter tax-specific data: 1. Filter by jurisdiction, tax name or tax ID, effective date, or STE release to narrow down to a specific tax or group of taxes. 2. Click a tax row to view additional detail and tax record history. 3. Click **View record** within the tax detail to see full history for that line item. ## 4. Find filing instructions for a tax program Click **Filing** in the left navigation, then use the search field to find a specific tax program: 1. Select a row to open the **Tax Program** detail page. 2. Review the **Overview** tab for a summary of what's needed before filing, plus agency contact information. 3. Check the **Filing**, **Payments**, **Taxes**, and **Register** tabs (whichever are available for that program) for step-by-step guidance. ## Next steps > **[Webhooks](/guides/webhooks/overview)** > > Receive tax changes automatically instead of checking Guides manually. > **[Migrating from Tax Notification Service](/guides/migrating/from-tax-notification-service)** > > Moving from TNS to Guides, and what changes for your team. More references: * [Understanding tax records](/guides/core-concepts/tax-records) for what the Effective date, STE release, and Who pays fields mean * [Filing guide coverage](/guides/core-concepts/filing-guide-coverage) for why the available sections vary by tax program # Migrating from Tax Notification Service to Symmetry Guides Source: https://docs.symmetry.com/guides/migrating/from-tax-notification-service Plan your TNS-to-Guides migration: feature comparison, transition timeline, Client Support Center access, and Taxes/Filing field mapping. Symmetry Guides replaces the Tax Notification Service (TNS). This article walks you through what's changing, what to expect during the transition, and where to find your tax data in Symmetry Guides. ## What is Symmetry Guides? Symmetry Guides is designed to replace TNS and expand on everything it offered. Built on the same trusted tax research database that powers Symmetry's payroll tax products, Guides delivers real-time tax rates, wage bases, and compliance data across 7,000+ U.S. jurisdictions, as well as rate information for Canadian taxes. Guides also goes beyond TNS capabilities by including step-by-step tax filing information across U.S. jurisdictions, agency-specific contact details, and an AI-powered search feature. ## Demo video Watch a high-level demonstration comparing Tax Notification Service to Guides. [Embedded content](https://player.vimeo.com/video/1187488042?badge=0\&autopause=0\&player_id=0\&app_id=58479) ## Features: TNS vs. Symmetry Guides | Feature | Tax Notification Service (TNS) | Symmetry Guides | | - | - | - | | Tax rate & wage base updates for U.S. and Canada | Yes | Yes, with expanded capability to see tax limits | | Email notifications on tax changes | Yes | Yes, with self-service subscription management | | Searchable online tax database | Yes | Yes: search for instant results across 7,000+ U.S. jurisdictions, plus Canadian tax rates | | Filing instructions & protocols | No | Yes: step-by-step filing guides by tax program across U.S. jurisdictions | | Agency contact information | Limited | Yes: agency-specific contact details for tax programs | | AI-powered research assistant | No | Yes: ask questions, get instant answers | | Who pays | No | Yes: identifies whether the employee, the employer, or both pay the tax | ## Transition timeline | Date | What Happens | | - | - | | **April 2, 2026** | Email announcement sent confirming TNS will be replaced by Symmetry Guides and sharing details on what to expect. | | **April 16, 2026** | **Symmetry Guides access is live.** You will see the Symmetry Guides tile in your Client Support Center portal. Your existing TNS access will remain available in a secondary location (footer within the Guides tile) during the overlap period. | | **April 16 to July 15, 2026** | 90-day free access period. Explore all Symmetry Guides features at no additional charge while your existing TNS subscription remains active. | | **July 15, 2026** | 90-day free access period ends. Clients who have renewed or upgraded to a Symmetry Guides subscription will retain uninterrupted access to Guides. Clients on active TNS contracts will continue to be served per their contractual terms. | | **At your next renewal** | TNS will be fully retired. Your subscription will be updated to Symmetry Guides. Your account manager will reach out before your renewal to walk you through the updated pricing and packaging. | ## How to access Symmetry Guides 1. Log in to your Symmetry Client Support Center portal as you normally would using your existing credentials. 2. On your portal home page, click the **Symmetry Guides** tile to launch the application. 3. If you have trouble accessing Symmetry Guides, submit a support ticket. ## Field mapping: where to find your TNS data in Symmetry Guides If you're familiar with the TNS interface, the table below shows you exactly where each field from TNS lives in Symmetry Guides. Note that data in Guides is split across two sections: * **Taxes** (for rate and jurisdiction data) * **Filing** (for agency and compliance workflow data) ### TNS tax research listing (found under *Taxes* in Symmetry Guides) | NetSuite TNS Field | Symmetry Guides Field | Location in Symmetry Guides | | - | - | - | | `TAX INFORMATION` | Tax name | Taxes screen | | `UNIQUE TAX ID` | Tax ID | Taxes screen | | `RATE STATE NAME` | State | Taxes screen | | `RES RATE` | Res rate | Taxes screen | | `NON-RES RATE` | Non-res rate | Taxes screen | | `CALC TYPE` | Calc type | Taxes screen | | `WAGE BASE` | Wage base | Taxes screen | | `RATE EFFECTIVE DATE` | Effective date | Taxes screen | | `DOWNLOAD FILE (PDF source doc)` | *Not available in the initial release of Symmetry Guides. If access to agency source documents is important to your workflow, please share feedback via a support ticket; this is being evaluated for a future release.* | | | `PSD CODE` | PSD code | Taxes screen (use the **Columns** configuration at the top right of the page to show this column) | | `DATE EMAIL SENT` | *Coming in a future release* | | | `LAST MODIFIED` | Last modified | Taxes screen | | `EXTERNAL RATE NOTES` | Research note | Taxes screen - click into tax row or click **View tax** button for tax detail | | `STE VERSION` | STE release | Taxes screen | | *Not in TNS* | **Who pays** (new in Guides) | Taxes screen (use the **Columns** configuration at the top right of the page to show this column) | ### TNS tax rate (found under *Taxes* in Symmetry Guides) | NetSuite TNS Field | Symmetry Guides Field | Location in Symmetry Guides | | - | - | - | | `TAX NAME` | The tax name is at the top of the page with no field name | Taxes screen - click into tax row for tax detail - top of page | | `RES RATE` | Res rate | Taxes screen - click into tax row for tax detail - Tax Records section | | `NON-RES RATE` | Non-res rate | Taxes screen - click into tax row for tax detail - Tax Records section | | `CALC TYPE` | Calc type | Taxes screen - click into tax row for tax detail - top of page | | `OH City Tax Credit` | Ohio city tax credit | Taxes screen (use the **Columns** configuration at the top right of the page to show this column) - can also click into tax for tax detail (Tax Records section) | | `OH City Credit Limit` | Ohio city credit limit | Taxes screen (use the **Columns** configuration at the top right of the page to show this column) - can also click into tax for tax detail (Tax Records section) | | `IS RITA` | Is RITA | Taxes screen (use the **Columns** configuration at the top right of the page to show this column) | | `IS RITA` | Is RITA Tax? | Taxes screen - click into tax row for tax detail - Tax Records section | | *Not in TNS* | Ohio tax base | Taxes screen (use the **Columns** configuration at the top right of the page to show this column) | | `WAGE BASE` | Wage base | Taxes screen - click into tax row for tax detail - Tax Records section | | `RATE EFFECTIVE DATE` | Effective date | Taxes screen - click into tax row for tax detail - Tax Records section | | `EXTERNAL RATE NOTES` | Research note | Taxes screen - click into tax row for tax detail - Tax Records section | | `TR STATE LIST` | State name listed with no field name | Taxes screen - click into tax row for tax detail - shown in the breadcrumb near the top of the page | | `SUPPLEMENTAL FLAT TAX? (checkbox)` | Supplemental flat tax | Taxes screen - click into tax row for tax detail - Tax Records section | | `SUPPLEMENTAL INFO` | Supplemental info | Taxes screen - click into tax row for tax detail - Tax Records section | | `DATE EMAIL SENT` | *Coming in a future release* | | | `STE VERSION` | STE release | Taxes screen - click into tax row for tax detail - Tax Records section | | `TAXRATEUNIQUEID` | Tax ID | Taxes screen - click into tax row for tax detail - top of page | | `LAST MODIFIED` | Last modified | Taxes screen only (not within tax info/Tax Records) | | *Not in TNS* | **Who pays** (new in Guides) | Taxes screen - click into tax row for tax detail and within Tax Records section | ## Frequently asked questions ### Will I lose any of my existing TNS data or tax history? No. All historical tax rates and wage base data from TNS have been imported into Symmetry Guides. Your rate history is fully preserved and searchable. ### How many tax records can be displayed per page? TNS had a limit of 1,000 rows returned at a time. With Guides, there are no limits to the number of rows which can be viewed (but there are per page limits; you can view `10`, `25`, or `50` tax records per page). ### Can I export my tax rate data from Symmetry Guides? Symmetry Guides does not offer a bulk file export of tax rates. Instead, webhooks deliver tax rate changes directly to your systems in real time as they happen. See [Webhooks in Guides: Overview](/guides/webhooks/overview) to set up your first webhook. ### Will I still have access to release notes to view tax changes? There will be no change to access to the Client Support Center to view tax rate changes in our Symmetry Tax Engine (STE) notes. In a future release of Guides, we will have in-application release notes and release notifications. ### If I already have a tax filing solution, how should I use the step-by-step tax filing information within Guides? Compare the step-by-step filing information in Guides with your current solution. If something does not fit your workflow, submit a support ticket with specifics so the team can review. ### What if a filing section isn't available for a tax program? Tabs are always available on each **Tax Program** page. Sections appear when verified agency information is available for that tax program. If a section you need isn't shown, or you have feedback on filing content, submit a support ticket. ## Additional resources See the following articles to learn more about using Symmetry Guides: * [Symmetry Guides Overview](/guides/overview/introduction) * [Managing Tax Notification Emails in Guides](/guides/getting-started/tax-notification-emails) # Introduction to Symmetry Guides Source: https://docs.symmetry.com/guides/overview/introduction Orient to Symmetry Guides: log in, use Ask AI on Search, filter Taxes for rates and records, and open Filing Tax Program tabs for agency guidance. Symmetry Guides is a proactive, real-time compliance intelligence hub built on the same trusted tax research database that powers Symmetry’s payroll tax products. Guides delivers real-time tax rates, wage bases, and compliance data across 7,000+ U.S. jurisdictions, as well as rate information for Canadian taxes. Additionally, Guides provides agency-specific contact and tax filing information. ## How to access Symmetry Guides Symmetry Guides authenticates using Auth0. You can access the application through the tile on your Client Support Center home page, or directly at [guides.symmetry.com](https://guides.symmetry.com/search). ## Guides UI overview Symmetry Guides is organized around three main areas, reflected in the left navigation: **Search**, **Taxes**, and **Filing.** A search bar at the top of the page lets you **Ask AI anything**. ### Search Use **Search** to learn about taxes and filing, or to access tax or filing information about specific jurisdictions. Begin typing into the text field at the center of the screen (or the top of the page) and the blue **Ask AI** button will appear to the right of your written text. To initiate the search, click the **Ask AI** button or press **Enter** on your keyboard. Ask your question in plain language, for example about a local rate or a state’s withholding filing rules, and review the summarized answer together with its sources. Example prompts will appear below the search box in the center of the page. **Search** page view: ![Search page.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48253760157972.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=859a9f66ba2d48244e0aee94c918729f) ### Taxes The **Taxes** section is a searchable view of tax-specific information. Filter by jurisdiction, tax name or tax ID, tax effective date, or STE Release to find a specific tax or specific group of taxes. Use the **Columns** filter to the top right of the page to customize the column data visible for the tax rows. Click a tax row to see additional tax information, along with tax record history. Within the tax detail, click the **View record** button to the right of the screen to see tax history details for that line item. **Taxes** page: ![Taxes page.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48263096895764.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=260a41c34e12595dfb35ae458193c5f8) **Taxes** page (viewing **Columns** filter): ![Columns filter - image 1.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48263165555476.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=67d9fd82a4c4c6aec292058271683bc3) ![Columns filter - image 2.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48263176282132.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=07019e25325b523431e8f573a88ad0f9) **Taxes** (after clicking into a specific tax row): ![Taxes - after clicking into a specific tax row.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48268329859604.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=fab624b32eb88e388cb34f3d6e0da4fe) **Tax Record Details**: ![Tax Record Details.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48268576213908.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=054774374f8b49435fe57f92148e2221) ### Filing The **Filing** section provides filing guides in a table format. You can use the open text **Search** field to search for a specific tax program within this page. Select a row to open the **Tax Program** detail for that program; this will be your primary place for agency-specific filing and registration content. **Filing** page: ![Filing page.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48253225610004.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=3e5efd8efd80528c30b77d058f797fa5) **Filing** (after clicking into a specific row): ![Filing tab after clicking into a specific row.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48226329089428.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=9a270fa9642b3ffc7708aa1503c163e2) ## Filing Guides Each **Tax Program** row within the **Filing** page can be clicked to view tax program-specific information. The specific tax program will have links to the agency website and/or tax portal which will remain static at the top of the page, with clickable tabs below to navigate into each of the filing sections. > [!NOTE] > > **Visible tabs and sections** > > The [**Overview**](#overview-tab), [**Filing**](#filing-tab), [**Payments**](#payments-tab), [**Taxes**](#taxes-tab), and [**Register**](#register-tab) tabs are always available on each **Tax Program** page. The sections which appear on those tabs, along with the headers which form the section table of contents at the right of each of these pages, will appear *if* the information applicable to the section *is available from the agency.* If a tab has no published content yet, it still appears and shows that no information is available for that area. > > This means you may see more tabs and sections for one tax program vs. another - this is expected behavior. Symmetry will include all verified agency information that is available for each tax program. ### Overview tab The **Overview** tab provides a brief summary of what is needed before submitting a filing, links to **How to register** (which links to the **Register** tab), and includes a **Support** section which lists agency contact information and details for the tax program. **Overview** tab: ![Overview tab.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48226452543380.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=3deb36162b530123ade2ea95195f3b9b) ### Filing tab The **Filing** tab provides a summary of key filing information, as well as various sections for filing guidance. A small **table of contents** to the right of the page indicates the sections that exist for the program you are viewing. Which sections appear depend on what information is published for that specific tax program. Possible sections for **Filing** include: * **Overview**: Provides high-level information about the tax program and filing for the tax program. * **Filing schedule**: Provides the frequency of filing, along with filing due dates. * **Liability rules**: Details wage thresholds, employee thresholds, conditions for when a business is liable, the time period requirement, and the deposit rules. * **Before you file**: Filing requirements, test guidance, and file upload limits with the agency. * **Filing methods**: Lists the available methods for filing, such as E-file or Paper Filing. Will also provide steps to file, how to know if accepted or rejected, proof of filing, processing times, and form name. * **Bulk filing**: Provides steps for bulk filing. * **Amendments**: Provides steps on how to make amendments to the filings. * **Additional guidelines**: Provides extra guidelines such as processing times. **Filing** tab for a specific tax program: ![Filing tab for a specific tax program.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48229981435028.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=ba36dc62bdfb7cf1e6ae459666960b3c) ### Payments tab The **Payments** tab focuses on payment-specific requirements for the program when that content has been provided from the agency. Which sections appear depend on what information is published for that specific tax program. Possible sections for **Payments** include: * **Deposit schedule**: Identifies deposit frequency, deposit due dates, and liability grouping. * **Payment methods**: Provides accepted payment methods by the agency. * **Bulk payments**: Provides deposit detail for bulk payments. * **Zero deposit requirements**: Details zero deposit requirements for periods with or without liability. **Payments** tab for a specific tax program: ![Payments tab for a specific tax program.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48230078426644.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=8fa5129f58b2abbe6149ab66734c359a) ### Taxes tab The **Taxes** tab lists taxes associated with the tax program you've clicked into. The tax name is listed, along with a button which will route you to the **Tax** page for tax details when clicked. **Taxes** tab for a specific tax program: ![Taxes tab for a specific tax program.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48230205021460.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=ec0019c55d8ce6ebc90479d90180cdd5) ### Register tab The **Register** tab provides details on how to register with the agency. A small **table of contents** to the right of the page indicates the sections that exist for the program you are viewing. Which sections appear depend on what information is published for that specific tax program. Possible sections for **Register** include: * **Agency ID**: Provides details on the **Registration ID format** for registering with the agency. * **Payroll provider/TPA**: Includes expandable accordions which detail **Requirements to register**, **How to register**, **How to manage clients**, and **TPA support**. * **Employer**: Includes expandable accordions which detail **Requirements to register** and **How to register**. **Register** tab for a specific tax program: ![Register tab for a specific tax program.png](https://mintcdn.com/symmetry-prod/EesyCAUYLi5bH_2z/guides/assets/images/48230240544148.png?fit=max\&auto=format\&n=EesyCAUYLi5bH_2z\&q=85\&s=51d69461914e8e566be2acfd261f4f63) ## Demo videos ### Explore taxes Watch a quick walkthrough of exploring Taxes in Symmetry Guides. [Embedded content](https://player.vimeo.com/video/1190605362?badge=0\&autopause=0\&player_id=0\&app_id=58479) ### Explore filing See Symmetry Guides Filing navigation in action with the below demo video. [Embedded content](https://player.vimeo.com/video/1191599716?badge=0\&autopause=0\&player_id=0\&app_id=58479) # Webhooks Overview: Register Callback URLs in Guides Source: https://docs.symmetry.com/guides/webhooks/overview Set up Guides webhooks by registering up to five Callback URLs under Settings > Manage webhooks. Covers Send test and troubleshooting from the Activity tab. Webhooks in Guides give your team real-time, automated tax change updates. These are delivered directly to your server as a JSON notification. When Symmetry publishes a new tax or new tax rate in Guides, any webhook you have configured will fire automatically, without any manual action on your part. Webhooks are available to all Guides clients and are managed directly in your account Settings in Guides. You can register up to five active webhook endpoints per account. ## How to create a webhook Follow the steps below to create up to five webhooks from Symmetry Guides: 1. Access [Symmetry Guides](https://guides.symmetry.com/) (use your Auth0 login). 2. Access the admin settings by clicking the dropdown next to the profile circle at the top right of the screen, then click **Settings**. 3. Click the **Manage webhooks** button. 4. From the Configuration tab, add your **Callback URL** and an optional **Description**, then click the **Add webhook** button. 5. Once added, your webhook will be visible within the Configuration tab. You can **Send test**, **Edit**, or **Remove** the webhook directly from this screen. ![](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/guides/assets/images/webhooks-overview-1.png?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=0d44229b3fe733f4b644f5a4cd48600e) ## Troubleshooting If you are not receiving webhooks as expected, follow the steps below. 1. Confirm the correct **Callback URL** is configured in Guides (**Settings** > **Manage webhooks**). 2. Check the **Activity** tab for delivery status (**Settings** > **Manage webhooks** > **Activity** > **Details**). * `4xx` errors indicate a problem with the submitted data and will not be retried. Confirm your callback URL is correct and pointing to the right server location. * `5xx` errors indicate a server-side issue. Guides will automatically retry delivery two additional times. # Apply custom app theme configuration Source: https://docs.symmetry.com/i9/api-reference/account-custom-app-theming/apply-custom-app-theme-configuration /i9/api-reference/i-9-api.yaml post /v1/applicationTheme Applies a new custom app theme configuration to all employers under the account. This will cascade the theme update to all employers' subdomains in WorkBright. # Delete custom app theme configuration Source: https://docs.symmetry.com/i9/api-reference/account-custom-app-theming/delete-custom-app-theme-configuration /i9/api-reference/i-9-api.yaml delete /v1/applicationTheme Deletes the custom app theme configuration for all employers under the account. This will cascade the deletion to all employers' subdomains and restore default styling. # Update custom app theme configuration Source: https://docs.symmetry.com/i9/api-reference/account-custom-app-theming/update-custom-app-theme-configuration /i9/api-reference/i-9-api.yaml patch /v1/applicationTheme Updates the existing custom app theme configuration for all employers under the account. Only the provided fields will be updated; other fields will remain unchanged. This will cascade the update to all employers' subdomains. Returns a status report showing which domains succeeded or failed. # Deletes a registered Admin Source: https://docs.symmetry.com/i9/api-reference/admin/deletes-a-registered-admin /i9/api-reference/i-9-api.yaml delete /v1/employers/{employerId}/admins/{adminId} Deletes an Admin associated with an Employer # Generate a deep link to a specific E-Verify case in the embedded UI Source: https://docs.symmetry.com/i9/api-reference/admin/generate-a-deep-link-to-a-specific-e-verify-case-in-the-embedded-ui /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/admins/{adminId}/everifyCases/{id}/generateUri Generate a deep link to a specific E-Verify case in the embedded UI # Generate a direct link to an individual employee's submission page Source: https://docs.symmetry.com/i9/api-reference/admin/generate-a-direct-link-to-an-individual-employees-submission-page /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/admins/{adminId}/employees/{employeeId}/submissions/{submissionId}/generateUri Generate a direct link to an individual employee's submission page # Generate a direct link to the administrator index page filtered by I-9s requiring Section 2 verification Source: https://docs.symmetry.com/i9/api-reference/admin/generate-a-direct-link-to-the-administrator-index-page-filtered-by-i-9s-requiring-section-2-verification /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/admins/{adminId}/generatePendingCountersignUri Generate a direct link to the administrator index page filtered by I-9s requiring Section 2 verification # Generate a direct link to the E-Verify case index page Source: https://docs.symmetry.com/i9/api-reference/admin/generate-a-direct-link-to-the-e-verify-case-index-page /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/admins/{adminId}/everifyCases/generateUri Generate a direct link to the E-Verify case index page # Generate a token for an admin to access the I9 system Source: https://docs.symmetry.com/i9/api-reference/admin/generate-a-token-for-an-admin-to-access-the-i9-system /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/admins/{adminId}/generateToken Generate a token for admin access # Generate Link to Access E-Verify Settings Source: https://docs.symmetry.com/i9/api-reference/admin/generate-link-to-access-e-verify-settings /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/admins/{adminId}/everifySettings/generateEverifySettingsUri Generate link to access e-verify settings # Registers an Admin with an Employer Source: https://docs.symmetry.com/i9/api-reference/admin/registers-an-admin-with-an-employer /i9/api-reference/i-9-api.yaml post /v1/employers/{employerId}/admins Registers an Admin associated with an Employer # Return admin data Source: https://docs.symmetry.com/i9/api-reference/admin/return-admin-data /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/admins/{adminId} Return admin data for the specified admin ID # Return admins for a given employer Source: https://docs.symmetry.com/i9/api-reference/admin/return-admins-for-a-given-employer /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/admins Return admins for a given employer. # Updates a registered Admin Source: https://docs.symmetry.com/i9/api-reference/admin/updates-a-registered-admin /i9/api-reference/i-9-api.yaml patch /v1/employers/{employerId}/admins/{adminId} Updates an Admin associated with an Employer # Return Open API configuration Source: https://docs.symmetry.com/i9/api-reference/documentation/return-open-api-configuration /i9/api-reference/i-9-api.yaml get /docs/config Return full API configuration. # Deletes a registered Employee Source: https://docs.symmetry.com/i9/api-reference/employee/deletes-a-registered-employee /i9/api-reference/i-9-api.yaml delete /v1/employers/{employerId}/employees/{employeeId} Deletes an Employee associated with an Employer # Generate a token for an employee to access the I9 form Source: https://docs.symmetry.com/i9/api-reference/employee/generate-a-token-for-an-employee-to-access-the-i9-form /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/employees/{employeeId}/generateToken Generate a token for employee access # Promote an employee to administrator role Source: https://docs.symmetry.com/i9/api-reference/employee/promote-an-employee-to-administrator-role /i9/api-reference/i-9-api.yaml post /v1/employers/{employerId}/employees/{employeeId}/promoteToAdmin Promotes an existing employee to administrator, granting them admin privileges while preserving their employee history. # Register a new employee with an employer Source: https://docs.symmetry.com/i9/api-reference/employee/register-a-new-employee-with-an-employer /i9/api-reference/i-9-api.yaml post /v1/employers/{employerId}/employees Register a new employee with an employer # Reject an I-9 submission Source: https://docs.symmetry.com/i9/api-reference/employee/reject-an-i-9-submission /i9/api-reference/i-9-api.yaml post /v1/employers/{employerId}/employees/{employeeId}/submissions/{submissionId}/reject Moves the submission to a rejected state. Only the latest I-9 submission for this employee can be rejected. The reason you provide may be shared with the employee (for example by email), depending on configuration. # Request Remote Reverification for an employee Source: https://docs.symmetry.com/i9/api-reference/employee/request-remote-reverification-for-an-employee /i9/api-reference/i-9-api.yaml post /v1/employers/{employerId}/employees/{employeeId}/submissions/{submissionId}/requestRemoteReverification Allows an administrator to request remote reverification for an employee. Employee must have i9RemoteCounterSignAuthorized and i9RemoteReverificationAuthorized enabled. # Reset an I-9 submission Source: https://docs.symmetry.com/i9/api-reference/employee/reset-an-i-9-submission /i9/api-reference/i-9-api.yaml post /v1/employers/{employerId}/employees/{employeeId}/submissions/{submissionId}/reset Resets the specified I-9 submission so that a new submission can be requested. The existing submission becomes a historical record. # Return a specific I9 submission for an employee Source: https://docs.symmetry.com/i9/api-reference/employee/return-a-specific-i9-submission-for-an-employee /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/employees/{employeeId}/submissions/{submissionId} Return a specific I9 submission for an employee. # Return employee data Source: https://docs.symmetry.com/i9/api-reference/employee/return-employee-data /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/employees/{employeeId} Return employee data for the specified employee ID # Return employees for a given employer Source: https://docs.symmetry.com/i9/api-reference/employee/return-employees-for-a-given-employer /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/employees Return employees for a given employer. # Return I9 submissions for an employee Source: https://docs.symmetry.com/i9/api-reference/employee/return-i9-submissions-for-an-employee /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/employees/{employeeId}/submissions Return I9 submissions for an employee. # Update an existing employee with an employer Source: https://docs.symmetry.com/i9/api-reference/employee/update-an-existing-employee-with-an-employer /i9/api-reference/i-9-api.yaml patch /v1/employers/{employerId}/employees/{employeeId} Update an existing employee with an employer # Apply custom app theme configuration for employer Source: https://docs.symmetry.com/i9/api-reference/employer-custom-app-theming/apply-custom-app-theme-configuration-for-employer /i9/api-reference/i-9-api.yaml post /v1/employers/{employerId}/applicationTheme Applies a new custom app theme configuration to the specified employer. This will create or replace the existing theme configuration in WorkBright. # Delete custom app theme configuration for employer Source: https://docs.symmetry.com/i9/api-reference/employer-custom-app-theming/delete-custom-app-theme-configuration-for-employer /i9/api-reference/i-9-api.yaml delete /v1/employers/{employerId}/applicationTheme Deletes the custom app theme configuration for the specified employer. This will remove the theme from WorkBright and restore default styling. # Get custom app theme configuration for employer Source: https://docs.symmetry.com/i9/api-reference/employer-custom-app-theming/get-custom-app-theme-configuration-for-employer /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/applicationTheme Retrieves the current custom app theme configuration for the specified employer. Returns the theme configuration stored in WorkBright, or null if no theme is configured. # Update custom app theme configuration for employer Source: https://docs.symmetry.com/i9/api-reference/employer-custom-app-theming/update-custom-app-theme-configuration-for-employer /i9/api-reference/i-9-api.yaml patch /v1/employers/{employerId}/applicationTheme Updates the existing custom app theme configuration for the specified employer. Only the provided fields will be updated; other fields will remain unchanged. # Configure E-Verify Settings Source: https://docs.symmetry.com/i9/api-reference/employer/configure-e-verify-settings /i9/api-reference/i-9-api.yaml post /v1/employers/{employerId}/everifySettings Configure E-Verify settings for an employer # Registers an Employer Source: https://docs.symmetry.com/i9/api-reference/employer/registers-an-employer /i9/api-reference/i-9-api.yaml post /v1/employers Registers an Employer associated with an Account # Request deletion of an Employer Source: https://docs.symmetry.com/i9/api-reference/employer/request-deletion-of-an-employer /i9/api-reference/i-9-api.yaml delete /v1/employers/{employerId} Requests deletion of an Employer and all associated data (employees, submissions, admins). # Retrieve current E-Verify settings for an employer Source: https://docs.symmetry.com/i9/api-reference/employer/retrieve-current-e-verify-settings-for-an-employer /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/everifySettings Retrieves the current E-Verify account configuration for an employer # Return employer data (for example, Admin details, employee details, and product tier) Source: https://docs.symmetry.com/i9/api-reference/employer/return-employer-data-for-example-admin-details-employee-details-and-product-tier /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId} Return employer data for specified employer. # Returns a list of all employers for account Source: https://docs.symmetry.com/i9/api-reference/employer/returns-a-list-of-all-employers-for-account /i9/api-reference/i-9-api.yaml get /v1/employers Returns a list of all employers # Update E-Verify settings for an employer Source: https://docs.symmetry.com/i9/api-reference/employer/update-e-verify-settings-for-an-employer /i9/api-reference/i-9-api.yaml patch /v1/employers/{employerId}/everifySettings Updates existing E-Verify settings for an employer # Updates an Employer Source: https://docs.symmetry.com/i9/api-reference/employer/updates-an-employer /i9/api-reference/i-9-api.yaml patch /v1/employers/{employerId} Updates an Employer associated with an Account # Return e-verify case data Source: https://docs.symmetry.com/i9/api-reference/everify/return-e-verify-case-data /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/everifyCases/{id} Return e-verify case data for the specified e-verify Case ID # Return e-verify cases for a given employer Source: https://docs.symmetry.com/i9/api-reference/everify/return-e-verify-cases-for-a-given-employer /i9/api-reference/i-9-api.yaml get /v1/employers/{employerId}/everifyCases Return e-verify cases for a given employer. # I-9 API overview Source: https://docs.symmetry.com/i9/api-reference/overview Base URLs, authentication, and the tools (live Swagger and a Postman collection) for working with the Symmetry I-9 API. The Symmetry I-9 API manages employers, employees, form submissions, and E-Verify cases for Form I-9 completion. The endpoint reference in this section is generated from the I-9 OpenAPI specification. ## Environments and base URLs Symmetry I-9 runs in a single production environment. There is no separate staging or sandbox environment. | Environment | Base URL | | - | - | | Production | `https://api.symmetry.com/i9` | > [!NOTE] > > To test your integration safely, register a dedicated test employer in production and point its webhook and postback URLs at your own test endpoints. See [Testing your setup with employer-level isolation](/i9/testing-and-troubleshooting/employer-level-isolation). ## Authentication Make a request to the `/authentication` endpoint using your API key. This returns a valid access token, which you then send on every other request. > [!WARNING] > > **Access token versus API key** > > Your access token is not the same as your API key. The API key is used for initial authentication to obtain an access token from the `/authentication` endpoint. The access token is then used to authorize and interact with the other I-9 API endpoints securely. ## Try it live with Swagger For interactive, authenticated calls against the running service, use the hosted Swagger UI. It mirrors the endpoints in the API reference and lets you execute real requests. > **[Production Swagger](https://api.symmetry.com/i9/docs)** > > Live API explorer for every I-9 endpoint. ### Step 1: Generate an access token Make a request to the `/authentication` endpoint using your API key. This returns a valid access token. ### Step 2: Authorize in Swagger * Select the **Authorize** button on the right side of the Swagger UI. * Paste your access token into the dialog box. * Select **Authorize**. Once authorized, an unlocked icon appears next to each endpoint, indicating that you can now send requests. ### Step 3: Try out endpoints * Select an endpoint. * Select **Try it out**. * Select **Execute**. Swagger displays the API's response. ## Next steps > **[Postman](/i9/api-reference/postman-collection)** > > Download the I-9 Postman collection and environment directly from the API. > **[Endpoints](/i9/api-reference/employer/returns-a-list-of-all-employers-for-account)** > > Full reference for every employer, employee, admin, and E-Verify endpoint. # Postman collection and environment for I-9 API Source: https://docs.symmetry.com/i9/api-reference/postman-collection Download the Symmetry I-9 Postman collection and environment directly from the API, set your credentials, and send sample requests to every I-9 endpoint. A Postman collection has been established to make testing the Symmetry I-9 API endpoints simple and intuitive. Symmetry serves the Postman files from the API itself rather than as static downloads, so the collection always reflects the current endpoints. ## Download from Swagger Both files come from the **Postman** endpoints, and both require authorization. | Endpoint | What it returns | | - | - | | `GET /postman/collection` | Sample requests for all employer, employee, account, administrator, and E-Verify endpoints. | | `GET /postman/environment` | The environment variables used across those requests. | > **[Postman endpoints in Swagger](https://api.symmetry.com/i9/docs#/Postman)** > > Jump to the Postman section of the Swagger UI to execute both endpoints and save each response. > [!NOTE] > > **Both endpoints require authorization** > > Authorize with an access token returned from the `/authentication` endpoint, not your API key. See [Symmetry I-9 API overview](/i9/api-reference/overview) for how to request one. ## Import into Postman **1. Authorize in Swagger and download both files** Authorize in the Swagger UI, then execute `GET /postman/collection` and `GET /postman/environment` and save each response as a file. **2. Import both files into Postman** In Postman, select **Import**, then add the collection file and the environment file you downloaded. **3. Select the environment and set your credentials** Activate the **Symmetry I-9** environment, then supply your own `apiKey` and confirm `apiDomain` is set to `https://api.symmetry.com`. ## Environment variables | Variable | Value | | - | - | | `apiKey` | Provided by Symmetry's Client Success team. If you are unsure of your company's `apiKey`, reach out to Client Success within the [Client Support Center](https://support.symmetry.com). | | `apiDomain` | The base domain for the I-9 API: `https://api.symmetry.com`. | | `accessToken` \* | Provided in the response from the `/authentication/login` endpoint. | | `employerId` | The unique identifier of the employer. | | `employeeId` | The unique identifier of the employee. | | `adminId` | The unique identifier of the company administrator. | | `submissionId` | The unique identifier of the employee's I-9 submission. Retrieved from the `/employers/{employerId}/employees/{employeeId}/submissions` GET endpoint. | | `everifyId` | The unique identifier of the E-Verify case. | | `apiVersion` | Endpoint version. Symmetry I-9 is currently on `v1`. | \* Set automatically in Postman. The authentication request includes a script that writes the returned token into the active environment. # Postman Collection Source: https://docs.symmetry.com/i9/api-reference/postman/postman-collection /i9/api-reference/i-9-api.yaml get /postman/collection Postman Collection # Postman Environment Variables Source: https://docs.symmetry.com/i9/api-reference/postman/postman-environment-variables /i9/api-reference/i-9-api.yaml get /postman/environment Postman Environment Variables # Return API version Source: https://docs.symmetry.com/i9/api-reference/version/return-api-version /i9/api-reference/i-9-api.yaml get /version Return API version # Audit trail Source: https://docs.symmetry.com/i9/compliance-and-audit-readiness/audit-events What the Symmetry I-9 audit trail captures for Forms I-9 and E-Verify cases, and where administrators view it in the employer embedded mode. Audit events (`auditLogs`) provide a detailed chronological record of key actions taken by the employee and the employer. They are automatically recorded for both Form I-9 submissions and E-Verify cases, providing a reliable, time-stamped trail of key actions and status changes. This page covers what the trail captures and where administrators find it in the embedded experience. To retrieve the trail programmatically or look up a specific event name, see [Audit Log Reference](/i9/compliance-and-audit-readiness/audit-logs). ## Audit event types ### I-9 events The I-9 audit events log captures key moments in the form’s lifecycle, such as: * When the employee submits section 1 * When an authorized representative or employer completes Section 2 * When employees or authorized representatives share their location during the Remote I-9 workflow for Section 2 * IP addresses for each event * Timestamps for every action For the complete list of event names and the actor behind each, see the [audit event reference](/i9/compliance-and-audit-readiness/audit-logs#audit-events). ### E-Verify events In addition to activities related to completing the Form I-9, Symmetry also captures E-Verify events including: * Status changes (e.g., from “Submitted” to “Pending Response”) * Actions taken by administrators * System-generated updates * Corresponding timestamps Each entry provides visibility into the E-Verify case lifecycle, helping administrators monitor activity and ensure that all required steps have been taken in a timely manner. E-Verify case events are returned on the case itself rather than on the I-9 submission—see [Manage E-Verify Cases via API](/i9/e-verify/manage-cases-api#everifycase-object). ## Accessing the audit trail ### Employer embedded mode #### Form I-9 events Administrators can access the audit trail by clicking into the "View audit events" on any of the I-9 status pages within the employer embedded mode. To get to an I-9 status page, click on the “Form I-9s” link under the Form I-9 Summary in the administrator homepage. ![](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/i9/assets/images/37922975464084.png?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=113b517b3ecb276b434319471500ee68) #### E-Verify events Administrators can access E-Verify event details from within E-Verify cases listing. To get to the E-Verify cases list, click on the “E-Verify cases” link under the E-Verify Summary in the administrator homepage. ![](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/i9/assets/images/37923274303636.png?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=6866a920d97482e521f4a35390e0a86d) ### API All audit details for a specific Form I-9 submission are returned in the `auditLogs` array from the `/employers/{employerId}/employees/{employeeId}/submissions/{submissionId}` endpoint, where each object represents one recorded action. See [Audit Log Reference](/i9/compliance-and-audit-readiness/audit-logs) for the request, the fields returned on each entry, and the complete list of event names. # Audit log reference Source: https://docs.symmetry.com/i9/compliance-and-audit-readiness/audit-logs Retrieve the auditLogs array from an I-9 submission and look up any eventName. Covers the request, the fields on each entry, and the complete audit event catalog. Each I-9 submission includes a detailed audit trail. The `auditLogs` array provides a time-stamped record of key actions taken by both the employee and the employer’s authorized representative throughout the I-9 process. Audit logs are automatically generated for every Form I-9 and E-Verify case, ensuring a reliable record of status changes, verifications, and interactions. You can retrieve all audit details for a specific I-9 submission by making a GET request to the `/employers/{employerId}/employees/{employeeId}/submissions/{submissionId}` endpoint. For what the trail captures and where administrators view it in the embedded experience, see [Audit Trail](/i9/compliance-and-audit-readiness/audit-events). ## Sample request ```bash theme={null} curl --location 'https://api.symmetry.com/i9/v1/employers/123456-b29d-75cf-a308-15ca267af31c/employees/123456-86d6-7447-aa2a-6a14c063273a/submissions/118' \ --header 'Authorization: Bearer ••••••' ``` ### Path parameters | Element | Type | Description | | :- | :- | :- | | `employerId` | string | **Required**. The unique identifier of the employer. | | `employeeId` | string | **Required**. The unique identifier of the employee who completed the I-9. | | `submissionId` | integer | **Required**. The unique identifier of the employee's I-9 submission. Retrieved from the `/employers/{employerId}/employees/{employeeId}/submissions` endpoint. | ## Response A successful response contains the `auditLogs` array within the `submission` object. For brevity, we've included a sample audit log array below. For more information on all details returned from this endpoint and the complete view of the `submissions` object, [read more here](/i9/getting-started/retrieve-completed-data#submission-object). ```json theme={null} { "submission": { "auditLogs": [ { "eventName": "employee_submission_created", "eventTitle": "null", "details": {}, "request": { "url": "https://symmetry.workbright.com/i9_submission", "referrer": "https://symmetry.workbright.com/forms/i9/submission/new", "remoteIp": "2600:4040:2975:dd00:7427:1036:8e9:12fc", "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36", "serverName": "symmetry.workbright.com" }, "userType": "EMPLOYEE", "serverTimestamp": "2025-05-28T10:49:10-04:00" }, { "eventName": "employee_submit_location", "eventTitle": "null", "details": { "action": "event", "controller": "i9/remote_countersign" }, "request": { "url": "https://symmetry.workbright.com/rc/3f8f816a-dc4d-4f53-9ae2-7d386d2d96a8/event", "referrer": "https://symmetry.workbright.com/i9_remote_countersign", "remoteIp": "2600:4040:2975:dd00:7427:123:123:12fc", "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36", "serverName": "symmetry.workbright.com" }, "serverTimestamp": "2025-05-28T10:52:49-04:00" } ] ... } } ``` ### Audit logs array Each audit log object within the array represents an action taken on the submission. | Element | Type | Description | | :- | :- | :- | | `eventName` | string | Name of the event. [See full list below](#audit-events). | | `eventTitle` | string | Not used | | `details` | object | Information related to the specific event | | `request` | object | Metadata about the HTTP request that triggered the audit event | | `userType` | string | User type who triggered the event (`EMPLOYEE`, `ADMIN`) | | `serverTimestamp` | string, date-time | Timestamp of when the event occurred based on the time zone of the server. ISO 8601 format. | ## Audit events Below is the complete list of audit events (`eventName`) captured within the application: | `eventName` | Description | Actor | | :- | :- | :- | | `admin_countersign` | Admin has countersigned Section 2 of Form I-9 | Admin | | `admin_reverify_cancelled` | Admin has canceled reverification of the employee's Form I-9 through the Authorized Representative Supplement B Reverification (Reverify) workflow | Admin | | `admin_reverify_created` | Admin has requested reverification of the employee's Form I-9 through the Authorized Representative Supplement B Reverification (Reverify) workflow | Admin | | `admin_update_additional_info` | Admin has updated the additional information field in Section 2 on Form I-9 | Admin | | `admin_update_documentation` | Admin has updated the documentation title (including removing Receipt), document number, issuing authority, and/or expiration date previously submitted in Section 2 on Form I-9 | Admin | | `authorized_representative_qr_scan` | Authorized Representative displayed scannable QR code for the Employee to scan to indicate they are in the same location in lieu of geolocation access to continue with the Authorized Representative Countersign workflow | Authorized Representative | | `authorized_representative_submit_location_failed` | Authorized Representative has denied access to device location to proceed with Authorized Representative Countersign workflow | Authorized Representative | | `authorized_representative_auth_rep_certify_identity` | Authorized Representative has certified their identity and attested to not being the same individual as the Employee completing Form I-9 | Authorized Representative | | `authorized_representative_indicated_document_mismatch` | Authorized Representative has submitted their responses on the document review attestation and has indicated the document(s) do not meet the attestation statement for Section 2 of Form I-9 | Authorized Representative | | `authorized_representative_reset_document_review` | Authorized Representative has reset the document review process to update responses on the document review attestation for Section 2 of Form I-9 | Authorized Representative | | `authorized_representative_reverify_certify_identity` | Authorized Representative has certified their identity and attested to not being the same individual as the Employee completing Supplement B Reverification of Form I-9 | Authorized Representative | | `authorized_representative_reverify_qr_scan` | Authorized Representative displayed scannable QR code for the Employee to scan to indicate they are in the same location in lieu of geolocation access to continue with the Authorized Representative Supplement B Reverification workflow | Authorized Representative | | `authorized_representative_reverify_submit_document_review` | Authorized Representative has submitted their responses on the document review attestation for Supplement B Reverification of Form I-9 | Authorized Representative | | `authorized_representative_submit_countersign` | Authorized Representative has countersigned Section 2 of Form I-9 | Authorized Representative | | `authorized_representative_submit_document_review` | Authorized Representative has submitted their responses on the document review attestation for Section 2 of Form I-9 | Authorized Representative | | `authorized_representative_submit_document_verify` | Authorized Representative has confirmed their responses on the document review attestation in preparation to countersign Form I-9 | Authorized Representative | | `authorized_representative_submit_location` | Authorized Representative has given access to device location to proceed with Authorized Representative Countersign workflow | Authorized Representative | | `authorized_representative_submit_reverify` | Authorized Representative has signed Supplement B Reverification of Form I-9 | Authorized Representative | | `deferred_ssn_updated` | The employee previously indicated that they were awaiting SSN upon submission of Section 1, and has now provided the missing SSN | Employee | | `employee_qr_scan` | Employee displayed scannable QR code for the Authorized Representative to scan to indicate they are in the same location in lieu of geolocation access to continue with the Authorized Representative Countersign workflow | Employee | | `employee_reset` | Employee has reset the Authorized Representative phone number to re-initiate Authorized Representative Countersign workflow | Employee | | `employee_reverify_qr_scan` | Employee displayed scannable QR code for the Authorized Representative to scan to indicate they are in the same location in lieu of geolocation access to continue with the Authorized Representative Reverify workflow | Employee | | `employee_reverify_reset` | Employee has reset the Authorized Representative phone number to re-initiate Authorized Representative Reverify workflow | Employee | | `employee_reverify_submit_auth_rep_phone` | Employee has provided the Authorized Representative phone number to initiate Authorized Representative Reverify workflow | Employee | | `employee_reverify_submit_location` | Employee has given access to device location to proceed with Authorized Representative Reverify workflow | Employee | | `employee_reverify_submit_location_failed` | Employee has denied access to device location to proceed with Authorized Representative Reverify workflow | Employee | | `employee_submission_created` | Form I-9 Section 1 was signed | Employee | | `employee_submit_auth_rep_phone` | Employee has provided the Authorized Representative phone number to initiate Authorized Representative Countersign workflow | Employee | | `employee_submit_location` | Employee has given access to device location to proceed with Authorized Representative Countersign workflow | Employee | | `employee_submit_location_failed` | Employee has denied access to device location to proceed with Authorized Representative Countersign workflow | Employee | | `admin_update_supplement_b_info` | Admin has completed Supplement B indicating either Reverification, Rehire, and/or Rename (action in Log Entry) | Admin | # ICE audits & Symmetry I-9 Source: https://docs.symmetry.com/i9/compliance-and-audit-readiness/ice-audits Respond to an ICE Notice of Inspection using Symmetry I-9: review the notice, locate and export Forms I-9, pull E-Verify case data, and use audit trails. If an employer receives a Notice of Inspection (NOI) from U.S. Immigration and Customs Enforcement (ICE), they may be asked to produce Form I-9 records and supporting documentation within three business days. This article outlines key features of Symmetry I-9 to help prepare and respond efficiently. ## Review ICE notice carefully Before taking action, review the ICE notice in full and encourage the employer to notify their legal counsel. Confirm: * The scope of the records requested * The deadline for producing documentation * Whether E-Verify case data is included An NOI often asks for more than Forms I-9. Depending on its scope, it may also request: * Forms I-9 for all current employees, or only for employees hired during a stated period * Payroll records * Business licenses or articles of incorporation * E-Verify case information It's best practice to provide only the documentation specifically requested, as submitting additional records may introduce unnecessary risk or scrutiny. Not everything an NOI lists is necessarily required to be produced, which is another reason to have counsel confirm the scope before anything is handed over. ### Records past the retention period An employer is only required to produce Forms I-9 it is still required to retain: three years after the hire date or one year after termination, whichever is later. See [Retention](/i9/compliance-and-audit-readiness/retention) for how to calculate this. > [!WARNING] > > Apply retention schedules as ongoing practice, not as a response to a notice. Once an NOI has been received, do not delete records without direction from the employer's legal counsel. Disposing of records after a notice arrives can carry consequences of its own, even for records that had already passed their retention period. ### Helpful reference The [American Immigration Lawyers Association (AILA)](https://www.aila.org/library/ice-notices-employer-regarding-i-9-inspections) provides sample ICE notices, including: * [ICE Notice of Inspection](https://www.aila.org/File/Related/09031660c.pdf) * [ICE Form I-846, Warning Notice](https://www.aila.org/files/o-files/view-file/3B4DB6C7-E3FB-4170-B6A1-639E9E39D45F) * [ICE Notice of Discrepancies](https://www.aila.org/File/Related/09031660g.pdf) * [ICE Notice of Suspect Documents](https://www.aila.org/File/Related/09031660i.pdf) ## Locate and export forms I-9 Symmetry I-9 delivers completed Form I-9 metadata and PDFs as part of the postback payload sent to the `postback.target.url` configured for the employer. As the service provider, you're responsible for ensuring the employer has access to records needed for employer retention. If you need to re-fetch completed I-9s via the API: 1. [Get all employees for the employer](/i9/api-reference/employee/return-employees-for-a-given-employer) (`/employers/{employerId}/employees`) 2. [List I-9 submissions for an employee](/i9/api-reference/employee/return-i9-submissions-for-an-employee) (`/employers/{employerId}/employees/{employeeId}/submissions`) 3. [Retrieve a specific I-9 submission](/i9/api-reference/employee/return-a-specific-i9-submission-for-an-employee) (`/employers/{employerId}/employees/{employeeId}/submissions/{submissionId}`) This final response includes: * The completed Form I-9 PDF (base64-encoded and compressed) * Document verification results * E-Verify case ID * A full audit log ## E-Verify case data If ICE requests E-Verify records from an employer, use the following endpoints: 1. [List all E-Verify cases for the employer](/i9/api-reference/everify/return-e-verify-cases-for-a-given-employer) (`/employers/{employerId}/everifyCases`) 2. [Retrieve detailed case data](/i9/api-reference/everify/return-e-verify-case-data) (`/employers/{employerId}/everifyCases/{id}`) This response includes: * Case status and timestamps * All raw response data from E-Verify * The complete case audit log ## Audit trail Each I-9 submission in Symmetry includes a detailed, timestamped audit log of employee and employer actions. The [`auditLogs` array](/i9/compliance-and-audit-readiness/audit-logs#audit-logs-array) captures: * Electronic signature timestamps * Document verification outcomes * E-Verify case statuses * Any changes or corrections * Role and user performing the action To access these logs, retrieve a specific I-9 submission (`/employers/{employerId}/employees/{employeeId}/submissions/{submissionId}`) and look for the `auditLogs` field in the response. > [!NOTE] > > **List of Audit Events** > > For a full list of audit event types and definitions, refer to [Audit Events](/i9/compliance-and-audit-readiness/audit-logs#audit-events). ## Reminders Symmetry I-9 provides the data and audit history needed to respond to an ICE audit confidently. Be sure to: * Store postback records securely * Use the API to retrieve any missing data * Leverage audit logs to demonstrate good-faith compliance For any questions, [create a ticket](https://support.symmetry.com/hc/en-us/requests/new) and our team will be happy to assist! # Compliance & audit readiness overview Source: https://docs.symmetry.com/i9/compliance-and-audit-readiness/overview How Symmetry I-9 keeps you audit-ready: who owns completed I-9 data, the M-274 retention rules, and the audit trail available for ICE and DHS inspections. Form I-9 is only useful if you can produce it—correctly completed and on time—when a government agency asks. Symmetry I-9 gives you the data and records to stay audit-ready, but your platform remains the system of record for completed Forms I-9. > [!NOTE] > > **You own the completed I-9 data.** Symmetry delivers each finished Form I-9 (metadata plus an encoded PDF) to your employer's postback URL. Symmetry does not act as the source of truth—you are responsible for storing and retaining it. See [Receive Completed I-9 Data](/i9/getting-started/retrieve-completed-data) for the delivery mechanics. ## What this section covers > **[Retention](/i9/compliance-and-audit-readiness/retention)** > > The M-274 retention rules—keep each Form I-9 for three years after hire or one year after termination, whichever is later—and how to delete records. > **[Audit Trail](/i9/compliance-and-audit-readiness/audit-events)** > > What is captured for every Form I-9 and E-Verify case, and where administrators view it in the embedded experience. > **[Audit Log Reference](/i9/compliance-and-audit-readiness/audit-logs)** > > Retrieve the `auditLogs` array from a submission and look up every `eventName` in the audit event catalog. > **[ICE Audits & Symmetry I-9](/i9/compliance-and-audit-readiness/ice-audits)** > > How to respond to a Notice of Inspection (NOI): locate and export Forms I-9, pull E-Verify case data, and use the audit trail. ## The three pillars of audit readiness * **Ownership & storage** — Symmetry posts completed I-9 data to your postback URL; you store it per your platform's requirements. * **Retention** — Federal rules dictate how long you must keep each form and make it promptly retrievable for inspection. * **Audit trail** — Every action on a Form I-9 and E-Verify case is captured with a timestamp and actor, so you can demonstrate exactly who did what and when. # Retention Source: https://docs.symmetry.com/i9/compliance-and-audit-readiness/retention How Symmetry delivers completed Form I-9 data to your postback URL and the M-274 retention rules: keep each form 3 years after hire or 1 year after termination. Symmetry returns all completed Form I-9 metadata and PDF data as JSON to the postback URL that's configured for the relevant employer. You are responsible for storing completed I-9 metadata and forms based on your platform's requirements. Symmetry does not and will not act as the source of truth for completed I-9 data. ## M-274 guidance Employers must retain Form I-9 for three years after the employee's hire date or one year after their termination date, whichever is later. Forms must be stored in a way that allows them to be retrieved promptly for inspection upon request by authorized government officials. Per section 10.0 of the [U.S. Citizenship and Immigration Services Handbook for Employers M-274](https://www.uscis.gov/book/export/html/59502): *To calculate how long to keep a former employee’s Form I-9:* * *If they worked for less than two years, retain their form for three years after the date you entered in the First Day of Employment field.* * *If they worked for more than two years, retain their form for one year after the date they stop working for you.* *You can retain Form I-9 on paper, microfilm or microfiche, or electronically. You only need to retain pages that you and your employee wrote information on: You do not need to keep the Lists of Acceptable Documents on page 2, the instructions or blank supplement pages.* ## Deletion Should you want to delete an employer, administrator, or employee from Symmetry, the following endpoints are available: | Action | Endpoint | What it removes | | - | - | - | | Delete employee | `DELETE /v1/employers/{employerId}/employees/{employeeId}` | The employee associated with the employer. | | Delete administrator | `DELETE /v1/employers/{employerId}/admins/{adminId}` | Administrator access only. If the administrator was [promoted from an employee](/i9/embedded-experiences/promote-employee-to-administrator), the employee record is retained. | | Delete employer | `DELETE /v1/employers/{employerId}` | Requests deletion of the employer and all associated data—employees, submissions, and administrators. | # Authentication Source: https://docs.symmetry.com/i9/core-concepts/authentication Authenticate Symmetry I-9 with a system-level API key and one-time access URIs for embedded sessions. Covers request headers, the API domain, and API versioning. Symmetry I-9 supports two types of authentication that are used throughout development: an API key for system-level API access and one-time use access URIs for session-level authorization for the embedded modules. ## API key To call any endpoint, you must first generate an access token using your Symmetry-provided API key. Include this token as a Bearer token in the Authorization header of your request. Your API key is provided by Symmetry's Client Success Team during onboarding and unique to your company. If you have any questions or are concerned your API key was compromised, please reach out to our team to request a new key. ### Sample header Below is a sample HTTP header: ```bash Sample Request Header theme={null} curl --location 'https://api.symmetry.com/i9/v1/employers' \ --header 'Authorization: Bearer ••••••' ``` ### Example request Below is a sample cURL to the authorization endpoint to request a token: ```bash cURL theme={null} curl --location 'https://api.symmetry.com/authentication/login' \ --header 'Accept: application/json' \ --header 'api-key: YOUR_API_KEY' ``` #### Example response ```json theme={null} { "accessToken": "eyJhbGc1234567890asdfghjklv0I8N-WgO7q23S4" } ``` #### Invalid response An invalid API key will produce the following response: ```json theme={null} { "status": "Unauthorized", "statusCode": 401, "reason": "Api key is invalid and/or expired" } ``` ## Embedded experience access There are three places in the Symmetry I-9 application that require one-time, session-level access for embedded experiences: 1. Employee embedded experience 2. Employer administrator embedded experience 3. E-Verify settings embedded experience Session-level access is used for the employee or administrator working in the embedded experience, and not clients accessing the Symmetry API. To obtain access, make a GET request to the respective generate endpoint using your API key in the HTTP header. A successful call returns a one-time use URI, which you will use inside your application to launch the embedded mode. | Experience | Endpoint | | :- | :- | | Employee | `GET /employees/{employeeId}/generateToken` | | Employer administrator | `GET /admins/{adminId}/generateToken` | | E-Verify settings | `GET /admins/{adminId}/everifySettings/generateEverifySettingsUri` | The two `generateToken` endpoints return a single `embeddedUri` with the token already embedded as a query parameter, so one URL both signs the user in and opens their session: ```json theme={null} { "token": { "embeddedUri": "https://example-subdomain.workbright.com/sign_in_with_token?token=26aab821e4536a8695061c79ca577840" } } ``` The E-Verify settings endpoint instead returns two URIs—`authenticateUri` to sign the administrator in, and `embeddedUri` for the page they land on. Open them in that order, or the page will not load. See [Configure E-Verify](/i9/e-verify/configure) for that flow. The resulting token has a **30 minute expiration** and will **timeout after 1 hour of inactivity**. Unlike API keys, you may request and use additional access tokens while other access tokens are still active. Therefore, it is not necessary to store the access token in the database if you prefer to request a token just in time before a system request. ### Example request Below is a sample cURL to establish an employee's I-9 session: ```bash theme={null} curl --location 'https://api.symmetry.com/i9/v1/employers/12345-b29d-75cf-a308-15ca267af31c/employees/01972151-86d6-7447-aa2a-6a14c063273a/generateToken' \ --header 'Authorization: Bearer ••••••' ``` ### Deep links into the administrator experience The administrator endpoint above opens the embedded experience at its default page. Three additional endpoints generate access that lands an administrator on a specific page instead, which is useful when you want to send someone straight to the task they need to complete. Each is scoped to an administrator and returns `authenticateUri` to sign the user in, plus `embeddedUri` for the page they arrive on. | Endpoint | Lands on | | :- | :- | | `GET /admins/{adminId}/generatePendingCountersignUri` | The administrator index, filtered to I-9s awaiting Section 2 verification. | | `GET /admins/{adminId}/everifyCases/generateUri` | The [E-Verify case index](/i9/e-verify/case-index). | | `GET /admins/{adminId}/everifyCases/{id}/generateUri` | A specific E-Verify case. | | `GET /admins/{adminId}/employees/{employeeId}/submissions/{submissionId}/generateUri` | An individual employee's submission page. | ## API domain There is one API domain (`apiDomain`) for all Symmetry I-9 endpoints: * **Production**: `https://api.symmetry.com/i9` ## API versioning Currently, Symmetry I-9 is on version 1 (`v1`), and this version is included in the endpoint URL. Symmetry's API versions are always backwards compatible. # Core concepts overview Source: https://docs.symmetry.com/i9/core-concepts/overview The mechanics that apply to every Symmetry I-9 API call: authentication, webhooks and postback, pagination, and timezones. Read these once before building any workflow. These concepts are true of the Symmetry I-9 API no matter which workflow you build. Understanding them once will make every other guide—setup, E-Verify, remote I-9, document verification, and compliance—easier to follow. ## Authentication Symmetry I-9 uses two kinds of credentials: a system-level **API key** for server-to-server calls, and one-time **access URIs** that authenticate a user into an embedded session. Knowing which to use where is the foundation of every request. > **[Authentication](/i9/core-concepts/authentication)** > > API keys, embedded access URIs, the API domain, and versioning. ## Resources and their state Every endpoint is scoped to a place in a fixed hierarchy, and an I-9's progress is tracked as three independent statuses rather than one. > **[Resource Model & Identifiers](/i9/core-concepts/resource-model)** > > How account, employer, employee, and submission nest—and which IDs are UUIDs. > **[Statuses & Lifecycle](/i9/core-concepts/statuses-and-lifecycle)** > > Section 1, countersign, and E-Verify status, and how to track each. ## Events: webhooks vs. postback Symmetry sends you data in two complementary ways: * **Webhooks** notify your platform in real time when something happens (an employee finishes Section 1, an E-Verify case updates, a document is expiring) so you can act or alert users. * **Postback** delivers the completed Form I-9 payload to your employer's configured URL once the form is done. > **[Webhooks](/i9/core-concepts/webhooks)** > > Available events, sample payloads, and delivery retries. ## Working with API data > **[Pagination](/i9/core-concepts/pagination)** > > Page through list endpoints with the `?page` query parameter. > **[Timezones](/i9/core-concepts/timezones)** > > The ten supported timezones, and how to read I-9 dates and timestamps. ## Where to go next Capabilities build on these concepts and are documented in their own sections: > **[Embedded Experiences](/i9/embedded-experiences/iframe-embed)** > > Deliver the employee and administrator interfaces in an iframe. > **[Document Verification](/i9/document-verification/overview)** > > OCR-based screening of identity and work-authorization documents. # Pagination Source: https://docs.symmetry.com/i9/core-concepts/pagination Page through Symmetry I-9 list endpoints with the ?page query parameter. Covers which GET endpoints support it, the Pagination-* response headers, and the Link header. Four list endpoints return results 25 at a time and are paged with the `?page` query parameter. Every paginated response also carries `Pagination-*` headers and a `Link` header, so you can walk through pages without tracking offsets yourself. ## Usage To request a specific page of results, include the `page` parameter in your query string: ```text theme={null} https://api.symmetry.com/i9/v1/employers/01971d41-b29d-75cf-a308-15ca267af31c/employees?page=2 ``` Page numbers start at 1. If you omit the parameter, the API returns the first page: ```text theme={null} ?page=1 ``` Each page contains up to 25 results. ## Supported endpoints Pagination applies to the following `GET` endpoints: * `/employers` * `/employers/{employerId}/employees` * `/employers/{employerId}/admins` * `/employers/{employerId}/everifyCases` > [!NOTE] > > `/employers/{employerId}/employees/{employeeId}/submissions` is not paginated. It returns every submission for an employee in a single response, because an employee accumulates only a small number of I-9 submissions over the course of employment. Two of these endpoints also accept filters that narrow the result set before it is paged: `/employees` accepts `status` and `includeStatus`, and `/everifyCases` accepts `actionRequired`. When you filter, the pagination headers describe the filtered set, not the full collection. ## Response headers Each paginated response includes the following headers to help you navigate pages: | Header name | Header description | Example value | | - | - | - | | `Pagination-Current-Page` | The page number returned | 2 | | `Pagination-Current-Page-Items` | Number of results returned on the current page | 2 | | `Pagination-Page-Item-Limit` | Page size | 25 | | `Pagination-Total-Items` | Total results across all pages | 27 | | `Pagination-Total-Pages` | Total number of pages | 2 | ### Link header Paginated responses include a `Link` header with page navigation URLs, using the `first`, `prev`, `next`, and `last` relations. The `prev` and `next` relations are only present when a page exists in that direction, so the last page has no `next`: ```text theme={null} ; rel="first", ; rel="prev", ; rel="last" ``` Responses also include a `Link` header pointing to the current request (`self`) along with any parent resources related to the request: ```text theme={null} ; rel="self", ; rel="employer" ``` > [!TIP] > > To retrieve a full collection, request the first page and follow the `next` relation until it is no longer present. This avoids assumptions about page size and keeps working if the record count changes between requests. # Resource model & identifiers Source: https://docs.symmetry.com/i9/core-concepts/resource-model How Symmetry I-9 resources nest from account to employer to employee to submission, and the identifier format each one uses—including why submission IDs are integers. Every Symmetry I-9 endpoint is scoped to a fixed place in a resource hierarchy. Knowing where a resource sits tells you which path to call and which identifiers you need to have on hand. ## The hierarchy ```text theme={null} Account (implicit — determined by your API key) └── Employer /v1/employers/{employerId} ├── Employee …/employees/{employeeId} │ └── Submission …/submissions/{submissionId} ├── Admin …/admins/{adminId} ├── E-Verify settings …/everifySettings └── E-Verify cases …/everifyCases/{id} ``` **Account** is the top of the tree, and it is never passed in a path. Your API key determines the account, and account-scoped endpoints act on every employer beneath it. `/v1/applicationTheme`, for example, sets a theme for the whole account, while `/v1/employers/{employerId}/applicationTheme` overrides it for one employer. **Employer** is the boundary that effectively all data hangs from. Employees, administrators, E-Verify configuration, and themes are all scoped to an employer, which is what makes employer-level isolation useful for [testing your setup](/i9/testing-and-troubleshooting/employer-level-isolation). **Employee** holds the person and their onboarding state. An employee can be promoted to an administrator while remaining an employee. **Submission** is a single Form I-9 belonging to an employee. An employee may have more than one submission over time, for example after a rehire. ## Identifiers Most identifiers are UUIDs. Treat them as opaque values: store them as strings, and don't parse them or infer anything from their ordering. | Resource | Identifier | Type | | - | - | - | | Employer | `employerId` | string (UUID) | | Employee | `employeeId` | string (UUID) | | Administrator | `adminId` | string (UUID) | | Submission | `submissionId` | **integer** | | E-Verify case | `caseId` | string | > [!WARNING] > > **Submission IDs are integers, not UUIDs.** Unlike every other resource, a submission is identified by a small sequential integer such as `118`. If your data model assumes a UUID for every Symmetry identifier, submissions will break it. A `submissionId` reaches you in a few ways. Most often you already have it from a [webhook](/i9/core-concepts/webhooks), where it arrives as `data.submission.id` rather than as `submissionId`: ```json theme={null} "data": { "employerId": "12345-3fe3-7146-8ea6-123456sdfg", "employeeId": "0987654-d7ee-702f-92f3-123456lkjhgf", "submission": { "id": 1334 } } ``` You can also list an employee's submissions to find one, then request it directly: ```http theme={null} GET /v1/employers/{employerId}/employees/{employeeId}/submissions GET /v1/employers/{employerId}/employees/{employeeId}/submissions/{submissionId} ``` The E-Verify `caseId` is issued by E-Verify rather than by Symmetry, so it follows E-Verify's own format instead of a UUID. See [Manage E-Verify Cases](/i9/e-verify/managing-cases) for working with cases. # Statuses & lifecycle Source: https://docs.symmetry.com/i9/core-concepts/statuses-and-lifecycle An I-9's progress is three independent statuses. Covers employeeSectionOneStatus, i9CountersignStatus, and everifyCaseStatus, and how to track each. Completing an I-9 involves three parties, and each one's progress is tracked by its own status field on the employee object: the employee completes Section 1, the employer or an authorized representative countersigns Section 2, and—where E-Verify is enabled—the E-Verify case runs its course. Because each field reports on a different party, together they pinpoint exactly which step is outstanding and who owes the next action. | Field | Values | Who acts | | - | - | - | | `employeeSectionOneStatus` | `not_started`, `in_progress`, `completed` | Employee | | `i9CountersignStatus` | `not_started`, `completed` | Employer or authorized representative | | `everifyCaseStatus` | 20 values — see [E-Verify Case Statuses](/i9/e-verify/case-statuses) | Employer, E-Verify, or employee | The three tracks advance independently, so read each field on its own rather than inferring one from another. ## Section 1: the employee's portion `employeeSectionOneStatus` tracks the employee completing and signing Section 1. * `not_started` — the employee has not opened their I-9. * `in_progress` — the employee has begun but not signed Section 1. * `completed` — Section 1 is signed. Section 2 can now be completed. ## Countersign: Section 2 `i9CountersignStatus` tracks completion of Section 2, where the employer or an authorized representative examines the employee's documents and countersigns. * `not_started` — Section 2 is outstanding. * `completed` — the I-9 has been countersigned and the form is complete. This field reports completion rather than granular progress. When an authorized representative handles Section 2 remotely, the [Remote I-9](/i9/remote-i-9/authorized-representatives) section covers the intermediate steps they move through, and the [audit trail](/i9/compliance-and-audit-readiness/audit-events) records each one. ## E-Verify `everifyCaseStatus` applies to employers with E-Verify enabled. It carries the most values of the three because it mirrors the full E-Verify case lifecycle, so you can surface outcomes that require employer action—such as `pending_referral`—the moment they occur. The canonical list lives on [E-Verify Case Statuses](/i9/e-verify/case-statuses), and [TNCs and FANs](/i9/e-verify/tncs-and-fans) explains the obligations a tentative nonconfirmation triggers. ## Tracking status changes You have two ways to observe these values, and most integrations use both: > **[Webhooks](/i9/core-concepts/webhooks)** > > Get notified as each status changes, rather than polling. > **[Retrieve completed data](/i9/getting-started/retrieve-completed-data)** > > Read current status directly from the employee and submission objects. > [!TIP] > > Drive your own UI from these three fields rather than from a status label of your own. A form with `employeeSectionOneStatus: completed` and `i9CountersignStatus: not_started` is waiting on the employer—which is exactly the queue an administrator needs to see. # Timezones Source: https://docs.symmetry.com/i9/core-concepts/timezones Set an employer's timezone from the ten supported values and interpret I-9 dates correctly. Covers the supported list, calendar dates vs. timestamps, and why date boundaries affect compliance. Every employer in Symmetry I-9 has a timezone, set from a fixed list of ten values. Because Form I-9 compliance is measured in calendar days rather than hours, the timezone establishes the local frame of reference for an employer's records: which day an employee signed Section 1, whether Section 2 was countersigned within three business days, and when a document is treated as expiring. ## Supported timezones Symmetry I-9 supports the following timezones, covering the United States and its territories: | Timezone identifier | U.S. time zone | Notes | | - | - | - | | `America/Puerto_Rico` | Atlantic Time | Also used for the U.S. Virgin Islands | | `America/New_York` | Eastern Time | | | `America/Chicago` | Central Time | | | `America/Denver` | Mountain Time | Observes daylight saving time | | `America/Phoenix` | Arizona | Mountain Time without daylight saving time | | `America/Los_Angeles` | Pacific Time | | | `America/Juneau` | Alaska Time | | | `Pacific/Honolulu` | Hawaii-Aleutian Time | Does not observe daylight saving time | | `Pacific/Guam` | Chamorro Time | Also used for the Northern Mariana Islands | | `Pacific/Apia` | Samoa Time | | ## Setting an employer's timezone The `timezone` field is required when [registering a new employer](/i9/getting-started/configure-employers) and can be changed later by [updating the employer](/i9/getting-started/configure-employers). Set it to the timezone where the employer's I-9 activity takes place, typically the worksite or the location of the administrators who countersign. ```json theme={null} { "name": "Example Company", "federalEIN": "98-7654321", "timezone": "America/New_York" } ``` The value must be one of the ten identifiers above. Any other IANA timezone, such as `UTC` or `America/Detroit`, is rejected with a validation error naming the accepted values. If you support employers across several regions, map your own location data to the closest supported timezone rather than passing an arbitrary identifier. > [!NOTE] > > Timezone is an employer-level setting; it is not configured per employee or per administrator. Employers operating in multiple time zones are typically modeled as separate employer records when their I-9 records need to be evaluated against different local dates. ## Interpreting dates and timestamps The API returns two distinct kinds of temporal values, and treating one like the other is the most common source of off-by-one-day errors. **Calendar dates** carry no time or offset. These are the dates recorded on the form itself, including `dateOfBirth`, `employeeStartDate`, `employeeSignDate`, `employerCertifyDate`, `documentationExpirationDate`, and `reverifyExpirationDate`. Store and display them as-is. ```json theme={null} { "employeeStartDate": "2026-03-02", "documentationExpirationDate": "2027-06-30" } ``` **Timestamps** are ISO 8601 values with an explicit UTC offset. These record when an action occurred in the system and include `submittedAt`, `statusChangedAt`, `resolvedAt`, the `serverTimestamp` on [audit log entries](/i9/compliance-and-audit-readiness/audit-logs), and the `timestamp` on [webhook payloads](/i9/core-concepts/webhooks). ```json theme={null} { "serverTimestamp": "2026-05-28T10:49:10-04:00" } ``` > [!WARNING] > > Always parse the offset that a timestamp carries rather than assuming a fixed zone, and normalize to UTC before sorting or comparing. Offsets can differ between entries in the same audit log, so a string comparison or a naive parse can put events in the wrong order. Converting a calendar date as though it were a midnight timestamp is what produces day shifts. An `employeeStartDate` of `2026-03-02` read as `2026-03-02T00:00:00Z` and then displayed in Pacific Time becomes March 1, which changes what your system reports about when the employee began work. ## Why this matters for compliance Form I-9 deadlines are defined in days, so the date an action is attributed to is what determines whether the record is timely: * **Section 1** must be completed no later than the employee's first day of employment. * **Section 2** must be completed within three business days of the employee's start date. When certification happens later, the completed form carries a `lateReason` explaining the delay, which becomes part of the record you produce in an audit. * **Reverification and expiring documents** are driven by calendar dates. The [`employee.upcomingExpiration` webhook](/i9/core-concepts/webhooks) fires 30 days ahead of a document's expiration date, so consistent date handling keeps your reminders aligned with the dates on the form. During an [ICE inspection](/i9/compliance-and-audit-readiness/ice-audits), the audit log is the evidence of who did what and when. Rendering those timestamps consistently in the employer's timezone means the sequence you present matches the sequence a reviewer reconstructs from the forms. # Webhooks Source: https://docs.symmetry.com/i9/core-concepts/webhooks Receive real-time Symmetry I-9 notifications via webhooks. Covers every event key and its payload, callback authentication, source IP allowlisting, and failure notifications. Webhooks allow you to receive real-time notifications when important events occur in the I-9 process. You can use them to trigger downstream workflows, update your internal systems, or monitor form progress without polling our APIs. ## Events When an event occurs, a `POST` request is sent to the configured webhook endpoint. All event types are included—you cannot subscribe to individual events. | Event | `eventKey` | Description | | :- | :- | :- | | Form I-9 was countersigned | `employee.i9Complete` | Notifies you when an employee's I-9 is complete and Section 2 is countersigned. | | E-Verify case details updated | `employee.everifyCaseUpdate` | Triggered when an employee’s E-Verify case is updated. Use this to prompt internal review or next steps. | | Employee profile updated | `employee.profileUpdated` | Notifies you when an employee's profile is updated (for example, social security number is added). It is not triggered when the employee is created. | | I-9 expiring documents | `employee.upcomingExpiration` | Triggers for Employment Authorization Documents (EADs) and Passport receipts 30 days before expiration, or immediately upon I-9 submission if within 30 days. Excludes original Passports. Applies only to active employees. | | Employee restarted Form I-9 | `employee.i9Restarted` | Notifies you when an employee restarts the Form I-9 process. This event does not include a submission ID because a new submission has not yet been created. | | Employee submitted form | `employee.section1Complete` | Fires when an employee completes Section 1, allowing you to prompt administrative review. | | Employee submission rejected | `employee.submissionRejected` | Notifies you when an employer rejects an employee's Form I-9 submission during the review process. Includes the rejection reason. | | Employee submission reverified | `employee.submissionReverified` | Notifies you when a Form I-9 has been successfully reverified through Supplement B. | | Authorized representative mismatch | `employee.i9AuthRepMismatch` | Triggered when an authorized representative identifies a mismatch while reviewing an employee’s Form I-9 documents during remote countersigning. | | E-Verify authentication result | `employer.everifyAuthenticationResult` | Notifies you of the result of an employer’s E-Verify credential authentication attempt (success or failure). This is an employer-level event and does not include employee data. | > [!NOTE] > > **Webhooks are distinct from the postback service** > > While webhooks send lightweight notifications about key events (such as form submission or case updates), the postback sends the full completed form data, including the actual form and its values. > > The postback is sent to the `postback.target.url` specified in the `employers` object and is typically used for processing the full I-9 record after completion. Read more here: [Receive Completed I-9 Data](/i9/getting-started/retrieve-completed-data). ## Sample payloads ### Form I-9 was countersigned (`employee.i9Complete`) Sent when Section 2 is countersigned. ```json theme={null} { "eventKey": "employee.i9Complete", "timestamp": "2025-12-22T15:51:19.757Z", "data": { "employerId": "12345-3fe3-7146-8ea6-123456sdfg", "employeeId": "0987654-d7ee-702f-92f3-123456lkjhgf", "submission": { "id": 1334 } } } ``` ### E-Verify case details updated (`employee.everifyCaseUpdate`) Sent when an employee’s E-Verify case status changes. ```json theme={null} { "eventKey": "employee.everifyCaseUpdate", "timestamp": "2025-12-22T15:51:26.109Z", "data": { "employerId": "12345-3fe3-7146-8ea6-123456sdfg", "employeeId": "0987654-d7ee-702f-92f3-123456lkjhgf", "submission": { "id": 1334 }, "everifyCase": { "caseId": "123456789ghj", "closed": false, "status": "draft" } } } ``` ### Employee profile updated (`employee.profileUpdated`) Sent when the employee's profile is updated. ```json theme={null} { "eventKey": "employee.profileUpdated", "timestamp": "2024-12-08T22:32:39.398-07:00", "data": { "employerId": "0197b38a-a7ca-77a1-86fb-f090890338d3", "employeeId": "0197b38a-a7ca-77a1-86fb-f090890338d3", "changedFields": { "employee": { "firstName": "Robert", "lastName": "Johnson", "middleName": "William", "nickname": "Bob", "socialSecurityNumber": "987-65-4321", "telephoneNumber": "(555) 987-6543", "gender": "Male", "dateOfBirth": "1985-06-15", "address": { "streetAddress1": "789 Pine St", "streetAddress2": "Suite 100", "city": "Another City", "state": "TX", "zipCode": "67890", "country": "US" } } } } } ``` ### I-9 expiring documents (`employee.upcomingExpiration`) Sent 30 days before a document expires, or immediately upon submission if within 30 days. ```json theme={null} { "eventKey": "employee.upcomingExpiration", "timestamp": "2025-12-22T16:07:41.128Z", "data": { "employerId": "12345-3fe3-7146-8ea6-123456sdfg", "employeeId": "0987654-d7ee-702f-92f3-123456lkjhgf", "submission": { "id": 1345, "documentationExpirationDate": "2025-12-24" } } } ``` ### Employee restarted Form I-9 (`employee.i9Restarted`) Sent when an employee restarts the Form I-9 process. **Workflow** 1. The employee begins completing Section 1. 2. The employee or an administrator restarts the Form I-9 process. 3. A new Form I-9 process is initiated. 4. The `employee.i9Restarted` webhook is sent. > [!NOTE] > > **Note** > > This event does not include a `submission` object because a new submission has not yet been created. The new submission ID is included in the subsequent `employee.section1Complete` webhook after the employee completes Section 1. ```json theme={null} { "eventKey": "employee.i9Restarted", "timestamp": "2026-07-13T14:12:53.117Z", "data": { "employerId": "019e4177-aabb-7722-a79f-9066b64a6b2c", "employeeId": "019f5bce-4108-79a6-9de7-a4b652d60d0e" } } ``` ### Employee submitted form (`employee.section1Complete`) Sent when the employee completes Section 1. ```json theme={null} { "eventKey": "employee.section1Complete", "timestamp": "2025-12-22T15:50:37.925Z", "data": { "employerId": "12345-3fe3-7146-8ea6-123456sdfg", "employeeId": "0987654-d7ee-702f-92f3-123456lkjhgf", "submission": { "id": 1334 } } } ``` ### Employee submission rejected (`employee.submissionRejected`) Sent when an administrator rejects an employee's Form I-9 submission during the review process. **Workflow** 1. Employee completes Section 1. 2. An administrator reviews the submission and completes Section 2. 3. The administrator rejects the Form I-9 submission and provides a rejection reason. 4. The `employee.submissionRejected` webhook is sent. ```json theme={null} { "eventKey": "employee.submissionRejected", "timestamp": "2026-05-27T00:41:28.476Z", "data": { "employerId": "019e4177-aabb-7722-a79f-91234567890", "employeeId": "019e41bb-2b38-795d-b32d-0987654321", "submission": { "id": 2729, "rejectionReason": "Document could not be verified." } } } ``` ### Employee submission reverified (`employee.submissionReverified`) Sent when a Form I-9 has been successfully reverified through Supplement B. **Workflow** 1. Employee has an existing completed Form I-9. 2. An administrator initiates the [Supplement B reverification](/i9/remote-i-9/reverification-supplement-b) process. 3. The administrator reviews and re-examines the employee's documentation as part of reverification. 4. The reverification is completed. 5. The `employee.submissionReverified` webhook is sent. ```json theme={null} { "eventKey": "employee.submissionReverified", "timestamp": "2024-07-18T21:17:06.847Z", "data": { "employerId": "019e4177-aabb-7722-1234567890", "employeeId": "019e41bb-2b38-795d-b32d-0987654321", "submission": { "id": 2730 } } } ``` ### Authorized representative mismatch (`employee.i9AuthRepMismatch`) Sent when an authorized representative identifies a mismatch while reviewing an employee’s documents during remote countersigning. **Workflow** 1. The employee is configured to use [remote countersigning with an authorized representative](/i9/remote-i-9/authorized-representatives). 2. The employee completes Section 1. 3. The authorized representative reviews the employee's documents during the remote countersigning process. 4. The authorized representative indicates that the employee's presented documents do not match the information entered in the Form I-9. 5. The `employee.i9AuthRepMismatch` webhook is sent. ```json theme={null} { "eventKey": "employee.i9AuthRepMismatch", "timestamp": "2026-05-13T13:50:13.572-07:00", "data": { "employerId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "employeeId": "12345678-abcd-1234-efgh-1234567890ab", "submission": { "id": 2500 } } } ``` ### E-Verify authentication result (`employer.everifyAuthenticationResult`) Sent when E-Verify credentials are authenticated or revalidated. Symmetry sends this event for every authentication attempt, even when the result matches the previous attempt. To check the current result at any time, call `GET /v1/employers/{employerId}/everifySettings` and read `everifyAuthenticated`. See [Configure E-Verify](/i9/e-verify/configure#check-e-verify-authentication-status). ```json theme={null} { "eventKey": "employer.everifyAuthenticationResult", "timestamp": "2026-02-17T13:50:13.572-07:00", "data": { "employerId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "everifyAuthenticated": true } } ``` ## Configuration Webhooks are configured at the employer level using the `/employers` POST endpoint. You can update the callback URL later using the `/employers/{employerId}` PATCH endpoint. When configured, you will receive all webhook event types. ### Request The `webhook` object contains the configuration for where webhook events will be delivered. ```json Sample Request theme={null} { "name": "Example Company", "federalEIN": "98-7654321", "timezone": "America/New_York", "address": { "streetAddress1": "14350 N 87 ST", "streetAddress2": "STE 310", "city": "Scottsdale", "state": "AZ", "zipCode": "85260" }, "webhook": { "callbackUrl": "https://client-system.example.com/callbacks/i9", "failureNotificationEmail": "admin@example.com", "authentication": { "authType": "basic", "username": "webhook_user", "password": "webhook_password" } } } ``` #### Webhook object fields | Element | Type | Description | | :- | :- | :- | | `callbackUrl` | string | Endpoint in your system where Symmetry will send the webhook event. This should be a publicly accessible URL that can receive `POST` requests. | | `failureNotificationEmail` | string | Email address to notify if a webhook request fails | | `authentication` | object | Specifies how Symmetry should authenticate when sending the webhook request to your system. Supported types include: `none`, `basic`, `oauth2`. | | `authentication.authType` | enum | **Required**. Configures the authentication scheme type to be used: `none`, `basic`, `oauth2`. | | `authentication.username` | string | Username to be used for basic authentication. | | `authentication.password` | string | Password to be used for basic authentication. | | `authentication.oauth2ClientId` | string | Oauth2 client ID required if using Oauth2 authentication | | `authentication.oauth2ClientSecret` | string | Oauth2 client secret, required if using Oauth2 authentication | | `authentication.oauth2AuthServerUrl` | string | URL to the Oauth2 token authentication server, required if using Oauth2 authentication | | `authentication.oauth2GrantType` | enum | OAuth 2.0 grant type. Required when using OAuth 2.0 authentication. Currently supports the `client_credentials` grant. | | `authentication.oauth2AdditionalParameters` | object | Additional parameters to be provided to the Oauth2 token authentication server | For full employer configuration details, see [Configure Employers](/i9/getting-started/configure-employers). ## Authentication Symmetry supports multiple authentication schemes when sending webhook requests: * None – no authentication header is included * Basic – `Authorization: Basic ` * OAuth2 – Symmetry will request an access token and include it in the `Authorization: Bearer ` header Authentication credentials are included in the request header when Symmetry sends webhook payloads to your system. This ensures secure delivery and proper endpoint validation. > [!NOTE] > > **If using OAuth2, ensure your token endpoint supports Client Credentials grant type.** ## IP allowlisting If your network restricts inbound traffic, allowlist the IP addresses below so Symmetry can deliver webhook events to your `callbackUrl`. | Availability zone | IP address | | :- | :- | | `us-west-2a` | `34.214.249.73` | | `us-west-2a` | `54.244.116.141` | | `us-west-2b` | `35.155.41.27` | | `us-west-2c` | `35.161.104.252` | | `us-west-2d` | `44.233.51.171` | > [!WARNING] > > Allowlist **all five** addresses. A webhook request can originate from any of these availability zones, so allowlisting only a subset will cause intermittent delivery failures. These addresses are static and shared across all I-9 clients. If they ever change, Symmetry will notify you in advance. ## Failure notifications You can optionally configure a dedicated email address to receive notifications when webhook deliveries fail. Notifications are sent only after all retry attempts have been exhausted. To configure the notifications, specify the target email address within the `failureNotificationEmail` field in the `webhook` object when setting up or updating each employer. # Account-level theming Source: https://docs.symmetry.com/i9/custom-theming/account-level-theming Manage an account-level theme that cascades to every employer. Covers the endpoint, supported methods, configuration structure, and apply, update, and delete examples. Account-level theming is the right choice when you serve multiple employers under one brand, when you prefer managing a theme centrally rather than employer by employer, or when you want to overwrite every existing employer theme at once. It is typically applied during onboarding. ## Endpoint Use this endpoint to manage an account-level application theme that cascades to all employers under your account: `/v1/applicationTheme` ## Supported methods | Method | Behavior | | - | - | | `POST` | Applies a theme to all employers | | `PATCH` | Partially updates the theme for all employers | | `DELETE` | Removes the theme from all employers | Additional behavior: * Requests are rate-limited to 25 requests per second * Cascading updates are processed in parallel > [!WARNING] > > **The cascade reaches only the employers that are active when you apply the theme.** Employers you activate afterward do not inherit it automatically. To bring a new employer in line, either re-apply the account-level theme with `POST`, or [apply a theme directly to that employer](/i9/custom-theming/employer-level-theming). ## Configuration structure All theming customizations are defined within a single JSON object using the structure shown below: ```json theme={null} { "custom_app_theme": { "alerts": {/* Notification styling with variants */}, "body": {/* Body text styling */}, "buttons": {/* Button styling with variants and states */}, "formControl": {/* Input field styling */}, "headings": {/* H1-H6 typography */}, "link": {/* Link styling and hover states */} } } ``` Each section supports a predefined set of properties. Properties outside the supported set are ignored and do not affect the rendered embedded UI. For the full list of customizable properties in each section, see [Custom Theming for Embedded Experiences](/i9/custom-theming/app-theming#supported-elements). ## Examples ### Apply a theme to all employers in your account Use `POST` to create or fully replace the account-level application theme. #### Request `POST /v1/applicationTheme` ```json theme={null} { "custom_app_theme": { "body": { "fontSize": "14px", "color": "#525257" }, "link": { "hoverColor": "#005c5c", "hoverDecoration": "underline", "color": "#0a8080", "decoration": "underline" }, "headings": { "h1": { "fontSize": "32px", "fontWeight": "500", "color": "#262626" }, "h2": { "fontSize": "50px", "fontWeight": "500", "color": "#000fff" } }, "alerts": { "borderWidth": "1px", "borderRadius": "4px", "variants": { "primary": { "backgroundColor": "#fdfcff", "borderColor": "#006cc1" }, "danger": { "backgroundColor": "#fffbfb", "borderColor": "#c53336" } } }, "buttons": { "borderRadius": "4px", "variants": { "primary": { "backgroundColor": "#0A8080", "activeBackgroundColor": "#005c5c" }, "default": { "borderColor": "#1c1c1c" } } }, "formControl": { "borderColor": "#929292", "borderRadius": "4px", "focusBorderColor": "#005c5c" } } } ``` #### Response The response returns the full theme as applied. ### Partially update a theme Use `PATCH` to update only the specified properties. All unspecified properties retain their existing values. #### Request `PATCH /v1/applicationTheme` ```json theme={null} { "custom_app_theme": { "body": { "fontSize": "15px", "color": "#525257" } } } ``` #### Response The response returns the complete theme with the updates applied. ### Delete a theme Deleting the account-level theme causes the embedded UI to fall back to the [Symmetry default theme](/i9/custom-theming/default-app-theme). #### Request `DELETE /v1/applicationTheme` ```bash theme={null} curl -X DELETE "https://api.symmetry.com/i9/v1/applicationTheme" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" ``` #### Response A successful request returns HTTP `200 OK`. # Custom theming for embedded experiences Source: https://docs.symmetry.com/i9/custom-theming/app-theming Apply your branding to embedded Symmetry I-9 experiences. Covers the account and employer theme inheritance model, how it works, and the supported styling elements. Symmetry I-9 supports custom theming for embedded experiences, allowing you to apply your branding to the user interfaces embedded within your platform. Theming applies to both embedded modules included with Symmetry I-9: * **Employee embedded experience**: the interface end users complete to submit Form I-9 * **Administrator embedded experience**: the interface you use to review submissions and take action on E-Verify cases Custom theming enables you to deliver a branded, cohesive experience across these embedded modules while preserving established UI behavior and accessibility standards. ## Theming scope and inheritance model Symmetry I-9 supports a two-tier theming model that lets you manage branding at either the account (service provider) level or the employer level. ### Account-level themes An account-level theme acts as the default theme for your account. * When applied, the theme cascades to all employers under your account * Updates and deletions at this level affect all employers * Account-level `GET` operations return the theme from the first available employer domain Use account-level theming when you want a consistent brand experience across all employers you manage. ### Employer-level themes An employer-level theme applies only to a specific employer. * Employer-level themes override any account-level theme for that employer * Updates affect only the specified employer * Other employers continue to use the account-level theme (if present) or their own employer-level theme Use employer-level theming when you need employer-specific branding. ## How it works Custom themes use a JSON configuration format that automatically translates into CSS variables applied globally across all application pages. The system uses nested JSON structures to organize style properties logically, making theme management straightforward and maintainable. > [!NOTE] > > **Supported customization** > > To ensure usability and visual consistency, only a defined set of styling properties can be modified. > > Unsupported values may still be processed as CSS variables but do not affect rendered UI elements. ## Supported elements Theming allows you to customize specific visual elements across six categories. These settings apply consistently across both embedded experiences. ### Body text and typography Controls the default text styling `body` used throughout the embedded interfaces: | Attribute | Type | Description | | :- | :- | :- | | `fontSize` | string | Base font size for body text (for example,`15px`). | | `color` | string | Base text color for body content. (for example,`#F54927`) | ### Links & navigation Defines how links (`link)` appear and respond to user interaction: | Attribute | Type | Description | | :- | :- | :- | | `color` | string | Default link color | | `decoration` | string | Default text decoration (for example, `underline` or `none`) | | `hoverColor` | string | Link color on hover | | `hoverDecoration` | string | Hover text decoration | ### Headings (H1–H6) Provides consistent styling for all heading levels in the `headings` object (`h1`, `h2`, `h3`, `h4`, `h5`, `h6`): | Attribute | Type | Description | | :- | :- | :- | | `fontSize` | string | Font size for the heading level | | `fontWeight` | string | Weight of the heading text | | `color` | string | Color of the heading text | ![Themed heading levels rendered in the embedded experience](https://mintcdn.com/symmetry-prod/ntGo9oNxMEkTNaTS/i9/assets/images/i9-theming-headings.png?fit=max\&auto=format\&n=ntGo9oNxMEkTNaTS\&q=85\&s=e24949acf4c5d0f2e0b11b4c08652aea) ### Alerts & notifications Customizes `alerts` and notifications using variant-based styling: | Attribute | Type | Description | | :- | :- | :- | | `borderWidth` | string | Border thickness for alerts | | `borderRadius` | string | Corner radius for alert containers | | `variants` | object | Color and border settings for alert variants (possible values:`primary`, `info`, `danger`, `success`, `warning`) | | `variants.backgroundColor` | string | Background color for the alert variant | | `variants.borderColor` | string | Border color for the alert variant | ![The primary, danger, info, warning, and success alert variants](https://mintcdn.com/symmetry-prod/ntGo9oNxMEkTNaTS/i9/assets/images/i9-theming-alerts.png?fit=max\&auto=format\&n=ntGo9oNxMEkTNaTS\&q=85\&s=31510482fcfddcbf6dcd15d5275b3c6f) ### Buttons & interactive elements Controls the appearance of `buttons` across variants and states: | Attribute | Type | Description | | :- | :- | :- | | `borderRadius` | string | Button corner radius within alerts | | `variants` | object | Per-variant button styling | | `variants.backgroundColor` | string | Background color for the button | | `variants.activeBackgroundColor` | string | Background color when the button is active or pressed | | `default` | string | Border color used for the default button style | ![Themed button variants and their active states](https://mintcdn.com/symmetry-prod/ntGo9oNxMEkTNaTS/i9/assets/images/i9-theming-buttons.png?fit=max\&auto=format\&n=ntGo9oNxMEkTNaTS\&q=85\&s=80bd053bad02642f3a2d7f7ec8d9a454) ### Form controls & inputs Ensures consistent styling for user input `formControl` elements: | Attribute | Type | Description | | :- | :- | :- | | `borderColor` | string | Border color applied to inputs and form fields | | `borderRadius` | string | Corner radius for form fields | | `focusBorderColor` | string | Border color when a field is focused | # Employer-level theming Source: https://docs.symmetry.com/i9/custom-theming/employer-level-theming Manage a theme for a specific employer that overrides your account default. Covers supported methods, configuration structure, and CRUD examples. Use this endpoint to manage an application theme for a specific employer: `/v1/employers/{employerId}/applicationTheme` Employer-level themes apply only to the specified employer and take precedence over any account-level theme. They use the same `custom_app_theme` object as account-level themes—see [Custom Theming for Embedded Experiences](/i9/custom-theming/app-theming#supported-elements) for the full list of supported properties. Use an employer-level theme when a single employer needs its own branding, when you support white-label or customer-specific designs, or when you need to override the account default for one employer without affecting the others. ## Supported methods | Method | Behavior | | - | - | | `GET` | Retrieves the theme for the specified employer | | `POST` | Applies a theme to the specified employer | | `PATCH` | Partially updates the theme for the specified employer | | `DELETE` | Removes the theme for the specified employer | ## Configuration structure All theming customizations are defined in a single JSON object under `custom_app_theme`. ```json theme={null} { "custom_app_theme": { "alerts": {/* Notification styling with variants */}, "body": {/* Body text styling */}, "buttons": {/* Button styling with variants and states */}, "formControl": {/* Input field styling */}, "headings": {/* H1-H6 typography */}, "link": {/* Link styling and hover states */} } } ``` Each section supports a predefined set of properties. Any unsupported properties are ignored and do not affect the rendered embedded UI. ## Examples ### Retrieve theme for specific employer #### Request `GET /v1/employers/{employerId}/applicationTheme` ```bash theme={null} curl -X GET \ "https://api.symmetry.com/i9/v1/employers/{employerId}/applicationTheme" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" ``` #### Response Returns the employer's complete `custom_app_theme` object—the same structure shown in the [account-level example](/i9/custom-theming/account-level-theming#apply-a-theme-to-all-employers-in-your-account). ### Apply theme to specific employer Use `POST` to create or fully replace an employer-level theme. The request body is the complete `custom_app_theme` object; see the [account-level example](/i9/custom-theming/account-level-theming#apply-a-theme-to-all-employers-in-your-account) for a full payload. #### Request `POST /v1/employers/{employerId}/applicationTheme` ```json theme={null} { "custom_app_theme": { "body": { "fontSize": "14px", "color": "#525257" }, "link": { "color": "#0a8080", "hoverColor": "#005c5c" } } } ``` #### Response The response returns the full theme as applied. ### Partially update a theme Use `PATCH` to update only the specified properties. All other existing theme values remain unchanged. #### Request `PATCH /v1/employers/{employerId}/applicationTheme` ```json theme={null} { "custom_app_theme": { "body": { "fontSize": "15px", "color": "#525257" } } } ``` #### Response The response returns the complete theme with the updates applied. ### Delete a theme Removing an employer-level theme restores the Symmetry default styling for that employer. Because account-level themes are cascaded to each employer when you apply them rather than inherited at render time, deleting an employer's theme does not restore the account-level theme. To put the account branding back, [re-apply the account-level theme](/i9/custom-theming/account-level-theming) or `POST` the theme to that employer again. #### Request `DELETE /v1/employers/{employerId}/applicationTheme` ```bash theme={null} curl -X DELETE "https://api.symmetry.com/i9/v1/employers/0456sdfAfrd/applicationTheme" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json" ``` #### Response A successful request returns HTTP `200 OK`. # Document verification overview Source: https://docs.symmetry.com/i9/document-verification/overview Document Verification screens Form I-9 supporting documents with OCR. Covers verified document types, the employee experience, the automated checks applied to each document, and managing verification results. Document Verification automates the screening of supporting documentation submitted with Form I-9. It uses Optical Character Recognition (OCR) to extract document details and applies a range of advanced verification checks to support enhanced I-9 compliance. This is a paid feature available for all I-9 clients. Reach out to your account executive if you don't have access to this feature. ## Overview Document verification does the following: 1. Guides the employee through the document upload process and uses OCR that to lift the document numbers automatically to reduce errors 2. Verifies the work authorization document(s) presented match the selected document(s) from Lists A, B, and/or C 3. Confirms work authorization document(s) image is clear, legible, and fully captured within the frame, including all required elements ## Verified documents Symmetry's document verification runs a variety of checks on the following documents when an employee completes Section 1 of the Form I-9: * List A: US Passport, Passport Card, Permanent Resident Card (I-551) * List B: Driver’s License Issued by State, State Issued ID Card * List C: US Social Security Card The list above represents approximately 90% of the documents commonly used to verify citizenship status using Form I-9 through Symmetry. ### Employee experience Once the employee selects their List A, B and/or C documents, Symmetry will begin the Document Verification process of guiding the employee through capturing the photos. ![](https://mintcdn.com/symmetry-prod/ntGo9oNxMEkTNaTS/i9/assets/images/36863687083284.png?fit=max\&auto=format\&n=ntGo9oNxMEkTNaTS\&q=85\&s=20f7dd99e1ff0e0bda10b6d9af4060bc) Once documentation is uploaded, the document verification process begins automatically. If a document fails verification, the employee can still complete Section 1 and, if using an Authorized Representative, proceed with Section 2. The verification status will be visible to the company’s administrator within the embedded employer experience for any required follow-up. ## Verification checks Each uploaded document is put through a series of automated checks. Which checks apply depends on the document presented. | Check | What it confirms | | - | - | | Processable submission | The upload is readable and not corrupted. | | Document type detection | The document presented matches the document type the employee selected. | | Government entity detection | The document is an official government-issued ID. | | Allowed country | The issuing country is permitted for the selected document type. | | Extracted properties | The required fields could be read from the document. | | Expired detection | The document is not past its expiration date. | Some checks apply only to particular documents: * **Double-side detection.** For documents requiring a front and a back, confirms two distinct sides were uploaded rather than the same side twice. * **Barcode detection.** For a driver's license or state-issued ID, confirms a barcode is present and can be decoded. * **Image metadata detection.** For a Permanent Resident Card, flags signs of photo editing that may indicate alteration. * **Social Security card checks.** Confirms the key data can be read and that the card is an unrestricted card. > [!NOTE] > > A failed check does not establish that a document is invalid. The most common cause is a mismatch between the document presented and the List A, B, or C selection the employee made, or an image that was unclear or incompletely framed. Review the result and the document before drawing a conclusion. See [Unable to verify](#unable-to-verify). ## Managing document verification After document verification is complete, administrators can review the following results: * Verified * Unable to Verify * Reviewed by Admin Within the employer embedded mode, administrators can see and filter for verification status across all I-9 management tabs. Please note that these statuses are not a reflection of acceptance or rejection of the I-9 submission itself, nor are they linked to E-Verify statuses. Rather, they provide additional insight into the enhanced document review process and allow HR admins additional insight into documents submitted. ![](https://mintcdn.com/symmetry-prod/ntGo9oNxMEkTNaTS/i9/assets/images/36864072334996.png?fit=max\&auto=format\&n=ntGo9oNxMEkTNaTS\&q=85\&s=c30756ccc207bce637a351b808c7fc4a) ### Verified If the document submission from the employee is verified, it will appear in the applicable I-9 forms tab with a ‘Verified’ tag (indicated in green). There is no additional action required for verified submissions. The details of the verification can be viewed by clicking on the 'Verified' badge. These results can also be seen with the Form I-9 submission. ### Unable to verify An administrator may need to take action when a document fails document verification. Administrators can review all failed verification results within the applicable I-9 forms tabs with the "Unable to Verify" status. ![](https://mintcdn.com/symmetry-prod/ntGo9oNxMEkTNaTS/i9/assets/images/36896646786196.png?fit=max\&auto=format\&n=ntGo9oNxMEkTNaTS\&q=85\&s=5fd6dc162d4d5f2b011797853182d3f4) To review the results, an administrator should click on the "Unable to Verify" status to see the document and result details. Review the results and document, input your findings in the optional comments box, and select the "Mark as Reviewed" button (indicated in blue). ![](https://mintcdn.com/symmetry-prod/ntGo9oNxMEkTNaTS/i9/assets/images/36896646788372.png?fit=max\&auto=format\&n=ntGo9oNxMEkTNaTS\&q=85\&s=5f6441539946089a3990a87295164f7d) Once the administrator reviews the document verification results, the status will be updated to "Reviewed by Admin." This review is only a confirmation that you have reviewed the document and does not update the Form I-9 itself. If there are additional steps you need to make on the submission, they must be done on the Form I-9 (for example, accept or reject). > [!WARNING] > > Please note: webbooks are not supported for document verification. Therefore, administrators will need to review within the respective I-9 form tabs. # E-Verify case statuses Source: https://docs.symmetry.com/i9/e-verify/case-statuses Reference for every E-Verify case status Symmetry returns: what each status means and the action needed to move a case toward resolution. Below is the full list of E-Verify case status values returned from Symmetry. | Symmetry Status | Administrator Action Required | E-Verify Status Mapping | | :- | :- | :- | | `close_case_and_resubmit` | Yes | 'CLOSE\_CASE\_AND\_RESUBMIT' | | `closed_authorized` | No | 'Closed - Authorized' | | `closed_nonconfirmation` | Yes | 'Closed - Unauthorized' | | `closed_other` | No | 'Closed - Other' | | `created` | No | 'Awaiting submission to E-Verify' | | `draft` | No | 'DRAFT' | | `employment_authorized` | No | 'EMPLOYMENT\_AUTHORIZED' | | `final_nonconfirmation` | Yes | 'FINAL\_NONCONFIRMATION' | | `internal_error` | No | 'Internal Error' | | `manual_review` | No | 'MANUAL\_REVIEW' | | `manually_closed` | No | 'Closed by Admin' | | `pending_referral` | Yes | 'Tentative Nonconfirmation' | | `photo_match` | Yes | 'PHOTO\_MATCH' | | `queued` | No | 'QUEUED' | | `referred` | Yes | 'REFERRED' | | `scan_and_upload` | Yes | 'SCAN\_AND\_UPLOAD' | | `submission_error` | No | 'Submission Error' | | `submitted` | No | 'Submitted' | | `unconfirmed_data` | Yes | 'UNCONFIRMED\_DATA' | | `unsubmitted_receipt` | No | 'Unsubmitted' | # Configure E-Verify Source: https://docs.symmetry.com/i9/e-verify/configure Configure E-Verify for an employer after registering it and its administrator. Covers the request and response elements and the two-step implementation process. Once you've registered your employer and administrator, the next step is to configure E-Verify for any employer that will be using the E-Verify program as part of the I-9 process. E-Verify configuration can be set up in two ways: 1. **API Setup** – use the API to pass E-Verify credentials directly for an employer. This avoids requiring the administrator to key them in manually through Embedded Mode. 2. **Embedded Mode Setup** – generate a secure, embeddable link that allows an administrator to sign in and configure E-Verify credentials through the UI. This remains the method for ongoing credential updates. ## Option 1: Configure E-Verify using the API Use the following endpoint to establish E-Verify credentials for an employer with an active E-Verify account: POST `/v1/employers/{employerId}/everifySettings` ### Request ```json theme={null} { "companyId": "123456", "programAdministratorId": "789012", "programAdministratorFirstName": "John", "programAdministratorLastName": "Doe", "programAdministratorEmail": "john.doe@example.com", "programAdministratorPhone": "234-567-8901", "webServiceUsername": "everify_user", "webServicePassword": "everify_pwd" } ``` #### Request elements | Element | Description | | - | - | | `companyId` | The employer’s E-Verify company ID (from the E-Verify portal, company profile). | | `programAdministratorId` | The E-Verify user profile ID (from the E-Verify portal, user profile). | | `programAdministratorFirstName` | Program Administrator’s first name (from the E-Verify portal). | | `programAdministratorLastName` | Program Administrator’s last name (from the E-Verify portal). | | `programAdministratorEmail` | Program Administrator’s email (from the E-Verify portal). | | `programAdministratorPhone` | Program Administrator’s phone number (from the E-Verify portal). | | `webServiceUsername` | The E-Verify web service user ID (from the E-Verify portal, web service profile). *Note: this is an ID, not an email.* | | `webServicePassword` | The E-Verify web service password (from the E-Verify portal, web service profile). | ##### E-Verify mapping Below you'll find screenshots from the E-Verify portal where you can find the data needed for the request. | | E-Verify Portal | | :- | :- | | Company ID | ![E-Verify company profile with the Company ID field highlighted](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/i9/assets/images/41354944436628.jpg?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=e2f66d5afe640d90b1b2f906dfc46e7a) | | User Credentials | ![E-Verify user profile mapped to the programAdministrator fields](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/i9/assets/images/41354944437524.jpg?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=aadf338668ad71071f33f38528d5aac5) | | Webservice Credentials: navigation to webservice user | ![Navigating to the webservice user in the E-Verify portal](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/i9/assets/images/41355181870612.jpg?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=0499887d5f65926ab0d3857d00108c89) | | Webservice Credentials: webservice username and password | ![Webservice user information showing the user ID and password fields](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/i9/assets/images/41354944438804.jpg?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=998af84e6e38b79a07b98db98a30b6a3) | ### Response The API will return the saved E-Verify settings in the `everifySettings` object. ```json theme={null} { "everifySettings": { "companyId": "123456", "programAdministratorId": "789012", "programAdministratorFirstName": "John", "programAdministratorLastName": "Doe", "programAdministratorEmail": "john.doe@example.com", "programAdministratorPhone": "234-567-8901", "webServiceUsername": "everify_user", "webServicePassword": "everify123", "everifyAuthenticated": false } } ``` The response always returns `everifyAuthenticated` as `false`, because Symmetry attempts to authenticate the credentials after the request completes. To get the authentication result, [check the E-Verify authentication status](#check-e-verify-authentication-status) or subscribe to the `employer.everifyAuthenticationResult` webhook. ## Option 2: Configure E-Verify via embedded mode The embedded E-Verify settings page lets a company administrator enter the employer's E-Verify credentials directly in your platform. It collects the same values as the API request above, so the administrator can complete setup without you handling credentials. ![The embedded Configure E-Verify form, with fields for company ID, program administrator details, and web services credentials](https://mintcdn.com/symmetry-prod/iQnpDJuhlimWxDgw/i9/assets/images/38481639418260.png?fit=max\&auto=format\&n=iQnpDJuhlimWxDgw\&q=85\&s=cd6746aabacd86c2939271159faa9e67) Embedded E-Verify settings page Implementing Embedded Mode configuration in your platform is a two-step process: 1. Authenticate the administrator using the `authenticateUri` 2. Navigate to the `embeddedUri` to complete the configuration The administrator must be authenticated *before* accessing the E-Verify settings page. Both links are returned by the API and must be used in sequence to ensure a successful configuration. > [!NOTE] > > **Enabling E-Verify makes start date mandatory.** E-Verify requires every Form I-9 to include the employee's first day of employment, which Symmetry stores as `startDate`. Once E-Verify is enabled, a `startDate` is required for every employee under that employer and is sent to E-Verify with each Form I-9. See [Configure Employees & Administrators](/i9/getting-started/configure-employees-and-administrators) for where that field is set. ## Generate E-Verify configuration page The `/employers/{employerId}/admins/{adminId}/everifySettings/generateEverifySettingsUri` GET endpoint generates a secure, embeddable link to the E-Verify configuration for a valid administrator. Once embedded in your platform, the administrator can complete the form to enable automatic E-Verify case creation for all completed Forms I-9 under the employer. ### Request ```bash theme={null} curl --location 'https://api.symmetry.com/i9/v1/employers/01971d41-b29d-75cf-a308-12345678/admins/01972152-29ab-78f4-93ce-12345678/everifySettings/generateEverifySettingsUri' \ --header 'Authorization: Bearer ••••••' ``` #### Path parameters | Element | Type | Description | | :- | :- | :- | | `employerId` | string | The unique identifier of the employer for whom E-Verify is being configured. | | `adminId` | string | The ID of the administrator completing the E-Verify configuration. | ### Response A successful response returns a `token` object with two URLs: one for authentication and one for accessing the configuration page. ```json theme={null} { "token": { "authenticateUri": "https://symmetry.workbright.com/sign_in_with_token?token=12345670a239f8b5809c", "embeddedUri": "https://symmetry.workbright.com/admin/everify/accounts" } } ``` #### Two-step implementation process To integrate the E-Verify settings page into your platform: 1. Authenticate the administrator using the `authenticateUri`: this one-time-use token link signs the user in securely 2. Embed or redirect to the `embeddedUri`: this opens the E-Verify settings form for configuration * The administrator must be signed in using the `authenticateUri` **before** accessing the `embeddedUri`, or the page will not load properly. #### Response elements Below are the fields returned in the `token` object. | Element | Type | Description | | :- | :- | :- | | `authenticateUri` | string | A secure, one-time-use link that signs the administrator in directly using a token | | `embeddedUri` | string | A direct link to the E-Verify configuration page where the authenticated administrator can complete or manage E-Verify setup for the employer. The administrator must be authenticated using the `authenticateUri` prior to accessing the `embeddedUri`. | > [!NOTE] > > **Monitor E-Verify Credential Authentication** > > Subscribe to the `employer.everifyAuthenticationResult` webhook event to receive updates on E-Verify credential authentication. Authentication occurs when credentials are added or updated and continues to run daily, so this event may be sent regularly. ## Check E-Verify authentication status Use the following endpoint to check whether an employer's E-Verify Web Services credentials are currently valid: GET `/v1/employers/{employerId}/everifySettings` The response returns the employer's saved E-Verify settings in the `everifySettings` object, including the read-only `everifyAuthenticated` field. ```json theme={null} { "everifySettings": { "companyId": "123456", "programAdministratorId": "789012", "programAdministratorFirstName": "John", "programAdministratorLastName": "Doe", "programAdministratorEmail": "john.doe@example.com", "programAdministratorPhone": "234-567-8901", "webServiceUsername": "everify_user", "everifyAuthenticated": true } } ``` | Element | Type | Description | | :- | :- | :- | | `everifyAuthenticated` | boolean | Whether the employer's E-Verify Web Services credentials are valid as of the most recent credential check. Returns `false` until the first successful authentication. Credentials are re-checked daily, so this value can return to `false` if a later check fails. | `everifyAuthenticated` is read-only. If you send it in a `POST` or `PATCH` request, Symmetry ignores the value and the request still succeeds. `POST` and `PATCH` responses always return `false`, so call `GET` afterward to read the result. If the employer has no E-Verify account configured, `GET` and `PATCH /v1/employers/{employerId}/everifySettings` return `404`. # Manage E-Verify cases (API) Source: https://docs.symmetry.com/i9/e-verify/manage-cases-api Retrieve and manage automatically created E-Verify cases through the API. Covers the case list and detail endpoints, query parameters, and response fields. Once [E-Verify has been configured](/i9/e-verify/configure) and Forms I-9 are completed by employees, E-Verify cases will be automatically created. As a reminder, E-Verify is configured at the employer level. While case actions (for example, photo confirmations and unconfirmed data) are handled by administrators through the embedded experience, you can access E-Verify case data through the API to support integration, reporting, and workflow logic. Available Endpoints 1. [Retrieve all E-Verify cases for an employer](/i9/e-verify/manage-cases-api#retrieve-all-e-verify-cases-for-an-employer) 2. [Retrieve detailed E-Verify case data](/i9/e-verify/manage-cases-api#retrieve-detailed-e-verify-case-data) 3. [Retrieve E-Verify account settings](/i9/e-verify/manage-cases-api#retrieve-e-verify-account-settings) ## Retrieve all e-verify cases for an employer To return all cases for a specific employer, call the `/employers/{employerId}/everifyCases` GET endpoint. This endpoint returns summary information only. To view or manage a case, the employer administrator must log into the embedded E-Verify experience—see [Accessing the E-Verify Case Index](/i9/e-verify/case-index). ### Sample cURL request ```bash theme={null} curl --location 'https://api.symmetry.com/i9/v1/employers/0197145/everifyCases' \ --header 'Authorization: Bearer ••••••' ``` #### Query parameter | Parameter | Type | Required | Description | | - | - | - | - | | `employerId` | string | Yes | The unique ID of the employer whose E-Verify cases you want to retrieve. | ### Sample response ```json theme={null} { "everifyCases": [ { "id": "0196ab0756754", "submissionId": 72, "caseId": "2025123482085BU", "caseStatus": "closed_authorized" } ] } ``` #### Response fields | Field | Type | Description | | - | - | - | | `id` | string | Internal ID used to fetch full case data using the `/employers/{employerId}/everifyCases/{id}` endpoint. | | `submissionId` | integer | ID of the I-9 submission that triggered the case. | | `caseId` | string | E-Verify-assigned case ID. | | `caseStatus` | string | Current case status. See [all possible values here](/i9/e-verify/case-statuses). | ## Retrieve detailed E-verify case data The `/employers/{employerId}/everifyCases/{id}` endpoint retrieves detailed information for a specific E-Verify case, including timestamps, raw response data, and audit logs. While this endpoint gives insight into the case’s history and result, **all case actions must be taken within the embedded E-Verify experience** by the employer’s administrator. ### Sample cURL request ```bash theme={null} curl --location 'https://api.symmetry.com/i9/v1/employers/0197ad3412345/everifyCases/36'\ --header 'Authorization: Bearer ••••••' ``` #### Query parameter | Parameter | Type | Required | Description | | - | - | - | - | | `id` | string | Yes | The Symmetry `everifyCases.id` value returned from the `/everifyCases` endpoint. This is distinct from the `caseId`. | | `employerId` | string | Yes | The unique ID of the employer whose E-Verify case you want to retrieve. | ### Sample response ```json theme={null} { "id": "0196ab07", "submission": { "submissionId": 72, "employeeId": "0196ab05" }, "everifyCase": { "caseId": "2025384082085BU", "caseCreatedAt": "2025-05-05T15:45:15.000-06:00", "caseResultAt": "2025-05-05T15:45:17.000-06:00", "receipt": false, "caseStatus": "closed_authorized", "everifyAccountId": 1, "rawResponse": { "caseStatus": "CLOSED", "caseStatusDisplay": "Closed", "caseEligibilityStatement": "EMPLOYMENT_AUTHORIZED" }, "auditLogs": [ { "name": "case_status_change", "details": { "status": "submitted" }, "serverTimestamp": "2025-05-05T15:45:15-06:00" }, { "name": "case_status_change", "details": { "status": "draft" }, "serverTimestamp": "2025-05-05T15:45:15-06:00" }, { "name": "case_status_change", "details": { "status": "closed_authorized" }, "serverTimestamp": "2025-05-05T15:45:17-06:00" } ], "tncI9Correct": false, "visitEverify": false, "deleteable": false, "unconfirmedDataFields": [] } } ``` #### Response fields ##### Top-level response fields | Field | Type | Description | | - | - | - | | `id` | string | Symmetry E-Verify case record ID | | `submission` | object | Metadata about the I-9 submission | | `everifyCase` | object | Detailed case information from the E-Verify system | ##### `submission` object | Field | Type | Description | | - | - | - | | `submissionId` | integer | ID of the I-9 submission | | `employeeId` | string | Unique identifier for the employee | ##### `everifyCase` object | Field | Type | Description | | - | - | - | | `caseId` | string | Department of Homeland Security E-Verify case ID | | `caseCreatedAt` | timestamp | When the case was submitted to E-Verify | | `caseResultAt` | timestamp | When the result was returned from E-Verify | | `receipt` | boolean | Indicates if a receipt was used in document verification | | `deadlineOn` | string | Deadline for admin/employee action to resolve the case | | `caseStatus` | string | Internal case status (e.g., `closed_authorized`). [See all possible values](/i9/e-verify/case-statuses). | | `everifyAccountId` | integer | Symmetry's internal account ID that represents a customer's E-Verify account | | `rawResponse` | object | Returns official DHS E-Verify case status values from the E-Verify API | | `auditLogs` | array | List of events relating to the E-Verify case. See the [audit log object](/i9/compliance-and-audit-readiness/audit-logs#audit-logs-array) for more information. | | `fanUrl` | string | Further Action Notice PDF URL (English) | | `rdcUrl` | string | Referral Date Confirmation PDF URL (English) | | `fanUrlSpanish` | string | Further Action Notice PDF URL (Spanish) | | `rdcUrlSpanish` | string | Referral Date Confirmation PDF URL(Spanish) | | `fanReviewed` | boolean | Whether the FAN has been reviewed | | `tncReview` | array of strings | Return a value based on the action taken by the employee | | `tncAction` | string | Returns a value of `referred` if the employee took acton on a tentative non-confirmation | | `tncI9Correct` | boolean | Whether the TNC is due to incorrect I-9 data | | `closureReasons` | array | Closure reason codes (`name`, `code` per item) | | `errors` | array of objects | Submission error details when present | | `visitEverify` | boolean | If true, must visit E-Verify's website to continue. Typically affects cases in the following statuses: `unconfirmed_data`, `scan_and_upload`, `pending_referral`, `referred`, `closed_other`, `close_case_and_resubmit`, `final_nonconfirmation`, `internal_error` | | `submissionErrorType` | string | Error type | | `duplicateContinueReasons` | array | Reasons selected when continuing a duplicate case | | `duplicateContinueReasonCode` | string | Code: `REHIRE`, `PREVIOUS_CASE_RESULT_RESUBMIT`, and more | | `duplicateContinueReasonOther` | string | Admin free-text for duplicate continue. | | `deleteable` | boolean | Indicates whether the case is eligible for deletion. Returns `true` for cases in the following statuses: `internal_error`, `submission_error`. | | `unconfirmedDataFields` | array | Returns the values that cause the unconfirmed data error | ##### `rawResponse` object | Field | Type | Description | | - | - | - | | `caseStatus` | string | E-Verify system `"case_status"` value (for example, `CLOSED`) | | `caseStatusDisplay` | string | E-Verify system `"case_status_display"` value (for example, `Closed`) | | `caseEligibilityStatement` | string | E-Verify system `"case_eligibility_statement"` value (for example, `EMPLOYMENT_AUTHORIZED`) | ##### `auditLogs` array | Field | Type | Description | | - | - | - | | `name` | string | Type of event. Possible values: `case_status_change`, `tnc_notification_sent_event`, `case_photo_matching_confirmation`, `case_scan_and_upload`, `case_confirmed_data`, `case_close`, `case_existing_draft_close`, `case_resubmitted`, `tnc_no_action`, `tnc_refer_case` | | `details.status` | string | E-Verify case status. Possible values: `closed_authorized`, `closed_nonconfirmation`, `closed_other`, `created`, `draft`, `employment_authorized`, `final_nonconfirmation`, `close_case_and_resubmit`, `internal_error`, `manual_review`, `pending_referral`, `manually_closed`, `photo_match`, `queued`, `referred`, `scan_and_upload`, `submission_error`, `submitted`, `unconfirmed_data`, `unsubmitted_receipt` | | `serverTimestamp` | timestamp | When the status change occurred | ## Retrieve E-Verify account settings Use the `/employers/{employerId}/everifySettings` GET endpoint to retrieve the current E-Verify configuration for an employer. This is helpful for verifying whether E-Verify has been configured and for displaying the stored administrator and credential settings in a UI. ### Sample cURL request ```bash theme={null} curl --location 'https://api.symmetry.com/i9/v1/employers/0197145/everifySettings' \ --header 'Authorization: Bearer ••••••' ``` #### Query parameter | Parameter | Type | Required | Description | | - | - | - | - | | `employerId` | string | Yes | The unique ID of the employer whose E-Verify cases you want to retrieve. | ### Sample response ```json theme={null} { "everifySettings": { "companyId": "123456", "programAdministratorEmail": "john.doe@example.com", "programAdministratorFirstName": "John", "programAdministratorId": "789012", "programAdministratorLastName": "Doe", "programAdministratorPhone": "234-567-8901", "webServiceUsername": "everify_user" } } ``` #### Elements | Element | Description | | - | - | | `companyId` | The employer's E-Verify Company ID found in the Company Profile within the E-Verify portal | | `programAdministratorId` | The E-Verify user profile ID found on the User Profile page | | `programAdministratorFirstName` | The E-Verify user’s first name from the User Profile | | `programAdministratorLastName` | The E-Verify user’s last name from the User Profile | | `programAdministratorEmail` | The E-Verify user’s email address from the User Profile | | `programAdministratorPhone` | The E-Verify user’s phone number from the User Profile | | `webServiceUsername` | The Web Services user ID found within the Web Services profile (this is an ID, not an email address) | | `webServicePassword` | The Web Services password associated with the Web Services user | # Resolve an E-Verify TNC Source: https://docs.symmetry.com/i9/e-verify/tentative-nonconfirmations-tncs Build the TNC workflow end to end. Covers the pending_referral webhook, retrieving FAN and RDC documents from the case detail API, employee and administrator embedded sessions, and status transitions. When E-Verify issues a Tentative Nonconfirmation (TNC), the E-Verify case `status` in Symmetry I-9 becomes `pending_referral`. The employer must present a Further Action Notice (FAN) to the employee and record the employee’s election. This page covers the integration work. For what a TNC and FAN are and the obligations each triggers, see [TNCs and FANs](/i9/e-verify/tncs-and-fans). > [!WARNING] > > **Symmetry does not notify employees directly** > > Your platform is responsible for alerting employees and administrators when webhooks indicate action is required. ## Prerequisites * [Webhooks](/i9/core-concepts/webhooks) configured * [E-Verify configured](/i9/e-verify/configure) for the employer * Familiarity with [E-Verify case statuses](/i9/e-verify/case-statuses) and [Manage E-Verify](/i9/e-verify/manage-cases-api) ## Trigger: `pending_referral` webhook When a case receives a TNC result from E-Verify, Symmetry sends `employee.everifyCaseUpdate` with `status` set to `pending_referral`: ```json theme={null} { "eventKey": "employee.everifyCaseUpdate", "timestamp": "2026-05-19T15:20:20.000Z", "data": { "employerId": "01971d41-b29d-75cf-a308-12345", "employeeId": "01971d45-777a-7002-b025-6789", "everifyCase": { "submissionId": 111, "caseId": "202573907331234", "closed": false, "status": "pending_referral" } } } ``` The webhook payload is intentionally lightweight. It does not include FAN PDF URLs or referral deadlines. Use the case detail API, described in [Phase 1](#phase-1-tnc-issued-pending_referral) below, to enrich your UI. ## Phase 1: TNC issued (`pending_referral`) ### 1. Handle the webhook Store at minimum: * `employerId`, `employeeId` * `everifyCase.submissionId`, `everifyCase.caseId` * `everifyCase.status` (`pending_referral`) ### 2. Enrich case data (optional but recommended) Fetch the full case details for the employer: ```bash theme={null} curl --location 'https://api.symmetry.com/i9/v1/employers/{employerId}/everifyCases' \ --header 'Authorization: Bearer ••••••' ``` Match the list entry where `submissionId` equals the webhook value. Then get the specific E-Verify case details: ```bash theme={null} curl --location 'https://api.symmetry.com/i9/v1/employers/{employerId}/everifyCases/{id}' \ --header 'Authorization: Bearer ••••••' ``` > [!TIP] > > **The `{id}` path parameter is Symmetry’s internal case record ID from the list response—not the DHS `caseId`.** Sample response: ```json theme={null} { "id": 67, "submission": { "submissionId": 315, "employeeId": "019e6aea-c187-78f0-bfb9-1234" }, "everifyCase": { "caseId": "20265447951234", "caseCreatedAt": "2026-05-27T14:07:16.000-06:00", "caseResultAt": "2026-05-27T15:03:51.000-06:00", "receipt": false, "deadlineOn": "2026-06-10", "caseStatus": "pending_referral", "everifyAccountId": 1, "rawResponse": { "caseStatus": "PENDING_REFERRAL", "caseStatusDisplay": "Tentative Nonconfirmation (DHS)", "dhsReferralStatus": "PENDING_REFERRAL" }, "auditLogs": [ { "name": "case_status_change", "details": { "status": "submitted" }, "serverTimestamp": "2026-05-27T14:07:16-06:00" }, { "name": "case_status_change", "details": { "status": "draft" }, "serverTimestamp": "2026-05-27T14:07:16-06:00" }, { "name": "case_status_change", "details": { "status": "photo_match" }, "serverTimestamp": "2026-05-27T14:07:17-06:00" }, { "name": "case_photo_matching_confirmation", "details": { "status": "Photo Matching Confirmation: not-matching", "subdomain": "symmetry", "actorName": "Admin Test", "subsidiary": "null", "photoConfirmation": "not-matching" }, "actorId": "3698123", "actorType": "User", "serverTimestamp": "2026-05-27T14:14:13-06:00" }, { "name": "case_status_change", "details": { "status": "pending_referral" }, "serverTimestamp": "2026-05-27T15:03:51-06:00" } ], "fanUrl": "https://wb-everify-tnc-documents.s3.us-west-1.amazonaws.com/symmetry-sandbox/fan/67/further_action_notice.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJHQUB3XUO6DDQXWQ%2F20260528%2Fus-west-1%2Fs3%2Faws4_request&X-Amz-Date=20260528T022329Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=d53e2f78e282dd88be4f43cee44428121050a0b208dabc15ccfcef230c6baa34", "fanUrlSpanish": "https://wb-everify-tnc-documents.s3.us-west-1.amazonaws.com/symmetry-sandbox/fan/67/further_action_notice_spanish.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAJHQUB3XUO6DDQXWQ%2F20260528%2Fus-west-1%2Fs3%2Faws4_request&X-Amz-Date=20260528T022329Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=85ba8991311ce7b42d2eb6d4520097c7afb5166207ae7b906f3c6747a406c4d4", "tncI9Correct": false, "closureReasons": [ { "name": "The case is being closed because the data entered is incorrect.", "code": "INCORRECT_DATA" }, { "name": "The case is being closed because another case with the same data already exists.", "code": "DUPLICATE_CASE_DATA_EXISTS" }, { "name": "The case is being closed with a reason of \"Other\".", "code": "OTHER_FREE_TEXT" } ], "visitEverify": true, "deleteable": false, "unconfirmedDataFields": [] } } ``` Useful fields for TNC ([full E-Verify object](/i9/e-verify/manage-cases-api#everifycase-object)): | Field | Use | | :- | :- | | `deadlineOn` | Federal referral/contest window—show prominently to the employee | | `fanUrl`, `fanUrlSpanish` | Links to the English and Spanish Further Action Notice PDFs that E-Verify issued for this case | | `rdcUrl`, `rdcUrlSpanish` | Links to the English and Spanish Referral Date Confirmation PDFs from E-Verify. Present once the case is `referred`. | | `visitEverify` | Often true for `pending_referral` and `referred`—indicates DHS/SSA involvement may be required | | `tncI9Correct` | Indicates whether the employee confirmed the I-9 information is correct after TNC. Returns `true` if confirmed correct and `false` if confirmed incorrect. | The notice URLs are pre-signed and expire, so request the case detail when you need to present a document rather than storing the link. ### 3. Notify and launch the employee session Alert the employee in your app, then request an access token: ```bash theme={null} curl --location 'https://api.symmetry.com/i9/v1/employers/{employerId}/employees/{employeeId}/generateToken' \ --header 'Authorization: Bearer ••••••' ``` Sample response: ```json theme={null} { "token": { "embeddedUri": "https://symmetry-sandbox.workbright.com/embedded/new_sign_in?token=412345" } } ``` Embed or redirect to `embeddedUri`, not the raw API URL. Tokens are valid for 30 minutes. See [Authentication](/i9/core-concepts/authentication). ### 4. Employee actions in embedded UI When the employee is authenticated into the embedded experience, they will see an action-required banner to review their E-Verify case. ![Action-required banner prompting the employee to review their E-Verify case](https://mintcdn.com/symmetry-prod/ntGo9oNxMEkTNaTS/i9/assets/images/i9-everify-employee-embedded-tnc.png?fit=max\&auto=format\&n=ntGo9oNxMEkTNaTS\&q=85\&s=c0aec5db71da0de2cf9cf163b6a142b9) Employee embedded experience: E-Verify case action required The employee will be presented with the following election options: | Election | Typical outcome | | :- | :- | | **Information is incorrect** | Signals an I-9 data problem; administrator will need to close the case and trigger a new I-9 for the employee. | | **Information is correct → Employee will take action** (contest) | Case moves toward `referred`; employee must contact SSA and/or DHS within the window shown by `deadlineOn`. | | **Information is correct → Will not take action** | Case progresses toward closure as unauthorized / no contest. | | **FAN acknowledgment** (all paths) | Employee confirms they received and reviewed the FAN. | ![Further Action Notice acknowledgement screen with the employee's election options](https://mintcdn.com/symmetry-prod/ntGo9oNxMEkTNaTS/i9/assets/images/i9-everify-employee-fan-notice.png?fit=max\&auto=format\&n=ntGo9oNxMEkTNaTS\&q=85\&s=c997b49c678c3221360d1b7211128687) Employee embedded experience: FAN acknowledgement and election ## Phase 2: While `status` remains `pending_referral` * Case status may stay `pending_referral` until employee elections and administrator attestation are recorded. * Listen for a new `employee.everifyCaseUpdate` webhook that indicates a change in `status`. * Display `deadlineOn` from case detail in employee-facing copy when available. ## Phase 3: Administrator completion ### 1. Notify the administrator `pending_referral` requires administrator action. ### 2. Launch administrator E-Verify UI Use the E-Verify case index endpoint: ```bash theme={null} curl --location 'https://api.symmetry.com/i9/v1/employers/{employerId}/admins/{adminId}/everifyCases/generateUri' \ --header 'Authorization: Bearer ••••••' ``` Sample response: ```json theme={null} { "token": { "authenticateUri": "https://symmetry-sandbox.workbright.com/sign_in_with_token?token=1234", "embeddedUri": "https://symmetry-sandbox.workbright.com/everify/cases" } } ``` Open `authenticateUri` first, then `embeddedUri`. ### 3. Administrator actions in embedded UI In the E-Verify case UI, the administrator typically: * Sees the case as **Pending Referral (TNC)**. * Checks **“I presented the FAN to the employee and informed them of their options.”** * If the employee reported **incorrect I-9 information**: closes the case (for example, incorrect data) and initiates a new I-9 for the employee. * If the employee **will contest**: monitors the case after it becomes `referred`; the employee contacts SSA/DHS and may need [E-Verify.gov](https://www.e-verify.gov/) when `visitEverify` is `true`. ## Phase 4: Status transitions after employee election | Status | Meaning | Service provider action | | :- | :- | :- | | `referred` | Employee chose to contest | Present the Referral Date Confirmation (`rdcUrl` / `rdcUrlSpanish`) from case detail; remind employee of `deadlineOn`; keep admin tasks open; monitor webhooks. | | `close_case_and_resubmit` | I-9 data requires correction | Guide admin to new I-9 via embedded administrator experience. | | `employment_authorized` / `closed_authorized` | Favorable resolution | Clear employee and admin alerts. | | `final_nonconfirmation` / `closed_nonconfirmation` | Unfavorable outcome | Trigger your HR/compliance workflow. | Status transitions produce a new `employee.everifyCaseUpdate` webhook. # Embedded employer experience Source: https://docs.symmetry.com/i9/embedded-experiences/employer-experience The embedded administrator experience for managing I-9s. Covers configuring E-Verify, actioning I-9 submissions, and reviewing the employee dashboard. The embedded employer experience allows administrators to manage the I-9 verification process: * [Configure E-Verify settings](#configure-e-verify-settings) * [Action on employee I-9 submissions](#action-on-i-9-submissions) * [Review employee employee progress](#review-the-employee-dashboard) ## Configure E-Verify settings Administrators connect an employer's E-Verify web services account from the embedded E-Verify settings module. To launch it within your application, make a GET request to the `/employers/{employerId}/admins/{adminId}/everifySettings/generateEverifySettingsUri` endpoint. Once the connection is established, Symmetry automatically initiates an E-Verify case as soon as your company administrator or Authorized Representative signs Section 2 of the Form I-9. For the full setup path—the credentials to enter, the API alternative, and how to create an account—see: * [E-Verify Overview](/i9/e-verify/overview) * [Configure E-Verify](/i9/e-verify/configure) * [Creating an E-Verify Account to Integrate with Symmetry](/i9/e-verify/create-account) * [Managing E-Verify Cases](/i9/e-verify/managing-cases) ## Action on I-9 submissions As noted in the [Employer Workflow Overview](/i9/getting-started/action-on-i-9), there are instances where an employer will need to take action on the employee's I-9 submission using the employer embedded experience: 1. Complete section 2 if the employer is not using alternative procedure 2. Document fails verification 3. E-Verify cases that are not returned as "closed" (for example, Tentative Non-Confirmation, Photo-Match, Unconfirmed Data, Scan and Upload, and Manual Review statuses) 4. Document receipt is provided As a reminder, to access the employer embedded experience through the API, you will make a GET request with the administrator and employer ID to the `/v1/employers/{employerId}/admins/{adminId}/generateToken` endpoint. A successful response will return an `embeddedUri` that you can use to embed within your product. Read more on how to launch the employer embedded mode: [Initiate employer embedded access](/i9/getting-started/action-on-i-9). ## Review the employee dashboard Within the embedded experience, administrators can review employees' I-9 progress and take action when necessary. The following portlets allow administrators to track the entire employee I-9 lifecycle. * **E-Verify summary**: review and take action on E-Verify cases * **Form I-9 summary**: see the status of all Forms I-9 within your organization * **Staff progress summary**: review employee sign-in activity and required forms * **Alerts**: Forms I-9 that require immediate attention (past due or incomplete) as well as upcoming due dates * **Expiring I-9 documents requiring review**: stay on top of document expiration dates and know when to request additional documentation from your employees ![](https://mintcdn.com/symmetry-prod/ntGo9oNxMEkTNaTS/i9/assets/images/37979415998740.png?fit=max\&auto=format\&n=ntGo9oNxMEkTNaTS\&q=85\&s=a8f6a9acbec1b4cffefcfbb8a69c65d4) ## Embedded administrator experience demo [Embedded content](https://player.vimeo.com/video/1094481320?badge=0\&autopause=0\&player_id=0\&app_id=58479) # Embed the I-9 experience in an iframe Source: https://docs.symmetry.com/i9/embedded-experiences/iframe-embed Configure the iframe attributes and feature policy permissions needed to embed the employee and administrator I-9 experiences. Both the employee and administrator I-9 experiences are delivered as embeddable URLs that you load in an ` ``` ### Attribute reference | Attribute | Required | Purpose | | :- | :- | :- | | `:src` | Yes | Vue shorthand for `v-bind:src`. Binds `src` to the value set within, which is the `embeddedUri` returned from the employee access token or administrator access token endpoint. | | `allow` | Yes | Enables the browser feature policies the embedded experience needs. `camera` is required for in-browser document scanning during Section 1. `geolocation` should also be allowed to cover all supported document capture flows. | | `sandbox` | Yes | Applies a security sandbox that restricts everything by default, then re-enables specific capabilities via tokens. See additional details below. | | `width`/`height` | Recommended | The embedded experience is responsive; a full-width container at least `1200px` tall avoids internal scrollbars on most viewports. | | `frameBorder` | Optional | Visual only. | | `title` | Recommended | Improves accessibility for screen readers. | #### Sandbox tokens The `sandbox` attribute starts fully locked down and only re-enables what's listed: | Token | Effect | | :- | :- | | `allow-scripts` | Lets the embedded content run JavaScript. | | `allow-same-origin` | Allows the iframe to be treated as same-origin, which is necessary for `sessionStorage` access and cookie-based session auth. | | `allow-popups` | Allows the embedded app to open new windows/tabs (for example, document downloads or external links). | | `allow-forms` | Allows form submission. | | `allow-storage-access-by-user-activation` | Needed in browsers (Safari, Firefox) that partition third-party cookies, so the embedded session cookie can be accessed. | ## Why the camera permission matters During Section 1, the embedded experience presents a scan or upload document dialog so the employee can capture identity and work authorization documents directly from their device. If the parent `