> ## 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.

# Círculo de Crédito

> The first credit bureau in the catalogue: what enabling it takes, what a consulta carries, what the decision records, and what its failure means.

**Círculo de Crédito** is a Mexican credit information society and the first source in the catalogue that reaches a network. The Platform reads its consumer credit report (RCC) as your instrument, under your own contract and credentials, one lookup per authorisation. One lookup is one **consulta**. That is the source's cost unit, the ledger carries the word, and you reconcile it against Círculo's own invoice.

Everything on [Credit sources](/lending/credit-sources): custody, the ledger, the satellite and offboarding applies to this source unchanged. This page is what is specific to it.

| Part of the declaration | For Círculo |
| - | - |
| Failure posture | `retry`, an outage is transport, not an outcome |
| Prohibition | None. Reading a consumer report discharges no legal screening duty |
| Transport | Network |
| Requirements | Identity fields below, your credentials, the borrower's authorisation |
| Cost unit | `consulta` |

## Before you enable it

Three things exist before the Console steps on [Credit sources](/lending/credit-sources) are performed for `circulo_rcc`, and none of them is the Platform's to provide.

| You hold | What it is |
| - | - |
| A contract with Círculo de Crédito | You are the bureau's Usuario. The Platform queries with your standing and holds none of its own |
| Integration credentials | The four-part document below, issued by Círculo for your account |
| An authorisation process | How you capture the borrower's authorisation and store the signed document. You attest to it on every application |

## Credentials

The credential you supply at the Console is one JSON document. The Platform seals it whole and parses it only at the moment of a consulta; a document without a usable API key cannot authenticate, and the attempt records `credentials_rejected`.

| Field | Requirement | What it is |
| - | - | - |
| `api_key` | Required | The Consumer Key of your approved application on Círculo's developer portal. The sandbox authenticates by it alone |
| `signing_key_pem` | Production | The ECDSA private key whose certificate you registered with Círculo, PEM-encoded. When present, the Platform signs each consulta with it as `x-signature`, which production verifies and the sandbox ignores |

```json The document you supply as the credential theme={null}
{
  "api_key": "…",
  "signing_key_pem": "-----BEGIN EC PRIVATE KEY-----\n…\n-----END EC PRIVATE KEY-----\n"
}
```

Against the sandbox, a document carrying only `api_key` is complete. Before production, generate the key pair, register its certificate with Círculo, and re-supply the document with both fields, because supplying does not withdraw what is there, so the swap has no window.

<Warning>
  Rotating any part is supplying a new document and then withdrawing the old one, in that order, the same rotation rule as every credential, applied to the document as a whole. There is no partial update.
</Warning>

## Naming a person

A consulta is addressed by identity fields on the application, checked before anything leaves. The required set is the enabled product's own published contract: the person whole, and the domicile whole.

| Field | Requirement | What it is |
| - | - | - |
| `given_name` | Required | First name, no initials |
| `first_surname` | Required | Apellido paterno |
| `second_surname` | Required | Apellido materno |
| `birth_date` | Required | ISO `YYYY-MM-DD` |
| `rfc` | Required | RFC with homoclave |
| `address` | Required | Street line: street and numbers |
| `address_colonia` | Required | Colonia |
| `address_municipio` | Required | Delegación or municipio |
| `address_city` | Required | City |
| `address_state` | Required | The state in Círculo's own catalogue value, e.g. `CDMX` |
| `address_postal_code` | Required | 5 digits, consistent with the state |
| `curp` | Optional | Travels to the bureau when stated |

The Platform transliterates names and address lines on the way out: accents to plain letters, upper case, as the bureau's contract itself asks; you may state `Ciudad de México` and the wire carries `CIUDAD DE MEXICO`.

An application missing a required field is refused naming it, and nothing reaches Círculo, no consulta is billed and no enquiry registers on the borrower's file. The refusal is a `422` under `source_access`, carrying the source's own sentence:

```json 422, no RFC, captured from a real run theme={null}
{
  "error": "risk: a source this decision needs cannot be read: source: the lookup cannot address the subject: circulo_rcc addresses a lookup by rfc and the application states none",
  "code": "source_access"
}
```

These fields travel, address the source, and come to rest in the satellite beside the decision. No decision record carries them.

## Authorisation

Every consulta runs under the four authorisation fields the application names, `consent.artifact_id`, `given_at`, `expires_at`, `attested`, checked before anything is fetched, exactly as [Credit sources](/lending/credit-sources) states.

When you set `attested`, you state on the record that you hold the borrower's authorisation that the law governing credit information societies requires of the party making the enquiry. The Platform forwards that statement as yours and composes none of its own. The ledger keeps what you attested and when. A consulta made on a false attestation is yours to answer for, to the borrower, to Círculo, and to the authority. Your counsel owns what your authorisation document must say; this is not legal advice.

One authorisation supports one consulta, and a report is never cached and never reused:

* A second decision about the same person is a second consulta under its own `artifact_id`. Nothing from the first report is served to it.
* A retry of a *failed* attempt under the same authorisation is the same consulta still being attempted, not a reuse: see the outage section below.
* There is no field in the Platform that could hold a report for reuse: the schema has no column for one.

## What comes back

A successful consulta produces four read attributes, each mapped from the report under the published RCC mapping, version 1. A policy version that reads any of them must band their `unavailable` state, the coherence rules refuse one that does not.

| Attribute | What it is | Reads `unavailable` when |
| - | - | - |
| `rcc_accounts_open` | Open credit accounts on the report, 0 to 100 | The report carried no account section |
| `rcc_worst_delay_periods` | The worst current delay across open accounts, in scheduled payments behind, 0 to 12 | No account is open, or an account carries an adverse marker instead of a count, because "no worst delay" is an absence, not punctuality |
| `rcc_months_of_history` | Whole months from the oldest account's opening to the report's own date, 0 to 600 | No account carries a readable opening date |
| `rcc_inquiries_last_12m` | Enquiries in the 12 months before the report's date, 0 to 120 | The report carried no enquiry section |

The decision's record names the consulta without carrying the report. Captured from a real run, the source list of a recorded decision:

```json The decision's source list, captured from a real run theme={null}
"sources": [{
  "name": "circulo_rcc",
  "consent_id": "consent-0001",
  "consented_at": "2026-08-29T20:11:26Z",
  "consent_expires_at": "2026-11-27T21:11:26Z",
  "attested": true,
  "source_reference": "folio-e2e-0001",
  "mapping_version": 1,
  "mapping_digest": "97d9e839fac025596925499bcbff7ea676738f170e7a12d5dacd2844a0fcad24",
  "attempt_id": "ff5b2db8-f01e-4720-98ba-4d9510a21ea0",
  "unavailable": false
}]
```

* `source_reference` is the **folio** Círculo assigned to the consulta, the identifier a dispute is taken back to the bureau under. The same folio stands on the attempt and on the ledger entry.
* `attempt_id` is the Platform's own handle, and the join to your ledger.
* The report itself is in none of this. It lives in the satellite beside the decision, under the custody rules, destroyable while the record stands.

## No file on the person

A person the bureau holds nothing on is an **answer**, not an outage. Círculo speaks it two ways: an empty `204` response, or its own `404` refusal, *No se encontró a la persona*, and the Platform records both under the one outcome name `subject_not_found`. The consulta runs, the attempt records it, and the decision is taken with every RCC attribute in its `unavailable` state, banded by your policy like any other absence. No retry asks again about a history that does not exist, and because neither spelling carries a folio, the attempt is the only handle that answer has.

## When it cannot be reached

The source's posture is `retry`: no decision exists, nothing is recorded as one, and the application's reference stays free. The answer is a `424` naming the attempt, the one thing that provably exists after a response is lost:

```json 424, a consulta that timed out, captured from a real run theme={null}
{
  "error": "risk: a source this decision needs did not answer: circulo_rcc answered \"unreachable\" and no decision was recorded -- the reference stays free; the attempt 681c5b07-e12a-4e52-8251-e8c316c9ee1f is the platform's handle for the lookup and the tenant's ledger carries it; resubmit the same application under the same reference and authorisation once the source recovers",
  "code": "source_unavailable",
  "retry": "as_is",
  "details": { "attempt_id": "681c5b07-e12a-4e52-8251-e8c316c9ee1f" },
  "request_id": "0190f6a2-3c4d-7e8f-9a0b-1c2d3e4f5a6b"
}
```

A program reads the attempt from `details.attempt_id` and whether to resubmit from `retry`: `as_is` where the source's failure is retryable, as here, and `never` where a resubmission would meet the same failure and the outcome has to be settled with the source first.

Resubmit the same application, same reference, same authorisation, once the source recovers. That retry is the same consulta still being attempted, and the recovered run's decision records the fresh attempt beside the folio it obtained. Both attempts stand in your ledger under the one authorisation.

The failure vocabulary is declared on the source and served back to you on `GET /v1/tenants/{tenant_id}/sources`, so your handling is written against the declared set rather than reverse-engineered from an outage.

| Outcome | Retryable | What it is |
| - | - | - |
| `unreachable` | Yes | The source could not be reached, or did not answer in time. Whether the consulta registered is unknowable from here |
| `source_refused_lookup` | No | Círculo refused the lookup as sent. Resubmitting the same one meets the same refusal |
| `credentials_rejected` | No | Your standing was rejected, or the supplied document cannot authenticate. Re-supply before retrying |
| `subject_not_found` | No. It is an answer | The bureau holds no file on the person. The decision proceeds on absent states |

One more outcome can reach your ledger and is not on that table, because it is the Platform's word rather than Círculo's: `unreadable_response`, always retryable. It means the answer was not the protocol being spoken, a status the contract does not describe, a redirect, or a `200` carrying no folio. The Platform follows no redirect, so nothing carrying your key travels to whatever host one names.

## The ledger entry

One consulta, as your ledger answers it, captured from a real run:

```json One ledger entry, captured from a real run theme={null}
{
  "id": "67f60c0e-ee3e-4191-8235-7a12646e99e2",
  "source": "circulo_rcc",
  "client_id": "client-alonso",
  "reference": "app-docs-0001",
  "consent_artifact_id": "consent-0001",
  "consent_given_at": "2026-08-29T20:11:26Z",
  "consent_expires_at": "2026-11-27T21:11:26Z",
  "attempt_id": "ff5b2db8-f01e-4720-98ba-4d9510a21ea0",
  "outcome": "ok",
  "source_reference": "folio-e2e-0001",
  "cost_unit": "consulta",
  "occurred_at": "2026-08-29T21:11:26.931278Z"
}
```

When, about whom, under which application and which authorisation, what came of it, the folio, and what it cost, and no payload. A failed consulta leaves an entry the same way, under its outcome name.

What separates a billed line from a free one is whether the call left the Platform, not whether it succeeded.

| `cost_unit` | Which attempts |
| - | - |
| `consulta` | Every attempt that reached Círculo, the successes, and `unreachable`, `source_refused_lookup`, `subject_not_found`, `unreadable_response` and a `credentials_rejected` the bureau itself answered |
| `none` | An attempt nothing of which reached Círculo: the credential you supplied could not be parsed or its signing key could not be loaded, or the connection could not be opened at all, the name did not resolve, the port refused, or the handshake failed |

A call that left is one your account may be billed for whatever happened next, so the ledger prices it at the source's own unit even where the answer never arrived, a connection reset mid-answer or a deadline that passed while waiting is a consulta the bureau may have registered, and whether it did is not knowable from this side. A call that never left cost nothing, keeps its entry and its attempt so you hold the refusal, and does not count against your daily bound. What decides which is which is the transport's own record of the request having been written, not the name of the failure: a connection the Platform could not open still reads `unreachable`, so your retry posture applies, and it still shows as an outage where the Platform watches sources.

<Info>
  The regulatory readings behind this source, who the Usuario is under LRSIC arts. 29 and 30, and what one authorisation may be used for under the Regla Octava, are held conservatively and listed on [Lending in Mexico](/lending/mexico).
</Info>


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