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

# AUSD to IDR in a bank account

> The user signs an ERC-3009 transfer of `value` AUSD **to the treasury** `0xcf330A7E5D4eae35250f00B4af96eBcf38347Df1`, valid for at least 5 more minutes. The backend takes the AUSD, then Xendit pays the IDR (at least Rp 10,000) to the bank. The answer comes at once; the payout shows in `/me/activity` `inFlight` until done. `channelCode` is Xendit's, such as `ID_BCA`, `ID_BRI`, `ID_MANDIRI`, `ID_BNI`.



## OpenAPI

````yaml https://api.matocard.xyz/openapi.json post /cashouts
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:
  /cashouts:
    post:
      tags:
        - Money
      summary: AUSD to IDR in a bank account
      description: >-
        The user signs an ERC-3009 transfer of `value` AUSD **to the treasury**
        `0xcf330A7E5D4eae35250f00B4af96eBcf38347Df1`, valid for at least 5 more
        minutes. The backend takes the AUSD, then Xendit pays the IDR (at least
        Rp 10,000) to the bank. The answer comes at once; the payout shows in
        `/me/activity` `inFlight` until done. `channelCode` is Xendit's, such as
        `ID_BCA`, `ID_BRI`, `ID_MANDIRI`, `ID_BNI`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - quoteId
                - authorization
                - bank
              properties:
                quoteId:
                  type: string
                  format: uuid
                  description: A `USD/IDR` quote
                authorization:
                  $ref: '#/components/schemas/Authorization'
                bank:
                  type: object
                  required:
                    - channelCode
                    - accountNumber
                    - accountHolderName
                  properties:
                    channelCode:
                      type: string
                      examples:
                        - ID_BCA
                    accountNumber:
                      type: string
                      pattern: ^[0-9]{6,20}$
                    accountHolderName:
                      type: string
      responses:
        '200':
          description: Accepted
          content:
            application/json:
              schema:
                type: object
                properties:
                  payoutId:
                    type: string
                    format: uuid
                  ausd:
                    $ref: '#/components/schemas/Amount'
                  fiat:
                    $ref: '#/components/schemas/Amount'
                    description: IDR paid out
              example:
                payoutId: 9fd1d0dd-f236-4c9d-90c2-db454b626502
                ausd: '600000'
                fiat: '10770'
        '400':
          $ref: '#/components/responses/Bad'
        '401':
          $ref: '#/components/responses/SignIn'
      security:
        - session: []
components:
  schemas:
    Authorization:
      type: object
      description: >-
        An ERC-3009 TransferWithAuthorization the sender signed (EIP-712, domain
        at the top). Numbers as decimal strings.
      required:
        - from
        - to
        - value
        - validAfter
        - validBefore
        - nonce
        - signature
      properties:
        from:
          $ref: '#/components/schemas/Address'
        to:
          $ref: '#/components/schemas/Address'
        value:
          $ref: '#/components/schemas/Amount'
        validAfter:
          type: string
          examples:
            - '0'
        validBefore:
          type: string
          description: Unix time
          examples:
            - '1791051600'
        nonce:
          type: string
          pattern: ^0x[0-9a-fA-F]{64}$
        signature:
          type: string
          pattern: ^0x[0-9a-fA-F]+$
    Amount:
      type: string
      pattern: ^[0-9]+$
      description: Smallest unit of its currency
      examples:
        - '1000000'
    Address:
      type: string
      pattern: ^0x[0-9a-fA-F]{40}$
      examples:
        - '0xC0519BE562f0De7E32e9A48e50AdecBAde605aAD'
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: string
          examples:
            - verify your identity first
  responses:
    Bad:
      description: The request was wrong; the message says why
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    SignIn:
      description: 'No session, a bad signature, or an expired one: sign again'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    session:
      type: apiKey
      in: header
      name: Authorization
      description: '`Matocard <wallet>.<until>.<signature>`, see the description at the top'

````

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