> ## Documentation Index
> Fetch the complete documentation index at: https://docs-test.symmetry.com/llms.txt
> Use this file to discover all available pages before exploring further.

# C SDK quickstart

> Link the native STE library and calculate withholding for one employee with the C API.

The **C API** is the native foundation that every other SDK is built on. It's a shared library (`libste.so` / `libste.dylib` / `ste.dll`) with a header, `ste/src/ste.h`, that is the authoritative source for signatures. This quickstart runs a federal + California state calculation for one employee using the modern **STE2-style** configuration.

<Note>
  STE2-style configures every tax through `ste_set_jurisdiction_data(...)` + `ste_set_jurisdiction_misc_parms(...)` using a `uniqueTaxID`. Prefer it over the legacy per-tax setters (`ste_set_federal`, `ste_set_state`, …).
</Note>

## Prerequisites

<Steps>
  <Step title="Get the library, header, and tax database">
    You need `ste.h`, the native library for your platform, and an **STE home directory** containing the tax database. These come with your STE license.
  </Step>

  <Step title="Link against the library">
    Linking differs per platform (rpath on macOS, `ldconfig`/`LD_LIBRARY_PATH` on Linux, import lib on Windows). See [Linking the native library](/ste/operations/linking-the-native-library).
  </Step>
</Steps>

## Calculate

```c theme={null}
#include "ste.h"
#include <stdio.h>

int main(void)
{
    /* 1. Initialize the engine against your STE home directory. */
    ste_handle *ste = ste_init("/opt/symmetry/ste");
    if (!ste) {
        fprintf(stderr, "STE init failed\n");
        return 1;
    }

    const char *federalLoc = "00-000-0000";
    const char *stateLoc   = "06-000-0000";             /* California */
    const char *fitTaxId   = "00-000-0000-FIT-000";     /* Federal income tax */
    const char *sitTaxId   = "06-000-0000-SIT-000";     /* California SIT */

    /* 2. Start clean for this employee. */
    ste_clear_calculations(ste);
    ste_clear_settings(ste);

    /* 3. Describe the pay run: biweekly, 12th period of the year. */
    ste_set_payroll_run_parameters(ste, "2026-06-15", 26, 12);

    /* 4. Wages: $4,000 gross, 80 hours, at both locations.
     *    Wage type 1 = Regular; calc method: Annualized regular, None supplemental. */
    ste_set_calcmethod(ste, federalLoc, ste_CALC_Method_Annualized, ste_CALC_Method_None);
    ste_set_calcmethod(ste, stateLoc,   ste_CALC_Method_Annualized, ste_CALC_Method_None);
    ste_set_wages(ste, federalLoc, ste_WAGE_Regular, 80.0, 4000.0, 0.0, 0.0, 0.0);
    ste_set_wages(ste, stateLoc,   ste_WAGE_Regular, 80.0, 4000.0, 0.0, 0.0, 0.0);

    /* 5. Federal income tax (STE2). roundResult 2 = default. */
    ste_set_jurisdiction_data(ste, fitTaxId, federalLoc,
        false, true, 0.0, 0.0, 0.0, 0.0, 0.0, 2, false, false, 0.0, 0.0, 0.0, 0.0);
    ste_set_jurisdiction_misc_parms(ste, fitTaxId, "FILINGSTATUS", "S");
    ste_set_jurisdiction_misc_parms(ste, fitTaxId, "TOTALALLOWANCES", "0");

    /* 6. California SIT (STE2). */
    ste_set_jurisdiction_data(ste, sitTaxId, stateLoc,
        false, true, 0.0, 0.0, 0.0, 0.0, 0.0, 2, false, false, 0.0, 0.0, 0.0, 0.0);
    ste_set_jurisdiction_misc_parms(ste, sitTaxId, "FILINGSTATUS", "S");
    ste_set_jurisdiction_misc_parms(ste, sitTaxId, "TOTALALLOWANCES", "0");

    /* 7. Calculate. */
    if (ste_calculate(ste)) {
        uint16_t code = ste_get_errno_ext(ste);
        fprintf(stderr, "calculate failed: %s\n", ste_get_strerror(code));
        ste_quit(ste);
        return 1;
    }

    /* 8. Read the withholding per tax. */
    char loc[128], taxId[128], desc[128];
    int isResident, payType, isUnemp;
    double tax, gross, subject, grossSubject, rate, wageBase;
    double subCTD, excCTD, subQTD, excQTD, subYTD, excYTD;

    if (ste_get_jurisdiction_calculation(ste, fitTaxId, ste_WAGE_Regular,
            loc, taxId, &isResident, &payType, &isUnemp, desc,
            &tax, &gross, &subject, &grossSubject, &rate, &wageBase,
            &subCTD, &excCTD, &subQTD, &excQTD, &subYTD, &excYTD)) {
        printf("Federal income tax: %.2f\n", tax);
    }
    if (ste_get_jurisdiction_calculation(ste, sitTaxId, ste_WAGE_Regular,
            loc, taxId, &isResident, &payType, &isUnemp, desc,
            &tax, &gross, &subject, &grossSubject, &rate, &wageBase,
            &subCTD, &excCTD, &subQTD, &excQTD, &subYTD, &excYTD)) {
        printf("California SIT:     %.2f\n", tax);
    }

    /* 9. Release the handle. */
    ste_quit(ste);
    return 0;
}
```

<Warning>
  `ste.h` is the authoritative signature reference. The exact out-parameter list of retrieval functions can vary by version — check your header. Functions that return heap-allocated strings (`ste_json`, `ste_xml`, `ste_get_schema`) must be freed with `ste_free_ptr()`.
</Warning>

## What each step does

| Step         | Call                                                        | Purpose                                                |
| ------------ | ----------------------------------------------------------- | ------------------------------------------------------ |
| Init         | `ste_init(steHome)`                                         | Opens an engine handle against the tax database.       |
| Reset        | `ste_clear_calculations`, `ste_clear_settings`              | Clears prior state so the handle is reusable.          |
| Pay run      | `ste_set_payroll_run_parameters(...)`                       | Pay date, periods per year, and current period.        |
| Wages        | `ste_set_calcmethod`, `ste_set_wages`                       | Method and gross/hours by location.                    |
| Jurisdiction | `ste_set_jurisdiction_data(uniqueTaxID, …)`                 | Configures one tax; residency, rounding, overrides.    |
| Elections    | `ste_set_jurisdiction_misc_parms(uniqueTaxID, name, value)` | Filing status, allowances, and other W-4-style inputs. |
| Calculate    | `ste_calculate`                                             | Runs the employee pass; returns `0` on success.        |
| Read         | `ste_get_jurisdiction_calculation(...)`                     | The amount to withhold for that tax.                   |

<Tip>
  Most functions return `uint16_t` where `0` means success. On a non-zero return, read the code with `ste_get_errno_ext(ste)` and the message with `ste_get_strerror(code)`.
</Tip>

## Handles, threads, and pooling

`ste_handle*` is opaque and **not thread-safe** — one handle per thread. For high volume, use the pool API (`ste_pool_init` / `ste_pool_checkout` / `ste_pool_checkin` / `ste_pool_quit`) to pay initialization cost once. See [Handles & pooling](/ste/operations/handles-and-pooling).

## Prefer JSON on-premise?

You don't have to use the C setters directly. The same native library exposes `ste_json()`, which accepts the exact `PayCalcRequest` payload from the [Hosted API quickstart](/ste/quickstarts/hosted-api-quickstart) — letting you keep one payload format across hosted and on-premise deployments.

## Next steps

<Columns cols={2}>
  <Card title="Full calculation walkthrough" href="/ste/calculation-walkthroughs/c-sdk" icon="list-check">
    Install the interface and run a complete, realistic pay calc end to end.
  </Card>

  <Card title="Configuring a calculation" href="/ste/configuration/setting-jurisdictions" icon="sliders">
    Wages, jurisdictions, benefits, and engine options in depth.
  </Card>

  <Card title="Linking the native library" href="/ste/operations/linking-the-native-library" icon="link">
    Per-platform linking and runtime load paths.
  </Card>
</Columns>
