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

# Verifying a statement

> Check that someone's income statement is real, without an account and without asking us.

An Orru statement is a record on Creditcoin. Anyone can read it. You do not need an account, an API key, or our cooperation, and that is deliberate. A verification service you have to trust is the thing Orru exists to remove.

## Two ways, same answer

<CardGroup cols={2}>
  <Card title="Open the page" icon="browser">
    `https://orru.xyz/verify/<credentialId>`

    Server-rendered, no wallet, no login. Works in a fresh incognito window. Hand this link to anyone.
  </Card>

  <Card title="Call the API" icon="code">
    `GET /api/verify/<credentialId>`

    The same data as JSON. Public and unauthenticated.
  </Card>
</CardGroup>

Or skip us entirely and [read the contract yourself](/verify/on-chain). The page and the API are conveniences; the credential lives on-chain and answers to nobody.

## What a statement proves

Four checks compose into one statement.

<Steps>
  <Step title="The Ethereum evidence is authentic">
    Attestcoin authenticated the source transaction against attested Ethereum history through Creditcoin's native query verifier. For Demo Payroll that receipt contains the ERC-20 transfer. For Semuni it contains the payer's commitment, not proof of an off-chain bank transfer.
  </Step>

  <Step title="The payer is recognised">
    The event came from the exact expected source contract, and its indexed payer is approved. The payer comes from `topics[1]`, not the transaction's gas-paying `from` address. A stranger emitting a lookalike event does not count.
  </Step>

  <Step title="The proof uses the same commitments">
    The zero-knowledge proof recomputes each commitment from the private amount, period and salt. Creditcoin requires those byte-identical commitments to be the ones Attestcoin accepted, then checks the common band and consecutive periods.
  </Step>

  <Step title="The subject controls the wallet">
    The holder signed an EIP-712 authorization at issuance. A proof shows payments exist; it does not show that whoever submitted it owns the address they named. Both are required.
  </Step>
</Steps>

<Warning>
  For an off-chain payer, the cryptographic claim begins at the approved payer's anchor. Orru removes trust in its own indexing and database, but it cannot prove that an external bank transfer occurred from an Ethereum commitment alone.
</Warning>

## What it does not prove

<Warning>
  This does not prove future income, affordability, legal credit eligibility, or guaranteed repayment.
</Warning>

It is a dated record of past payments, not a forecast. Treat it as one input to your own decision.

## What you get, and what you do not

A statement carries an **income band**, never an amount.

| You see                            | You do not see            |
| ---------------------------------- | ------------------------- |
| `$2,500 to $4,000` per cycle       | the exact figure          |
| how many periods were proven       | the individual payments   |
| which payer the evidence came from | the payer's other workers |
| the date the evidence ends         | anything after that date  |

The band is enforced by a zero-knowledge circuit: the holder proves every payment fell inside one band without revealing what any of them were. That is the whole point, and it means a narrower band is more useful to you and less private to them.

## Statements do not expire

There is no expiry field, and that is a design decision rather than an omission.

A statement attests a **dated past window**, and that stays true forever. Whether a window is recent enough to lend against is your policy, not ours. A payday lender and a mortgage underwriter will not agree, and neither should be forced into the other's answer.

Every statement carries `evidenceEndDate`: the date of the most recent payment it proves. Apply your own maximum age to it.

```js theme={null}
const MAX_AGE_DAYS = 30;

const age = (Date.now() - Date.parse(statement.evidenceEndDate)) / 86_400_000;
if (age > MAX_AGE_DAYS) {
  // Not invalid, just older than your policy accepts.
}
```

<Info>
  If you want this enforced on-chain rather than in your code, `DemoCreditPool` shows the pattern: a `minimumEvidenceHeight` floor that rejects anything older, and can only ever be raised.
</Info>

## Three states, and only three

<AccordionGroup>
  <Accordion title="valid">
    Issued and not revoked. Read the band, the period count, and `evidenceEndDate`, then apply your own freshness policy.
  </Accordion>

  <Accordion title="revoked">
    The holder or the issuer withdrew it. `revokedAt` says when. Do not lend against a revoked statement, regardless of how good the band looks.
  </Accordion>

  <Accordion title="unknown">
    No statement with that id was ever issued. Usually a mistyped id. A credential id is `0x` followed by 64 hex characters; anything else is not one.
  </Accordion>
</AccordionGroup>

<Warning>
  **Render on `status`, never on whether you got data back.** The contract returns a fully populated record for a revoked statement: same subject, same band, everything. Code that checks "did I receive a response?" will show a revoked statement as valid.
</Warning>
