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

# Read a policy version

> Read one version of a Credit policy whole: the attributes it reads, its knockouts, its scorecard and its cutoff bands.

This call answers one version of one Credit policy, complete: every attribute it reads with that attribute's bounds and the reason the Platform holds for reading it, every knockout with its bound, every scorecard entry with its bands and points, and every cutoff band with its outcome, rate and ceiling.

A version resolves on its own. Nothing here is a difference against an earlier version, and reading it needs no other version.

<Info>
  The rules your applications are decided by are not held back from you. A Tenancy that cannot read the scorecard cannot explain its own refusals.
</Info>

## Path parameters

<ParamField path="tenant_id" type="string" required>
  The Tenancy asking. Another Tenancy's path answers `403`.
</ParamField>

<ParamField path="policy" type="string" required>
  The policy's name, as the list answers it: `mx-base`.
</ParamField>

<ParamField path="version" type="integer" required>
  The version number, counting from 1.
</ParamField>

## Response

<ResponseField name="policy" type="string" required>
  The policy this version belongs to.
</ResponseField>

<ResponseField name="version" type="integer" required>
  The version number.
</ResponseField>

<ResponseField name="digest" type="string" required>
  The digest of this version's content. Every Decision decided under it records the same value.
</ResponseField>

<ResponseField name="currency" type="string" required>
  The money this version states its principal ceilings in, as an ISO 4217 code. An application naming a Configuration version denominated in other money is refused.
</ResponseField>

<ResponseField name="attributes" type="array" required>
  Every attribute this version reads, directly or as the input of one it derives.

  <Expandable title="attribute">
    <ResponseField name="name" type="string" required>
      How an application spells it.
    </ResponseField>

    <ResponseField name="kind" type="string" required>
      `declared` — you state it. `derived` — the Platform computes it from declared values and the requested principal, and refuses an application that states it.
    </ResponseField>

    <ResponseField name="unit" type="string" required>
      What the number counts: `years`, `months`, `minor units`, `count` or `basis points`.
    </ResponseField>

    <ResponseField name="min" type="integer" required>
      The lowest value the Platform reads, inclusive. A value below it is refused rather than banded.
    </ResponseField>

    <ResponseField name="max" type="integer" required>
      The highest value the Platform reads, inclusive.
    </ResponseField>

    <ResponseField name="admits" type="array" required>
      The non-present states this attribute may arrive in: `not_applicable`, `unavailable`, or neither. Empty means the fact is one you always hold.
    </ResponseField>

    <ResponseField name="rationale" type="string" required>
      What the attribute is for and why the Platform reads it.
    </ResponseField>

    <ResponseField name="permissibility" type="string" required>
      The Platform's explicit verdict that reading it is permitted.
    </ResponseField>

    <ResponseField name="max_age_days" type="integer">
      How old the day a declared value is held true on may be. Absent on a derived attribute, which carries no day of its own.
    </ResponseField>

    <ResponseField name="reads_inputs" type="array">
      The declared attributes a derived attribute is computed from. Absent on a declared one.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="knockouts" type="array" required>
  Rules that settle an application outright, each comparing one attribute against one bound. Every one of them is evaluated for every application — not only up to the first that fires.

  <Expandable title="knockout">
    <ResponseField name="id" type="string" required>
      Stable across versions and namespaced to whoever authored the rule. The Platform's own carry `capcells:`. An identifier never names a different rule in a later version.
    </ResponseField>

    <ResponseField name="text" type="string" required>
      What the rule does, in words. It travels into every Decision's trace, so a refusal explains itself without this call.
    </ResponseField>

    <ResponseField name="attribute" type="string" required>
      The attribute the rule reads.
    </ResponseField>

    <ResponseField name="comparison" type="string" required>
      `less_than`, `at_most`, `at_least` or `greater_than`. The rule fires when the value stands in that relation to the bound.
    </ResponseField>

    <ResponseField name="bound" type="integer" required>
      The value compared against, in the attribute's own unit.
    </ResponseField>

    <ResponseField name="outcome" type="string" required>
      What firing produces: `refuse`, or `refer` where the rule is a case the policy declines to settle. A knockout never approves.
    </ResponseField>

    <ResponseField name="absent" type="array">
      What the rule does when the attribute arrives in a non-present state. One entry per state the attribute admits, each with `state` and `fires`.
    </ResponseField>

    <ResponseField name="moratorium_days" type="integer">
      How many whole days a refusal this rule produced stands against re-application. Only a refusing knockout carries one, and it need not. Where several fired knockouts carry one, the refusal carries the longest.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="scorecard" type="array" required>
  Entries that award points. The score is their integer sum.

  <Expandable title="entry">
    <ResponseField name="id" type="string" required>
      The entry's stable identifier.
    </ResponseField>

    <ResponseField name="text" type="string" required>
      What the entry rewards, in words.
    </ResponseField>

    <ResponseField name="attribute" type="string" required>
      The attribute it reads.
    </ResponseField>

    <ResponseField name="bands" type="array" required>
      The value bands, each with `from`, `to` and `points`, inclusive at both ends. They cover the attribute's whole domain with no gap and no overlap.
    </ResponseField>

    <ResponseField name="states" type="array">
      Points for each non-present state the attribute admits, each with `state` and `points`. An entry silent about a state is not served.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="cutoffs" type="array" required>
  The score bands, an ordered partition of every score the scorecard can produce.

  <Expandable title="band">
    <ResponseField name="id" type="string" required>
      The band's stable identifier. A Decision names it as `band`.
    </ResponseField>

    <ResponseField name="text" type="string" required>
      What the band means, in words.
    </ResponseField>

    <ResponseField name="from" type="integer" required>
      The lowest score in the band, inclusive.
    </ResponseField>

    <ResponseField name="to" type="integer" required>
      The highest score in the band, inclusive.
    </ResponseField>

    <ResponseField name="outcome" type="string" required>
      `refuse`, `approve` or `refer`.
    </ResponseField>

    <ResponseField name="rate" type="object">
      An approving band's exact annual rate, as `numerator`, `denominator` and `quotation`. `9/20 annual nominal` is 45% per year. Only an approving band carries one.
    </ResponseField>

    <ResponseField name="ceiling" type="object">
      An approving band's principal ceiling, in minor units of the version's currency. A request above it is refused naming the ceiling.
    </ResponseField>

    <ResponseField name="moratorium_days" type="integer">
      How many whole days a refusal under this band stands against re-application. Only a refusing band carries one, and a refusing band need not.
    </ResponseField>
  </Expandable>
</ResponseField>

## What `mx-base` version 1 decides

The base policy for the Mexican market reads seven declared attributes and four it derives from them. Its score runs from 0 to 111.

| Band | Score | Outcome | Terms |
| - | - | - | - |
| `capcells:mx.cutoff.below` | 0–49 | `refuse` | Bars re-application for 30 days |
| `capcells:mx.cutoff.referred` | 50–64 | `refer` | None |
| `capcells:mx.cutoff.standard` | 65–84 | `approve` | 60% per year, up to MXN 15,000.00 |
| `capcells:mx.cutoff.preferred` | 85–111 | `approve` | 45% per year, up to MXN 50,000.00 |

<Warning>
  Every bound in this content is a conservative assertion pending a jurisdictional review, in the same sense the Mexican moratory-interest rule is. The age floor of 21 sits three years above the age of majority, the age ceiling of 75 is a proxy for term risk, and a single prior default refuses outright.
</Warning>

## Refusals

This route reads no query parameter and takes no body.

| Status | When |
| - | - |
| `400` | The URL carries a query parameter, which this route does not read |
| `403` | The key authenticates for another Tenancy |
| `404` | The Platform publishes no such policy, or no such version of it |

<RequestExample>
  ```bash Read theme={null}
  curl https://api.capcells.com/v1/tenants/capyplazo/credit-policies/mx-base/versions/1 \
    -H "Authorization: $(capcells_sign "$CAPCELLS_API_KEY" GET /v1/tenants/capyplazo/credit-policies/mx-base/versions/1)"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 Abridged theme={null}
  {
    "policy": "mx-base",
    "version": 1,
    "digest": "498e17408e74013e84c500e261fa7bc3f22a51a721c7c1540e1b5b755ad85cab",
    "currency": "MXN",
    "attributes": [
      {
        "name": "age_years",
        "kind": "declared",
        "unit": "years",
        "min": 18,
        "max": 100,
        "admits": [],
        "max_age_days": 365,
        "rationale": "Capacity to contract and the shape of the credit risk over a term. Read as the age the tenant states its client to be on the day it states it.",
        "permissibility": "Permitted: age is a term of the contract's own validity in the launch market. Provisional under the regulatory-conservative flag and first on the jurisdictional pass, because the bound below is a lending rule rather than a modelling choice."
      },
      {
        "name": "obligations_to_income_bps",
        "kind": "derived",
        "unit": "basis points",
        "min": 0,
        "max": 1000000,
        "admits": ["not_applicable"],
        "rationale": "What the client already owes each month against what they earn each month. How much of the income is spoken for before this loan is considered.",
        "permissibility": "Permitted: arithmetic over two declared facts.",
        "reads_inputs": ["monthly_income_minor", "monthly_obligations_minor"]
      }
    ],
    "knockouts": [
      {
        "id": "capcells:mx.age.under-minimum",
        "text": "The client is younger than the minimum age this policy lends to.",
        "attribute": "age_years",
        "comparison": "less_than",
        "bound": 21,
        "outcome": "refuse"
      },
      {
        "id": "capcells:mx.income.unassessable",
        "text": "The client's monthly income is stated as nothing, or was not gathered at all, so affordability cannot be assessed.",
        "attribute": "monthly_income_minor",
        "comparison": "at_most",
        "bound": 0,
        "absent": [{ "state": "unavailable", "fires": true }],
        "outcome": "refer"
      }
    ],
    "scorecard": [
      {
        "id": "capcells:mx.score.age",
        "text": "Points for the client's age, most at the middle of a working life.",
        "attribute": "age_years",
        "bands": [
          { "from": 18, "to": 20, "points": 0 },
          { "from": 21, "to": 24, "points": 5 },
          { "from": 25, "to": 34, "points": 15 },
          { "from": 35, "to": 49, "points": 20 },
          { "from": 50, "to": 64, "points": 15 },
          { "from": 65, "to": 100, "points": 5 }
        ]
      }
    ],
    "cutoffs": [
      {
        "id": "capcells:mx.cutoff.below",
        "text": "Below the cutoff: the application is refused.",
        "from": 0,
        "to": 49,
        "outcome": "refuse",
        "moratorium_days": 30
      },
      {
        "id": "capcells:mx.cutoff.preferred",
        "text": "Approved on preferred terms.",
        "from": 85,
        "to": 111,
        "outcome": "approve",
        "rate": { "numerator": 9, "denominator": 20, "quotation": "annual nominal" },
        "ceiling": { "minor_units": 5000000, "currency": "MXN" }
      }
    ]
  }
  ```

  ```json 404 No such version theme={null}
  {
    "error": "risk: unknown policy version: mx-base publishes versions 1 to 1 and not 9",
    "code": "unknown_version"
  }
  ```
</ResponseExample>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.