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

# Retrieve a stored calculation

> Returns the calculation **exactly as it was answered**, including the rules that produced it (`record.rule_fingerprint`). Nothing is recomputed: payroll rules change, and a past payslip must not.

Add `?include=audit_trail` for the step-by-step trace. The trace is always stored, whatever `options.include_audit_trail` asked to be shown when the calculation ran.



## OpenAPI

````yaml /openapi.json get /v1/payroll/calculations/{calculation_id}
openapi: 3.1.0
info:
  title: Payroll API
  description: >

    ## Payroll Infrastructure API for Latin America


    **Stripe for payroll** — embedded payroll calculation infrastructure.


    ### Overview


    This API performs payroll calculations for Mexico, Colombia, Brazil,
    Argentina,

    and Chile. It is a **pure computation engine**: give it employee data, get
    back

    a fully itemized payroll breakdown.


    ### Key concepts


    - **Scheme** — A country-specific payroll ruleset (e.g., Mexico `ordinario`,
    Colombia `integral`).
      Use `GET /v1/payroll/schemes/{country}` to discover available schemes.
    - **Calculation** — A single employee payroll run for one period.

    - **Audit trail** — A step-by-step trace of every formula evaluated.
    Required for
      legal compliance in most Latin American countries.

    ### Decimal precision


    All monetary amounts are returned as **JSON strings** (not numbers) to
    prevent

    floating-point precision loss in client languages. Parse them with your
    language's

    `Decimal` type before doing any arithmetic.


    ```

    ✅ correct:  {"net_salary": "20039.25"}

    ❌ wrong:    {"net_salary": 20039.25}  // could lose precision

    ```


    ### Authentication


    All endpoints require a Bearer API key:

    ```

    Authorization: Bearer your_api_key_here

    ```


    ### Error format


    All errors follow a consistent structure:

    ```json

    {
      "error": {
        "code": "SCHEME_NOT_FOUND",
        "message": "Human-readable description",
        "details": {},
        "request_id": "abc123"
      }
    }

    ```


    Use the `code` field (not the HTTP status) for programmatic error handling.

    The `request_id` links to server logs — include it when contacting support.


    ### Payouts (mock provider)


    The `/v1/payouts` surface lets you pay an employee their `net_salary` after
    a

    calculation. In v1 every payout is handled by an **in-process mock
    provider** —

    no real funds are moved. Every response is marked with `mock: true` in the
    body

    and `X-Clevis-Mock: true` as a response header.


    - Magic `external_id` prefixes (`MOCK_REJECT_INTAKE_`, `MOCK_REJECT_BANK_`,
      `MOCK_SLOW_`, `MOCK_STUCK_`, `MOCK_OK_`) trigger deterministic outcomes for
      demos and tests.
    - `processing.step_seconds: 0` makes the payout transition to its terminal
      status synchronously before the response is returned.
    - Idempotency is supported via the `Idempotency-Key` header or via the
      `external_id` field (per API key).

    See `docs/specs/04_payout_mock_endpoint.md` for the full contract. The real

    dLocal integration will be a config flip behind the same interface; this

    client-facing contract does not change.
  contact:
    name: Payroll API Support
    email: api@payroll.io
  license:
    name: Proprietary
  version: 1.0.0
servers: []
security: []
tags:
  - name: Payroll
    description: Payroll calculation endpoints. All monetary values are JSON strings.
  - name: Payouts
    description: >-
      Single-beneficiary payout endpoints backed by an in-process **mock**
      provider in v1 — no real funds are moved. Every response carries `mock:
      true` and the `X-Clevis-Mock: true` header. Magic trigger values (e.g.
      `external_id` prefixed with `MOCK_REJECT_BANK_`) force deterministic
      outcomes for demos and tests.
  - name: Schemes & Health
    description: Discover available payroll schemes and check service health.
  - name: Health
    description: Service health and readiness checks.
paths:
  /v1/payroll/calculations/{calculation_id}:
    get:
      tags:
        - Calculations
      summary: Retrieve a stored calculation
      description: >-
        Returns the calculation **exactly as it was answered**, including the
        rules that produced it (`record.rule_fingerprint`). Nothing is
        recomputed: payroll rules change, and a past payslip must not.


        Add `?include=audit_trail` for the step-by-step trace. The trace is
        always stored, whatever `options.include_audit_trail` asked to be shown
        when the calculation ran.
      operationId: Calculations_get_calculation
      parameters:
        - name: calculation_id
          in: path
          required: true
          schema:
            type: string
            description: Calculation id (ULID).
            title: Calculation Id
          description: Calculation id (ULID).
        - name: include
          in: query
          required: false
          schema:
            anyOf:
              - type: string
              - type: 'null'
            description: Set to `audit_trail` to include the step-by-step trace.
            title: Include
          description: Set to `audit_trail` to include the step-by-step trace.
      responses:
        '200':
          description: The stored calculation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CalculateResponse'
        '401':
          description: Missing, invalid, revoked or wrong-environment API key.
        '404':
          description: No such calculation for this client.
        '422':
          description: Validation Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HTTPValidationError'
      security:
        - ApiKeyBearer: []
components:
  schemas:
    CalculateResponse:
      properties:
        id:
          type: string
          title: Id
          description: Globally unique calculation ID (ULID). Stable and sortable by time.
          examples:
            - 01HX9B2KM3V4W5X6Y7Z8A9B0CD
        status:
          type: string
          const: success
          title: Status
          default: success
        country:
          type: string
          title: Country
        scheme:
          type: string
          title: Scheme
        year:
          type: integer
          title: Year
        period:
          $ref: '#/components/schemas/Period'
        employee_id:
          type: string
          title: Employee Id
          description: Employee ID echoed from the request.
        summary:
          $ref: '#/components/schemas/PayrollSummary'
        perceptions:
          items:
            $ref: '#/components/schemas/PerceptionResponse'
          type: array
          title: Perceptions
        deductions:
          items:
            $ref: '#/components/schemas/DeductionResponse'
          type: array
          title: Deductions
        taxable_bases:
          items:
            $ref: '#/components/schemas/TaxableBaseResponse'
          type: array
          title: Taxable Bases
        employer_contributions:
          items:
            $ref: '#/components/schemas/EmployerContributionResponse'
          type: array
          title: Employer Contributions
        dsl_version:
          type: string
          title: Dsl Version
          description: Version string of the DSL rule set used for this calculation.
          examples:
            - '2024.2'
        computed_at:
          type: string
          format: date-time
          title: Computed At
          description: UTC timestamp when this calculation was performed.
        audit_trail:
          anyOf:
            - items:
                additionalProperties: true
                type: object
              type: array
            - type: 'null'
          title: Audit Trail
          description: >-
            Step-by-step calculation trace. Each step shows the formula,
            resolved inputs, and result. Null when include_audit_trail=false.
        period_basis:
          anyOf:
            - $ref: '#/components/schemas/PeriodBasis'
            - type: 'null'
          description: >-
            Which slice of a liquidated month these figures are, and what the
            whole month came to. Present on every calculation.
        record:
          anyOf:
            - $ref: '#/components/schemas/StoredRecord'
            - type: 'null'
          description: >-
            Storage and provenance of this calculation: what rules produced it,
            which engine build ran, and how to verify later that it has not
            changed.
        warnings:
          items:
            $ref: '#/components/schemas/WarningDetail'
          type: array
          title: Warnings
          description: >-
            Non-fatal diagnostics about this calculation. Every amount above
            already reflects the request as sent; a warning flags an input that
            contradicts the salary the engine used, so the caller can check it.
            Empty when the request is coherent.
      type: object
      required:
        - id
        - country
        - scheme
        - year
        - period
        - employee_id
        - summary
        - perceptions
        - deductions
        - taxable_bases
        - employer_contributions
        - dsl_version
        - computed_at
      title: CalculateResponse
      description: |-
        Full single-employee payroll calculation result.

        All monetary values are JSON strings. Parse with your language's
        Decimal library before doing any arithmetic.
    HTTPValidationError:
      properties:
        detail:
          items:
            $ref: '#/components/schemas/ValidationError'
          type: array
          title: Detail
      type: object
      title: HTTPValidationError
    Period:
      properties:
        type:
          type: string
          enum:
            - monthly
            - biweekly
            - weekly
          title: Type
          description: >-
            Period frequency. Determines default days if not provided. Accepting
            a value here is not a promise that every scheme liquidates it: a
            scheme only honours the frequencies listed in its
            `supported_period_types`, and anything else is rejected with
            PERIOD_TYPE_NOT_SUPPORTED. Today only Mexico prorates by
            `period.days`; the other countries are monthly-only.
          examples:
            - monthly
        start_date:
          type: string
          format: date
          title: Start Date
          description: First calendar day of the payroll period (inclusive).
          examples:
            - '2024-03-01'
        end_date:
          type: string
          format: date
          title: End Date
          description: Last calendar day of the payroll period (inclusive).
          examples:
            - '2024-03-31'
        days:
          type: integer
          maximum: 31
          minimum: 1
          title: Days
          description: >-
            Number of days in the payroll period used for salary calculations.
            For a full calendar month this is typically 30 regardless of the
            actual month length (IMSS convention in Mexico).
          examples:
            - 30
      type: object
      required:
        - type
        - start_date
        - end_date
        - days
      title: Period
      description: Payroll period definition.
    PayrollSummary:
      properties:
        gross_salary:
          type: string
          title: Gross Salary
          description: Total perceptions (percepciones totales). String in JSON.
        total_perceptions:
          type: string
          title: Total Perceptions
        total_deductions:
          type: string
          title: Total Deductions
        net_salary:
          type: string
          title: Net Salary
          description: Employee take-home pay after all deductions. String in JSON.
        employer_contributions_total:
          type: string
          title: Employer Contributions Total
          description: Sum of all employer-side contributions (IMSS, Infonavit, etc.).
        employer_total_cost:
          type: string
          title: Employer Total Cost
          description: 'Total cost to employer: gross salary + employer contributions.'
      type: object
      required:
        - gross_salary
        - total_perceptions
        - total_deductions
        - net_salary
        - employer_contributions_total
        - employer_total_cost
      title: PayrollSummary
      description: High-level financial summary of the payroll calculation.
    PerceptionResponse:
      properties:
        id:
          type: string
          title: Id
          description: DSL concept ID.
        label:
          type: string
          title: Label
          description: Human-readable label (Spanish).
        amount:
          type: string
          title: Amount
          description: Amount as decimal string in response JSON.
        taxable:
          type: boolean
          title: Taxable
          description: Whether this perception is included in the ISR base.
        imss_base:
          type: boolean
          title: Imss Base
          description: Whether this perception is included in the IMSS cotization base.
        tags:
          items:
            type: string
          type: array
          title: Tags
      type: object
      required:
        - id
        - label
        - amount
        - taxable
        - imss_base
      title: PerceptionResponse
      description: One perception (earning) line in the payroll result.
    DeductionResponse:
      properties:
        id:
          type: string
          title: Id
        label:
          type: string
          title: Label
        amount:
          type: string
          title: Amount
        tags:
          items:
            type: string
          type: array
          title: Tags
        bracket_applied:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Bracket Applied
          description: Bracket tier detail if this deduction used a progressive table.
      type: object
      required:
        - id
        - label
        - amount
      title: DeductionResponse
      description: One deduction line in the payroll result.
    TaxableBaseResponse:
      properties:
        id:
          type: string
          title: Id
        label:
          type: string
          title: Label
        amount:
          type: string
          title: Amount
        formula:
          type: string
          title: Formula
          description: The DSL formula that computed this base.
      type: object
      required:
        - id
        - label
        - amount
        - formula
      title: TaxableBaseResponse
      description: One computed taxable base (base gravable) used in the calculation.
    EmployerContributionResponse:
      properties:
        table_id:
          type: string
          title: Table Id
        label:
          type: string
          title: Label
        total:
          type: string
          title: Total
          description: Sum of all component amounts (string).
        components:
          items:
            $ref: '#/components/schemas/ContributionComponentResponse'
          type: array
          title: Components
      type: object
      required:
        - table_id
        - label
        - total
        - components
      title: EmployerContributionResponse
      description: One employer contribution table result (e.g., IMSS patrón, Infonavit).
    PeriodBasis:
      properties:
        type:
          type: string
          enum:
            - monthly
            - biweekly
            - weekly
          title: Type
          description: The period frequency these figures were liquidated for.
          examples:
            - biweekly
        sequence:
          type: integer
          title: Sequence
          description: >-
            Which sub-period of the month this is, 1-based. Derived from
            period.start_date: day 1-15 is the first, 16 onward the second.
          examples:
            - 1
        periods_in_month:
          type: integer
          title: Periods In Month
          description: >-
            How many sub-periods make up the month. 1 for monthly, 2 for
            biweekly.
          examples:
            - 2
        factor:
          type: string
          pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
          title: Factor
          description: >-
            This period's nominal share of the month. Reported for clarity; the
            amounts are not a plain multiplication by it — see `residual`.
          examples:
            - '0.5'
        proration:
          anyOf:
            - type: string
              enum:
                - native
                - split_monthly
            - type: 'null'
          title: Proration
          description: >-
            How the scheme honours a sub-monthly period. 'native' means its
            formulas prorate from period.days (Mexico). 'split_monthly' means
            the month was liquidated and the result split (Colombia), because
            its brackets, floors and ceilings are all defined monthly by law.
            Null when the scheme is monthly-only.
        absorbs_residual:
          type: boolean
          title: Absorbs Residual
          description: >-
            True on the period that carries the rounding remainder. Every period
            but the last gets the rounded share and the last gets what is left,
            so the sub-periods sum to the month exactly rather than drifting by
            a peso a line.
          examples:
            - false
        monthly_equivalent:
          $ref: '#/components/schemas/MonthlyEquivalent'
      type: object
      required:
        - type
        - sequence
        - periods_in_month
        - factor
        - absorbs_residual
        - monthly_equivalent
      title: PeriodBasis
      description: >-
        Which slice of a liquidated month these figures represent (spec 16).


        Always present, whatever the periodicity: a monthly calculation reports

        `sequence: 1`, `periods_in_month: 1`, `factor: "1"` and a

        `monthly_equivalent` equal to its own summary, so a client reads the
        same

        fields either way instead of branching on the period type.
    StoredRecord:
      properties:
        stored:
          type: boolean
          title: Stored
          description: >-
            Whether this calculation was recorded. Always true: a calculation
            that could not be stored is not returned at all — the request fails
            with 503 PERSISTENCE_UNAVAILABLE rather than handing back an id that
            nothing can fetch.
          default: true
        rule_fingerprint:
          type: string
          title: Rule Fingerprint
          description: >-
            SHA-256 of the rule file that produced these amounts. This, and not
            `dsl_version`, is the identity of the rules: several different rule
            sets have shipped under the same version label.
          examples:
            - sha256:b90834cebdc4224c3...
        engine_version:
          type: string
          title: Engine Version
          description: Build of the calculation engine that ran, as a git SHA.
        schema_version:
          type: integer
          title: Schema Version
          description: >-
            Shape of this stored response. An older record is returned in the
            shape it was written in, never upgraded in place.
        content_digest:
          type: string
          title: Content Digest
          description: >-
            SHA-256 over the canonical form of this response. Keep it and you
            can prove later that what we return is what we returned then.
        batch_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Batch Id
          description: Batch this calculation was part of, if any.
        supersedes_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Supersedes Id
          description: Calculation this one replaces, when it is a recalculation.
        metadata:
          additionalProperties:
            type: string
          type: object
          title: Metadata
          description: Your own labels, echoed back.
      type: object
      required:
        - rule_fingerprint
        - engine_version
        - schema_version
        - content_digest
      title: StoredRecord
      description: |-
        Where this calculation lives and what produced it (spec 23).

        Present on every calculation, both when it is created and when it is
        fetched later, so the two bodies are the same document.
    WarningDetail:
      properties:
        code:
          type: string
          title: Code
          description: >-
            Stable warning code. Use this for programmatic handling, not the
            message text. Current codes: FLAG_THRESHOLD_MISMATCH.
          examples:
            - FLAG_THRESHOLD_MISMATCH
        field:
          type: string
          title: Field
          description: Dotted path of the request field the warning is about.
          examples:
            - overrides.aplica_auxilio_transporte
        message:
          type: string
          title: Message
          description: >-
            Human-readable explanation, quoting the values the engine compared
            and the legal basis for the threshold.
        severity:
          type: string
          const: warning
          title: Severity
          description: >-
            Severity of the diagnostic. v1 only emits 'warning'; the field
            exists so richer severities do not break the contract later.
          default: warning
      type: object
      required:
        - code
        - field
        - message
      title: WarningDetail
      description: >-
        A non-fatal diagnostic about the request. Never changes an amount.


        Emitted when an input contradicts something the engine can see for
        itself —

        today, a boolean flag that disagrees with the salary the benefit is
        gated

        on. The calculation still honours the flag: the legal call belongs to
        the

        integrator, who may hold information this API never receives.
    ValidationError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Location
        msg:
          type: string
          title: Message
        type:
          type: string
          title: Error Type
        input:
          title: Input
        ctx:
          type: object
          title: Context
      type: object
      required:
        - loc
        - msg
        - type
      title: ValidationError
    ContributionComponentResponse:
      properties:
        id:
          type: string
          title: Id
        label:
          type: string
          title: Label
        base:
          type: string
          title: Base
          description: Base amount (string) the rate was applied to.
        rate:
          type: string
          title: Rate
          description: Rate applied (string).
        amount:
          type: string
          title: Amount
          description: Resulting contribution amount (string).
      type: object
      required:
        - id
        - label
        - base
        - rate
        - amount
      title: ContributionComponentResponse
      description: One rate component within an employer contribution table.
    MonthlyEquivalent:
      properties:
        total_perceptions:
          type: string
          title: Total Perceptions
        total_deductions:
          type: string
          title: Total Deductions
        net_salary:
          type: string
          title: Net Salary
        employer_contributions_total:
          type: string
          title: Employer Contributions Total
        employer_total_cost:
          type: string
          title: Employer Total Cost
      type: object
      required:
        - total_perceptions
        - total_deductions
        - net_salary
        - employer_contributions_total
        - employer_total_cost
      title: MonthlyEquivalent
      description: >-
        What the whole month came to, when the figures above are one slice of
        it.


        Colombia files PILA and declares withholding by month, so a caller
        paying

        fortnightly needs the monthly figure to reconcile against either.
        Repeating

        it here means they never have to recompute it — or worse, add up two

        fortnights and hope the rounding agreed.
  securitySchemes:
    ApiKeyBearer:
      type: http
      description: >-
        API key authentication. Send your API key as: Authorization: Bearer
        <your_api_key>
      scheme: bearer

````