> This page is for Direct Executions.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://infonite.dev/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://infonite.dev/_mcp/server.

# Labor Check

**Where it lives:** in the Spain Public Administration results, at `data.employment.labor_check`. APIs with dedicated per-product results endpoints return this model directly.

The labor check answers three questions about a person: **who they have worked for and when**,
**what they have contributed month by month**, and **what that means today** — whether they are
currently working, their current work statuses, and a guaranteed minimum net income floor. Use it to
verify employment, gauge income stability and assess risk.

It arrives in the session results under `data`, and the official TGSS reports the data was read from travel as [attachments](/guides/data-models/attachments) when you ask for them, downloadable for your own records.

### Schema (`TGSSSpainLaborCheckSchema`)

The person's labor life with the Spanish Social Security (TGSS). It answers three questions:
who they have worked for and when (`work_relations_history`), what they have contributed
month by month per employer account (`contribution_base_by_company`), and what that means
today — a guaranteed minimum NET income floor (`income_floor`, a lower bound derived from
the contribution bases, never a salary estimate) and the person's current work statuses
(`current_work_types`). Use it to verify employment, gauge income stability and assess risk;
the source reports the data was read from travel in `attachments`, and the holder they name in
`holder_name` and `identifier`.

```yaml
components:
  schemas:
    IdentificationNumberSchemaType:
      type: string
      enum:
        - unknown
        - es:dni
        - es:nie
        - es:cif
        - es:ssn
        - co:cc
        - co:ce
        - co:nit
        - co:ti
      description: >-
        Kind of document the number belongs to (e.g. a national ID, passport,
        tax ID, or Social

        Security number).
      title: IdentificationNumberSchemaType
    IdentificationNumberSchema:
      type: object
      properties:
        type:
          $ref: '#/components/schemas/IdentificationNumberSchemaType'
          description: >-
            Kind of document the number belongs to (e.g. a national ID,
            passport, tax ID, or Social

            Security number).
        value:
          type: string
          description: The number itself, as reported by the source.
        validated:
          type: boolean
          description: >-
            True when the value passed the platform's format and check-digit
            validation. It vouches for

            the NUMBER being well-formed — not for the official status of the
            document behind it.
        country:
          type:
            - string
            - 'null'
          format: country
          description: Country that issued the number, as a two-letter ISO code.
        valid_until:
          type: string
          format: date
          description: Expiry date of the document, when the source reports it.
      required:
        - type
        - value
        - validated
      description: >-
        One identification document: its type, its value, and whether the value
        passed validation.
      title: IdentificationNumberSchema
    WorkType:
      type: string
      enum:
        - unknown
        - employee
        - self_employed
        - public_employee
        - vacations
        - unemployment_benefits
        - other
      title: WorkType
    WorkContractType:
      type: string
      enum:
        - unknown
        - permanent
        - temporary
        - training
        - professional_practices
        - fixed_discontinuous
      title: WorkContractType
    WorkScheduleType:
      type: string
      enum:
        - unknown
        - full_time
        - part_time
      title: WorkScheduleType
    WorkRelationSchema:
      type: object
      properties:
        activity_start:
          type: string
          format: date
          description: >-
            Activity start date — the date the TGSS counts contributed days
            from.
        activity_end:
          type: string
          format: date
          description: Activity end date. Empty while the relation is ongoing.
        name:
          type: string
          description: >-
            Display name of the relation: the employer's name for employees, the
            regime for

            self-employment, and the situation description for benefit periods.
        regime:
          type: string
          description: Social Security regime of this relation.
        ccc:
          type: string
          description: >-
            Employer contribution account code (CCC) — the join key to
            `contribution_base_by_company`.

            Absent for self-employment, which has no employer account.
        assimilated:
          type: boolean
          default: false
          description: >-
            True for situations assimilated to registration (benefit periods,
            paid untaken

            vacations...) — periods that count for Social Security but are not
            an actual job. Skip

            them when reasoning about employment or earned income.
        work_type:
          $ref: '#/components/schemas/WorkType'
          description: >-
            Work type of this relation (e.g. `employee`, `self_employed`,
            `unemployment_benefits`).
        contract_type:
          $ref: '#/components/schemas/WorkContractType'
          description: >-
            Contract type as mapped from the TGSS classification; `unknown` when
            the source key has

            no mapping.
        work_schedule:
          $ref: '#/components/schemas/WorkScheduleType'
          description: 'Work schedule: `full_time`, `part_time`, or `unknown`.'
        contribution_group:
          type: string
          description: Contribution group of the worker in this relation.
        collective_agreement:
          type: string
          description: Collective agreement governing this relation, when declared.
        social_security_days:
          type: integer
          description: >-
            Days this relation counts for Social Security. Simultaneous
            relations each count their

            own days, so summing across relations overstates — the deduplicated
            career total is the

            top-level `social_security_days`.
        currently_active:
          type: boolean
          description: True while this relation is ongoing (it has no end date yet).
      required:
        - activity_start
        - name
        - work_type
        - contract_type
        - work_schedule
      description: >-
        One period of the person's labor life: an employment, a self-employment
        stretch, or a

        situation that counts for Social Security without being a job.
      title: WorkRelationSchema
    ContributionMonthStatus:
      type: string
      enum:
        - registered
        - no_alta
        - no_base_registered
        - pending_update
        - not_yet_elapsed
        - not_yet_settled
      description: >-
        State of one month in a social-security contribution-base history.


        The first five values are what the TGSS report prints.
        ``not_yet_settled``

        is the refined reading of a printed ``no_alta`` that falls inside a

        certified open relation near the report's emission date: contribution
        bases

        register with a settlement lag, so those months mean "not settled yet",

        never "not registered" — they must not count as gaps or zeros.
      title: ContributionMonthStatus
    CurrencyAmountSchemaCurrency:
      oneOf:
        - type: string
          format: currency
        - type: string
          enum:
            - '***'
      description: >-
        Three-letter ISO currency code — or `***` when the source did not
        disclose the currency.
      title: CurrencyAmountSchemaCurrency
    CurrencyAmountSchema:
      type: object
      properties:
        currency:
          $ref: '#/components/schemas/CurrencyAmountSchemaCurrency'
          description: >-
            Three-letter ISO currency code — or `***` when the source did not
            disclose the currency.
        amount:
          type: string
          format: number
          description: Decimal number with 2 digits precision
      required:
        - currency
        - amount
      description: A monetary amount together with its currency.
      title: CurrencyAmountSchema
    MonthlyBaseSchema:
      type: object
      properties:
        date:
          type: string
          format: date
          description: >-
            Last day of the contribution month — a convenience key for
            date-indexed consumers; `year`

            and `month` carry the same information.
        year:
          type: integer
          description: Contribution year.
        month:
          type: integer
          description: Contribution month (1-12).
        status:
          $ref: '#/components/schemas/ContributionMonthStatus'
          description: >-
            State of the month: `registered` (base certified by the TGSS),
            `pending_update`

            (contribution reported, amount not published yet — an existing
            contribution, NOT a gap),

            `not_yet_settled` (recent month still inside the settlement lag),
            `no_base_registered`, or

            `no_alta` (not registered that month). A month absent from the list
            altogether means no

            contribution row existed for it.
        base:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            Monthly contribution base (gross). Carries a numeric amount only
            when the month is

            `registered`; in any other state the amount is not available —
            unavailable, not zero.
        provisional:
          type: boolean
          default: false
          description: >-
            True when the base is provisional and may still be regularized by
            the TGSS — typical for

            self-employed workers until the yearly settlement.
      required:
        - date
        - year
        - month
        - status
        - base
      description: >-
        One month of contribution: its state and, when registered, the gross
        base amount.
      title: MonthlyBaseSchema
    CompanyContributionsSchema:
      type: object
      properties:
        company_name:
          type: string
          description: Employer or regime name, as certified by the TGSS.
        ccc:
          type: string
          description: >-
            Employer contribution account code (CCC) — the join key linking this
            history to the

            matching entries in `work_relations_history`. Absent for
            self-employment, which has no

            employer account.
        regime:
          type: string
          description: Social Security regime of this account.
        is_benefit_block:
          type: boolean
          default: false
          description: >-
            True when this entry tracks a benefit (e.g. cessation-of-activity
            protection for the

            self-employed), not an actual employer. Its bases are NOT earned
            income — exclude them

            from any income computation.
        months:
          type: array
          items:
            $ref: '#/components/schemas/MonthlyBaseSchema'
          default: []
          description: Monthly contribution bases of this account, most recent first.
      description: >-
        The month-by-month contribution history of one employer account (or
        regime).
      title: CompanyContributionsSchema
    IncomeFloorStatus:
      type: string
      enum:
        - computed
        - not_currently_active
        - activity_unknown
        - insufficient_data
      description: Whether a guaranteed-minimum income floor could be asserted at all.
      title: IncomeFloorStatus
    IncomeFloorBasis:
      type: string
      enum:
        - window_minimum
      description: >-
        How a company entry's floor was derived.


        The per-company list only ever contains companies CONTRIBUTING to the

        computed floor (closed/stale employments are excluded entirely, so no
        past

        salary can be misread as a current one); the enum names the derivation
        and

        leaves room for future methods.
      title: IncomeFloorBasis
    CompanyIncomeFloorSchema:
      type: object
      properties:
        company_name:
          type: string
          description: Employer or regime this floor comes from.
        ccc:
          type: string
          description: Employer contribution account code (CCC) of this company.
        work_type:
          $ref: '#/components/schemas/WorkType'
          description: Work type behind this income.
        monthly_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            Estimated minimum NET monthly income from this company: its worst
            observed window

            month's net share, after worker Social Security contributions and
            IRPF withholding at

            that month's real income mix. Every unknown (contract type, age,
            family situation) is

            resolved toward more deductions, so real take-home pay can only be
            equal or higher.
        annual_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: Estimated minimum NET annual income from this company.
        gross_monthly_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            The certified GROSS monthly floor this company's net figure derives
            from — the minimum

            contribution base over the observation window.
        gross_annual_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            The certified GROSS annual floor from this company (the gross
            monthly floor x12).
        basis:
          $ref: '#/components/schemas/IncomeFloorBasis'
          description: >-
            How this floor was derived (e.g. `window_minimum`: the minimum base
            over the trailing

            window of fully certified months).
        observed_months:
          type: integer
          default: 0
          description: >-
            Number of certified months the floor is based on — the more months,
            the steadier the

            floor.
      required:
        - company_name
        - monthly_floor
        - annual_floor
        - basis
      description: >-
        One company's share of the income floor: the minimum net income it
        contributes.
      title: CompanyIncomeFloorSchema
    IncomeFloorSchema:
      type: object
      properties:
        status:
          $ref: '#/components/schemas/IncomeFloorStatus'
          description: >-
            Whether a floor could be asserted: `computed` (floor available),
            `not_currently_active`

            (no ongoing employment — e.g. between contracts, a scheduled future
            hire or an ongoing

            unemployment benefit; the current floor is zero),
            `insufficient_data` (working, but not

            enough certified months yet to measure a floor), or
            `activity_unknown` (no employment

            evidence either way).
        monthly_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            Estimated minimum NET monthly income: the worst observed window
            month after worker

            Social Security contributions and IRPF withholding. A lower bound
            for risk assessment —

            NOT a salary estimate: every unknown in the conversion (contract
            type, age, family

            situation) is resolved toward more deductions, so real take-home pay
            can only be equal

            or higher. For self-employed workers it deliberately understates
            real income; combine

            with other signals.
        annual_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: The net monthly floor, annualized.
        gross_monthly_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            Guaranteed minimum GROSS monthly income, certified by the
            contribution bases. The net

            floor is minimized over months separately, so it can come from a
            different (net-worse)

            month than this gross minimum.
        gross_annual_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: The gross monthly floor, annualized (x12).
        estimated_deduction_rate:
          type: string
          format: number
          default: nan
          description: Decimal number with 4 digits precision
        observed_months:
          type: integer
          default: 0
          description: >-
            Number of months the floor was measured over. A month only partly
            worked (a start after

            the 1st, an end before the month's last day) is left out once at
            least two full months

            exist, so its prorated pay never passes for a monthly income. Fewer
            than 3 means the

            floor rests on little evidence — typically a recent hire.
        companies:
          type: array
          items:
            $ref: '#/components/schemas/CompanyIncomeFloorSchema'
          default: []
          description: >-
            Only the companies contributing to the computed floor (ongoing,
            recent activity). Past

            employments are never listed here — their history is in
            `contribution_base_by_company` —

            so nothing in this list can be misread as a salary the person no
            longer earns.
        method_version:
          type: string
          description: >-
            Version of the floor derivation method. Bumped whenever the
            algorithm changes meaning —

            compare floors only within the same version.
      required:
        - status
      description: >-
        A guaranteed minimum NET income derived from the contribution bases — a
        floor for

        risk assessment, never a salary estimate. The certified gross lower
        bound travels

        alongside in the `gross_*` fields.
      title: IncomeFloorSchema
    ProductAttachmentType:
      type: string
      enum:
        - attachment:attachment
        - attachment:supplier_invoice
        - attachment:client_invoice
        - attachment:es-tgss-life-report
        - attachment:es-tgss-contribution-base-report
        - attachment:es-aeat-model-100
        - attachment:es-cirbe-report
        - attachment:sepa-direct-debit-bill
        - attachment:person-certified-photo
      description: Product Attachment Type
      title: ProductAttachmentType
    FileAttachmentSchema:
      type: object
      properties:
        product:
          type: string
          enum:
            - attachment
          default: attachment
          description: The product type identifier. Always `attachment`.
        sub_family:
          $ref: '#/components/schemas/ProductAttachmentType'
          description: >-
            What kind of document this is (e.g.
            `attachment:es-tgss-life-report`).
        id:
          type: string
          format: object-id
          description: >-
            Attachment identifier — what the attachments endpoint of the API
            that returned the result

            takes to download the file.
        content_name:
          type: string
          description: File name of the document.
        content_hash:
          type: string
          description: Fingerprint of the content, to verify its integrity.
        content_type:
          type: string
          format: mime-type
          description: MIME type of the content.
        metadata:
          type: object
          additionalProperties:
            description: Any type
          description: >-
            Extra facts about the document, as simple key-value pairs (e.g. its
            official verification

            code, its issue date).
      required:
        - sub_family
        - id
        - content_name
        - content_type
        - metadata
      description: >-
        A document attached to a result — an official report, a receipt, an
        invoice... The entry

        describes the file; its bytes are downloaded with `id`, through the
        attachments endpoint of the

        API that returned the result.
      title: FileAttachmentSchema
    TGSSSpainLaborCheckSchema:
      type: object
      properties:
        product:
          type: string
          enum:
            - social_security
          description: >-
            The product type identifier. Always `social_security` for this
            product.
        sub_family:
          type: string
          enum:
            - social_security:spain_labor_check
          description: >-
            The sub-family identifier: `social_security:spain_labor_check`, the
            Spanish Social Security (TGSS) labor life

            check.
        fetch_date:
          type: string
          format: datetime
          description: Date this product was fetched.
        holder_name:
          type: string
          description: >-
            The holder's full name, as printed on the official Social Security
            reports (the PDFs).

            ⚠️ **When it is not reported, review this product carefully before
            you rely on it**: the two

            reports print different names for the same holder, or no report
            could be used.
        identifier:
          $ref: '#/components/schemas/IdentificationNumberSchema'
          description: >-
            The holder's identity document (DNI or NIE), as printed on the
            official reports; when both are

            read, they must agree on it. Not reported when no report could be
            used (not available, not

            readable, or disagreeing on the identity numbers). When the labor
            check is retrieved by

            connecting to the Social Security, both reports are read whether or
            not you ask for them as

            attachments, and without a usable one the rest of the data may come
            from its web pages instead.
        currently_active:
          type: boolean
          description: >-
            True when the person is actually WORKING right now: at least one
            entry in

            `current_work_types` is real work (`employee`, `self_employed` or
            `public_employee`).

            Receiving an unemployment benefit is not active employment. Neither
            is a hire scheduled

            for a future date: Social Security reports such a person as
            registered ("alta

            programada"), but this field stays `false` until the job actually
            starts. `false` means

            the person's current situation is known and includes no active job;
            `null` means the

            work history could not be recovered, so nothing is claimed either
            way. The value is

            deliberately cautious — it is designed for risk decisions — so only
            clearly identified

            work counts: in the rare case where an ongoing relation cannot be
            classified you get

            `false` plus a `current_work_type_unknown` warning, never an
            optimistic `true`.
        current_work_types:
          type: array
          items:
            $ref: '#/components/schemas/WorkType'
          description: >-
            The person's current work statuses: one entry per ongoing relation,
            so repeated values reveal

            simultaneous jobs (two `employee` entries = two concurrent
            employments). An ongoing benefit

            shows as `unemployment_benefits`. An empty list means nothing
            ongoing — no job and no benefit.
        social_security_days:
          type: integer
          description: >-
            Total days effectively counted by Social Security over the whole
            career. Simultaneous

            employments are counted once, so this is NOT the sum of the
            per-relation day counts.
        work_relations_history:
          type: array
          items:
            $ref: '#/components/schemas/WorkRelationSchema'
          description: >-
            Work relation history: ongoing relations first, then the finished
            ones from the most

            recently ended backwards — including situations assimilated to
            registration such as

            benefit periods.
        contribution_base_by_company:
          type: array
          items:
            $ref: '#/components/schemas/CompanyContributionsSchema'
          default: []
          description: >-
            Contribution-base history grouped per employer account, most recent
            first. Join each group to

            its work relation through the `ccc` code.
        income_floor:
          $ref: '#/components/schemas/IncomeFloorSchema'
          description: >-
            Guaranteed minimum NET income derived from the certified
            contribution bases (the certified

            gross lower bound travels alongside it). A floor for risk
            assessment, never a salary

            estimate.
        attachments:
          type: array
          items:
            $ref: '#/components/schemas/FileAttachmentSchema'
          default: []
          description: >-
            List of attached supporting documents (e.g. the original TGSS PDF
            reports this product was

            extracted from).
        contribution_base_history:
          type: array
          items:
            $ref: '#/components/schemas/MonthlyBaseSchema'
          description: >-
            Flat monthly contribution-base history, most recent first. Months
            only — company attribution lives in `contribution_base_by_company`,
            which groups these same months per employer account.
          deprecated: true
      required:
        - product
        - sub_family
        - fetch_date
        - work_relations_history
        - contribution_base_history
      title: TGSSSpainLaborCheckSchema
```

## The holder

`holder_name` and `identifier` say whom the official reports are about, exactly as the reports print it: the holder's name, and their DNI or NIE. The official reports are the two PDFs the Social Security issues — the work-life report and the contribution-base report. When the labor check is retrieved by connecting to the Social Security, both are read **whether or not you ask for them as attachments**: the feature's `work_life_report` and `contribution_base_report` settings decide what is attached, never what is read. The holder fields record what the documents say; they do not verify your customer — comparing them with the identity you hold is your decision. The work-life report prints the given name first and the contribution-base report the surnames first: when both are read, `holder_name` is the work-life report's, and when only one could be read, it is that one's.

> **A labor check without \`holder_name\` needs a careful review**
>
> When both official reports are read, they must carry the same identity numbers, or neither is used. Their names are compared with tolerance, because each report prints them its own way — surnames first or last, abbreviated, without accents. When they still do not match, **`holder_name` is not reported**, while `identifier` is. In Direct Executions, the execution's `messages` then carry a `labor_check_holder_name_mismatch` warning.
>
> The Social Security may hold the name in two forms — after a legal change of name, for instance — or one of its records may carry an error. Either way, **compare the name printed in the reports with your customer's identity before you rely on this product** — ask for them as attachments to have them at hand.
>
> When `identifier` is not reported either, no report could be used — they were not available, could not be read, or did not agree on the holder's identity numbers — or the person has never been registered with the Social Security. If the labor check was retrieved by connecting to the Social Security, the rest of its data then comes from the Social Security's web pages, and leaving the reports out of the attachments is never the reason.

## Work relations

One entry per period of the labor life, most recent first: employments, self-employment
stretches, and situations that count for Social Security without being a job (an ongoing
unemployment benefit, paid untaken vacations). The `ccc` employer account code is the join key
to the contribution history below.

### Schema (`WorkRelationSchema`)

One period of the person's labor life: an employment, a self-employment stretch, or a
situation that counts for Social Security without being a job.

```yaml
components:
  schemas:
    WorkType:
      type: string
      enum:
        - unknown
        - employee
        - self_employed
        - public_employee
        - vacations
        - unemployment_benefits
        - other
      title: WorkType
    WorkContractType:
      type: string
      enum:
        - unknown
        - permanent
        - temporary
        - training
        - professional_practices
        - fixed_discontinuous
      title: WorkContractType
    WorkScheduleType:
      type: string
      enum:
        - unknown
        - full_time
        - part_time
      title: WorkScheduleType
    WorkRelationSchema:
      type: object
      properties:
        activity_start:
          type: string
          format: date
          description: >-
            Activity start date — the date the TGSS counts contributed days
            from.
        activity_end:
          type: string
          format: date
          description: Activity end date. Empty while the relation is ongoing.
        name:
          type: string
          description: >-
            Display name of the relation: the employer's name for employees, the
            regime for

            self-employment, and the situation description for benefit periods.
        regime:
          type: string
          description: Social Security regime of this relation.
        ccc:
          type: string
          description: >-
            Employer contribution account code (CCC) — the join key to
            `contribution_base_by_company`.

            Absent for self-employment, which has no employer account.
        assimilated:
          type: boolean
          default: false
          description: >-
            True for situations assimilated to registration (benefit periods,
            paid untaken

            vacations...) — periods that count for Social Security but are not
            an actual job. Skip

            them when reasoning about employment or earned income.
        work_type:
          $ref: '#/components/schemas/WorkType'
          description: >-
            Work type of this relation (e.g. `employee`, `self_employed`,
            `unemployment_benefits`).
        contract_type:
          $ref: '#/components/schemas/WorkContractType'
          description: >-
            Contract type as mapped from the TGSS classification; `unknown` when
            the source key has

            no mapping.
        work_schedule:
          $ref: '#/components/schemas/WorkScheduleType'
          description: 'Work schedule: `full_time`, `part_time`, or `unknown`.'
        contribution_group:
          type: string
          description: Contribution group of the worker in this relation.
        collective_agreement:
          type: string
          description: Collective agreement governing this relation, when declared.
        social_security_days:
          type: integer
          description: >-
            Days this relation counts for Social Security. Simultaneous
            relations each count their

            own days, so summing across relations overstates — the deduplicated
            career total is the

            top-level `social_security_days`.
        currently_active:
          type: boolean
          description: True while this relation is ongoing (it has no end date yet).
      required:
        - activity_start
        - name
        - work_type
        - contract_type
        - work_schedule
      title: WorkRelationSchema
```

> **A relation's days are the certified ones, not the span of its dates**
>
> A relation's `social_security_days` are the days the official report certifies, and they can be fewer than its dates span. A part-time relation counts its days at its coefficient; when the working hours changed during a relation, the report counts every one of them but prints only the last coefficient — so a relation that ended full-time can show no `part_time_percentage` and fewer days than its dates. Read the days as certified; never recompute them from the dates.

## Contribution bases

The monthly contribution history, **grouped per employer account** — join each group to its work
relation through `ccc`. The flat `contribution_base_history` on the labor check is the same
months in one list, for date-keyed consumers.

### Schema (`CompanyContributionsSchema`)

The month-by-month contribution history of one employer account (or regime).

```yaml
components:
  schemas:
    ContributionMonthStatus:
      type: string
      enum:
        - registered
        - no_alta
        - no_base_registered
        - pending_update
        - not_yet_elapsed
        - not_yet_settled
      description: >-
        State of one month in a social-security contribution-base history.


        The first five values are what the TGSS report prints.
        ``not_yet_settled``

        is the refined reading of a printed ``no_alta`` that falls inside a

        certified open relation near the report's emission date: contribution
        bases

        register with a settlement lag, so those months mean "not settled yet",

        never "not registered" — they must not count as gaps or zeros.
      title: ContributionMonthStatus
    CurrencyAmountSchemaCurrency:
      oneOf:
        - type: string
          format: currency
        - type: string
          enum:
            - '***'
      description: >-
        Three-letter ISO currency code — or `***` when the source did not
        disclose the currency.
      title: CurrencyAmountSchemaCurrency
    CurrencyAmountSchema:
      type: object
      properties:
        currency:
          $ref: '#/components/schemas/CurrencyAmountSchemaCurrency'
          description: >-
            Three-letter ISO currency code — or `***` when the source did not
            disclose the currency.
        amount:
          type: string
          format: number
          description: Decimal number with 2 digits precision
      required:
        - currency
        - amount
      description: A monetary amount together with its currency.
      title: CurrencyAmountSchema
    MonthlyBaseSchema:
      type: object
      properties:
        date:
          type: string
          format: date
          description: >-
            Last day of the contribution month — a convenience key for
            date-indexed consumers; `year`

            and `month` carry the same information.
        year:
          type: integer
          description: Contribution year.
        month:
          type: integer
          description: Contribution month (1-12).
        status:
          $ref: '#/components/schemas/ContributionMonthStatus'
          description: >-
            State of the month: `registered` (base certified by the TGSS),
            `pending_update`

            (contribution reported, amount not published yet — an existing
            contribution, NOT a gap),

            `not_yet_settled` (recent month still inside the settlement lag),
            `no_base_registered`, or

            `no_alta` (not registered that month). A month absent from the list
            altogether means no

            contribution row existed for it.
        base:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            Monthly contribution base (gross). Carries a numeric amount only
            when the month is

            `registered`; in any other state the amount is not available —
            unavailable, not zero.
        provisional:
          type: boolean
          default: false
          description: >-
            True when the base is provisional and may still be regularized by
            the TGSS — typical for

            self-employed workers until the yearly settlement.
      required:
        - date
        - year
        - month
        - status
        - base
      description: >-
        One month of contribution: its state and, when registered, the gross
        base amount.
      title: MonthlyBaseSchema
    CompanyContributionsSchema:
      type: object
      properties:
        company_name:
          type: string
          description: Employer or regime name, as certified by the TGSS.
        ccc:
          type: string
          description: >-
            Employer contribution account code (CCC) — the join key linking this
            history to the

            matching entries in `work_relations_history`. Absent for
            self-employment, which has no

            employer account.
        regime:
          type: string
          description: Social Security regime of this account.
        is_benefit_block:
          type: boolean
          default: false
          description: >-
            True when this entry tracks a benefit (e.g. cessation-of-activity
            protection for the

            self-employed), not an actual employer. Its bases are NOT earned
            income — exclude them

            from any income computation.
        months:
          type: array
          items:
            $ref: '#/components/schemas/MonthlyBaseSchema'
          default: []
          description: Monthly contribution bases of this account, most recent first.
      title: CompanyContributionsSchema
```

Each month carries its state and, when registered, the gross base:

### Schema (`MonthlyBaseSchema`)

One month of contribution: its state and, when registered, the gross base amount.

```yaml
components:
  schemas:
    ContributionMonthStatus:
      type: string
      enum:
        - registered
        - no_alta
        - no_base_registered
        - pending_update
        - not_yet_elapsed
        - not_yet_settled
      description: >-
        State of one month in a social-security contribution-base history.


        The first five values are what the TGSS report prints.
        ``not_yet_settled``

        is the refined reading of a printed ``no_alta`` that falls inside a

        certified open relation near the report's emission date: contribution
        bases

        register with a settlement lag, so those months mean "not settled yet",

        never "not registered" — they must not count as gaps or zeros.
      title: ContributionMonthStatus
    CurrencyAmountSchemaCurrency:
      oneOf:
        - type: string
          format: currency
        - type: string
          enum:
            - '***'
      description: >-
        Three-letter ISO currency code — or `***` when the source did not
        disclose the currency.
      title: CurrencyAmountSchemaCurrency
    CurrencyAmountSchema:
      type: object
      properties:
        currency:
          $ref: '#/components/schemas/CurrencyAmountSchemaCurrency'
          description: >-
            Three-letter ISO currency code — or `***` when the source did not
            disclose the currency.
        amount:
          type: string
          format: number
          description: Decimal number with 2 digits precision
      required:
        - currency
        - amount
      description: A monetary amount together with its currency.
      title: CurrencyAmountSchema
    MonthlyBaseSchema:
      type: object
      properties:
        date:
          type: string
          format: date
          description: >-
            Last day of the contribution month — a convenience key for
            date-indexed consumers; `year`

            and `month` carry the same information.
        year:
          type: integer
          description: Contribution year.
        month:
          type: integer
          description: Contribution month (1-12).
        status:
          $ref: '#/components/schemas/ContributionMonthStatus'
          description: >-
            State of the month: `registered` (base certified by the TGSS),
            `pending_update`

            (contribution reported, amount not published yet — an existing
            contribution, NOT a gap),

            `not_yet_settled` (recent month still inside the settlement lag),
            `no_base_registered`, or

            `no_alta` (not registered that month). A month absent from the list
            altogether means no

            contribution row existed for it.
        base:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            Monthly contribution base (gross). Carries a numeric amount only
            when the month is

            `registered`; in any other state the amount is not available —
            unavailable, not zero.
        provisional:
          type: boolean
          default: false
          description: >-
            True when the base is provisional and may still be regularized by
            the TGSS — typical for

            self-employed workers until the yearly settlement.
      required:
        - date
        - year
        - month
        - status
        - base
      title: MonthlyBaseSchema
```

## Income floor

> **Warning**
>
> The floor is a **guaranteed minimum net income**, never a salary estimate: deductions are
> estimated conservatively so the net stays a floor, and real net income can only be equal or
> higher. For self-employed workers it deliberately understates real income — combine it with
> other signals.

### Schema (`IncomeFloorSchema`)

A guaranteed minimum NET income derived from the contribution bases — a floor for
risk assessment, never a salary estimate. The certified gross lower bound travels
alongside in the `gross_*` fields.

```yaml
components:
  schemas:
    IncomeFloorStatus:
      type: string
      enum:
        - computed
        - not_currently_active
        - activity_unknown
        - insufficient_data
      description: Whether a guaranteed-minimum income floor could be asserted at all.
      title: IncomeFloorStatus
    CurrencyAmountSchemaCurrency:
      oneOf:
        - type: string
          format: currency
        - type: string
          enum:
            - '***'
      description: >-
        Three-letter ISO currency code — or `***` when the source did not
        disclose the currency.
      title: CurrencyAmountSchemaCurrency
    CurrencyAmountSchema:
      type: object
      properties:
        currency:
          $ref: '#/components/schemas/CurrencyAmountSchemaCurrency'
          description: >-
            Three-letter ISO currency code — or `***` when the source did not
            disclose the currency.
        amount:
          type: string
          format: number
          description: Decimal number with 2 digits precision
      required:
        - currency
        - amount
      description: A monetary amount together with its currency.
      title: CurrencyAmountSchema
    WorkType:
      type: string
      enum:
        - unknown
        - employee
        - self_employed
        - public_employee
        - vacations
        - unemployment_benefits
        - other
      title: WorkType
    IncomeFloorBasis:
      type: string
      enum:
        - window_minimum
      description: >-
        How a company entry's floor was derived.


        The per-company list only ever contains companies CONTRIBUTING to the

        computed floor (closed/stale employments are excluded entirely, so no
        past

        salary can be misread as a current one); the enum names the derivation
        and

        leaves room for future methods.
      title: IncomeFloorBasis
    CompanyIncomeFloorSchema:
      type: object
      properties:
        company_name:
          type: string
          description: Employer or regime this floor comes from.
        ccc:
          type: string
          description: Employer contribution account code (CCC) of this company.
        work_type:
          $ref: '#/components/schemas/WorkType'
          description: Work type behind this income.
        monthly_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            Estimated minimum NET monthly income from this company: its worst
            observed window

            month's net share, after worker Social Security contributions and
            IRPF withholding at

            that month's real income mix. Every unknown (contract type, age,
            family situation) is

            resolved toward more deductions, so real take-home pay can only be
            equal or higher.
        annual_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: Estimated minimum NET annual income from this company.
        gross_monthly_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            The certified GROSS monthly floor this company's net figure derives
            from — the minimum

            contribution base over the observation window.
        gross_annual_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            The certified GROSS annual floor from this company (the gross
            monthly floor x12).
        basis:
          $ref: '#/components/schemas/IncomeFloorBasis'
          description: >-
            How this floor was derived (e.g. `window_minimum`: the minimum base
            over the trailing

            window of fully certified months).
        observed_months:
          type: integer
          default: 0
          description: >-
            Number of certified months the floor is based on — the more months,
            the steadier the

            floor.
      required:
        - company_name
        - monthly_floor
        - annual_floor
        - basis
      description: >-
        One company's share of the income floor: the minimum net income it
        contributes.
      title: CompanyIncomeFloorSchema
    IncomeFloorSchema:
      type: object
      properties:
        status:
          $ref: '#/components/schemas/IncomeFloorStatus'
          description: >-
            Whether a floor could be asserted: `computed` (floor available),
            `not_currently_active`

            (no ongoing employment — e.g. between contracts, a scheduled future
            hire or an ongoing

            unemployment benefit; the current floor is zero),
            `insufficient_data` (working, but not

            enough certified months yet to measure a floor), or
            `activity_unknown` (no employment

            evidence either way).
        monthly_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            Estimated minimum NET monthly income: the worst observed window
            month after worker

            Social Security contributions and IRPF withholding. A lower bound
            for risk assessment —

            NOT a salary estimate: every unknown in the conversion (contract
            type, age, family

            situation) is resolved toward more deductions, so real take-home pay
            can only be equal

            or higher. For self-employed workers it deliberately understates
            real income; combine

            with other signals.
        annual_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: The net monthly floor, annualized.
        gross_monthly_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            Guaranteed minimum GROSS monthly income, certified by the
            contribution bases. The net

            floor is minimized over months separately, so it can come from a
            different (net-worse)

            month than this gross minimum.
        gross_annual_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: The gross monthly floor, annualized (x12).
        estimated_deduction_rate:
          type: string
          format: number
          default: nan
          description: Decimal number with 4 digits precision
        observed_months:
          type: integer
          default: 0
          description: >-
            Number of months the floor was measured over. A month only partly
            worked (a start after

            the 1st, an end before the month's last day) is left out once at
            least two full months

            exist, so its prorated pay never passes for a monthly income. Fewer
            than 3 means the

            floor rests on little evidence — typically a recent hire.
        companies:
          type: array
          items:
            $ref: '#/components/schemas/CompanyIncomeFloorSchema'
          default: []
          description: >-
            Only the companies contributing to the computed floor (ongoing,
            recent activity). Past

            employments are never listed here — their history is in
            `contribution_base_by_company` —

            so nothing in this list can be misread as a salary the person no
            longer earns.
        method_version:
          type: string
          description: >-
            Version of the floor derivation method. Bumped whenever the
            algorithm changes meaning —

            compare floors only within the same version.
      required:
        - status
      title: IncomeFloorSchema
```

Each company contributing to the computed floor appears with its own share — past employments
are never listed here, so nothing in this list can be misread as a salary the person no longer
earns:

### Schema (`CompanyIncomeFloorSchema`)

One company's share of the income floor: the minimum net income it contributes.

```yaml
components:
  schemas:
    WorkType:
      type: string
      enum:
        - unknown
        - employee
        - self_employed
        - public_employee
        - vacations
        - unemployment_benefits
        - other
      title: WorkType
    CurrencyAmountSchemaCurrency:
      oneOf:
        - type: string
          format: currency
        - type: string
          enum:
            - '***'
      description: >-
        Three-letter ISO currency code — or `***` when the source did not
        disclose the currency.
      title: CurrencyAmountSchemaCurrency
    CurrencyAmountSchema:
      type: object
      properties:
        currency:
          $ref: '#/components/schemas/CurrencyAmountSchemaCurrency'
          description: >-
            Three-letter ISO currency code — or `***` when the source did not
            disclose the currency.
        amount:
          type: string
          format: number
          description: Decimal number with 2 digits precision
      required:
        - currency
        - amount
      description: A monetary amount together with its currency.
      title: CurrencyAmountSchema
    IncomeFloorBasis:
      type: string
      enum:
        - window_minimum
      description: >-
        How a company entry's floor was derived.


        The per-company list only ever contains companies CONTRIBUTING to the

        computed floor (closed/stale employments are excluded entirely, so no
        past

        salary can be misread as a current one); the enum names the derivation
        and

        leaves room for future methods.
      title: IncomeFloorBasis
    CompanyIncomeFloorSchema:
      type: object
      properties:
        company_name:
          type: string
          description: Employer or regime this floor comes from.
        ccc:
          type: string
          description: Employer contribution account code (CCC) of this company.
        work_type:
          $ref: '#/components/schemas/WorkType'
          description: Work type behind this income.
        monthly_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            Estimated minimum NET monthly income from this company: its worst
            observed window

            month's net share, after worker Social Security contributions and
            IRPF withholding at

            that month's real income mix. Every unknown (contract type, age,
            family situation) is

            resolved toward more deductions, so real take-home pay can only be
            equal or higher.
        annual_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: Estimated minimum NET annual income from this company.
        gross_monthly_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            The certified GROSS monthly floor this company's net figure derives
            from — the minimum

            contribution base over the observation window.
        gross_annual_floor:
          $ref: '#/components/schemas/CurrencyAmountSchema'
          description: >-
            The certified GROSS annual floor from this company (the gross
            monthly floor x12).
        basis:
          $ref: '#/components/schemas/IncomeFloorBasis'
          description: >-
            How this floor was derived (e.g. `window_minimum`: the minimum base
            over the trailing

            window of fully certified months).
        observed_months:
          type: integer
          default: 0
          description: >-
            Number of certified months the floor is based on — the more months,
            the steadier the

            floor.
      required:
        - company_name
        - monthly_floor
        - annual_floor
        - basis
      title: CompanyIncomeFloorSchema
```