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

# Anyone's public credit record

> The page someone back home opens to check a record (`/verify` in the app).



## OpenAPI

````yaml https://api.matocard.xyz/openapi.json get /verify/{wallet}
openapi: 3.1.0
info:
  title: Matocard API
  version: 1.0.0
  description: >-
    The backend the app calls. Served at `/docs` (this page) and
    `/openapi.json`. Guides, concepts and the contracts are in the docs:
    https://docs.matocard.xyz


    **Amounts** are decimal strings in the currency's smallest unit, never
    floats: AUSD has 6 decimals (`"1000000"` = 1 AUSD), IDR has none (`"50000"`
    = Rp 50,000), MYR is in sen. Format them with `formatAmount` from
    `@matocard/core`.


    **Signing in.** No passwords: the account's key (the Mera passkey account)
    signs once, and the app sends the result on every signed route as


    `Authorization: Matocard <wallet>.<until>.<signature>`


    where `until` is a unix time at most 7 days ahead and `signature` is
    `personal_sign` (viem `signMessage`) of exactly:


    ```

    Sign in to Matocard

    <wallet in lowercase>

    until <until>

    ```


    The first signed call creates the user. To try a signed route here, press
    **Authorize** and paste the whole header value, `Matocard 0x….…`.


    **Errors** are `{ "error": "…" }` with a 4xx status and a message the app
    may show. 500 is `something went wrong` and is logged on the server.


    **Signed transfers (ERC-3009).** `/sends` and `/cashouts` take an AUSD
    `TransferWithAuthorization` the user signed, so the relayer pays the gas.
    EIP-712 domain on Monad testnet: `name: "Agora Dollar"`, `version: "1"`,
    `chainId: 10143`, `verifyingContract:
    0xa9012a055bd4e0eDfF8Ce09f960291C09D5322dC`. Types:
    `TransferWithAuthorization(address from, address to, uint256 value, uint256
    validAfter, uint256 validBefore, bytes32 nonce)`. Use a random 32-byte
    `nonce` per transfer.


    **Money in.** Top-ups and settlements return a Xendit `checkoutUrl`; open
    it, and the backend credits the contract when Xendit reports the payment.
    Poll `GET /me` (or `/me/activity`, whose `inFlight` lists payments not
    onchain yet) to see it land. **Which currency:** ask for a `USD/MYR` quote
    when `user.country` is `MY` (ringgit through Xendit Malaysia: FPX, DuitNow
    QR, Malaysian cards), otherwise `USD/IDR` (rupiah through Xendit Indonesia:
    virtual accounts, QRIS, cards). Cash-outs are always `USD/IDR`. In test mode
    nothing is charged: FPX and DuitNow pages have a button to succeed, and the
    Indonesian virtual account numbers are not real, so never transfer to them
    (pick one and ask the backend owner to simulate it), or pay with a Xendit
    test card. A card top-up shows in `collateral.pendingShares` until its hold
    ends (about a minute on testnet); virtual accounts, QRIS, FPX and DuitNow
    count at once.


    **Done in the app, not here:** `draw(amount, to)` (borrow, straight to
    anyone's wallet), `repay` / `repayWithPermit` (pay back in AUSD),
    `repayFromCollateral(amount)` (pay back out of collateral) and
    `withdrawCollateral` are the user's own transactions on the `MatoCreditLine`
    contract (`0x4D6279c3DD0369e788C33b3aE1297D4E9abbd01a`), paid with the MON
    the backend drips after KYC. Send each with `gas: gasLimits.<function>` from
    `@matocard/contracts`: Monad charges the gas limit, so a fixed limit is
    cheaper than a padded estimate.
servers:
  - url: https://api.matocard.xyz
    description: VPS, Monad testnet, Xendit and Didit in test mode
  - url: http://127.0.0.1:3000
    description: local docker compose
security: []
tags:
  - name: Public
  - name: Account
    description: Signed in
  - name: Money
    description: >-
      Signed in; top-ups and sends also need the account verified onchain
      (`verified` in `GET /me`)
  - name: Webhooks
    description: Called by Xendit and Didit, not by the app
paths:
  /verify/{wallet}:
    get:
      tags:
        - Public
      summary: Anyone's public credit record
      description: >-
        The page someone back home opens to check a record (`/verify` in the
        app).
      parameters:
        - name: wallet
          in: path
          required: true
          schema:
            $ref: '#/components/schemas/Address'
      responses:
        '200':
          description: The record
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Verify'
        '404':
          description: Not an address
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security: []
components:
  schemas:
    Address:
      type: string
      pattern: ^0x[0-9a-fA-F]{40}$
      examples:
        - '0xC0519BE562f0De7E32e9A48e50AdecBAde605aAD'
    Verify:
      type: object
      description: 'The public record: no name, no document'
      properties:
        account:
          $ref: '#/components/schemas/Address'
        verified:
          type: boolean
        score:
          $ref: '#/components/schemas/Amount'
        ratioBps:
          $ref: '#/components/schemas/Amount'
        cycles: 58951e20-0fbb-4860-bc4a-22a417a001e5
        defaulted:
          type: boolean
        history:
          type:
            - object
            - 'null'
          description: From the indexer; null when it is down
          properties:
            score:
              type: string
            cycleCount:
              type: integer
            repayCount:
              type: integer
            cyclesOpened:
              type: integer
            defaulted:
              type: boolean
            verifiedAt:
              type:
                - string
                - 'null'
            firstSeenAt:
              type: string
            cycles:
              type: array
              items:
                type: object
                properties:
                  number:
                    type: integer
                  outcome:
                    type: string
                    examples:
                      - Qualified
                  openedAt:
                    type: string
                  closedAt:
                    type:
                      - string
                      - 'null'
                  peakDrawn:
                    type: string
                  totalRepaid:
                    type: string
                  scoreAfter:
                    type:
                      - string
                      - 'null'
                  openTxHash:
                    type: string
                  closeTxHash:
                    type:
                      - string
                      - 'null'
        indexer:
          type: string
          enum:
            - ok
            - unavailable
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          examples:
            - verify your identity first
    Amount:
      type: string
      pattern: ^[0-9]+$
      description: Smallest unit of its currency
      examples:
        - '1000000'

````

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