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

# API introduction

> Base URL, authentication, the response envelope, conventions, and everything global to the AroPay API v1.

The AroPay API is a JSON-over-HTTPS API. Every dashboard feature is built on
it, so anything you see in the UI can be automated with the same calls.

## Base URL

```text theme={null}
https://aropay.aro.media/api/v1
```

All paths in this reference are relative to the base URL. On-chain operations
execute on **Ethereum Sepolia** (chain ID `11155111`), the current MVP sandbox
environment; a Mainnet deployment will follow.

## Authentication

Protected endpoints accept either credential; the `Authorization` header wins
when both are present:

<CodeGroup>
  ```bash API key (integrations) theme={null}
  curl "$BASE/wallets" \
    -H "Authorization: Bearer aro_sk_…"
  ```

  ```bash Session cookie (browser) theme={null}
  # Cookie jar captured by POST /auth/login
  curl "$BASE/wallets" -b cookies.txt
  ```
</CodeGroup>

A handful of sensitive endpoints are **session-only** and return
`403 session_required` when called with an API key: password change, TOTP and
passkey management, key create/revoke, and wallet export. Each is labeled in
its endpoint page. Background in
[Authentication](/security/authentication).

## The response envelope

Every endpoint (except the flat [Sandbox](/api-reference/introduction#sandbox-endpoints)
probes) wraps its result:

<CodeGroup>
  ```json Success theme={null}
  {
    "ok": true,
    "data": { "wallet": { "id": "ckwlt0001…", "…": "…" } }
  }
  ```

  ```json Failure theme={null}
  {
    "ok": false,
    "error": {
      "code": "validation_error",
      "message": "Request validation failed.",
      "details": [{ "path": "amount", "message": "Required" }]
    }
  }
  ```
</CodeGroup>

Branch on HTTP status for class of failure and on `error.code` for specifics;
the full catalog is in [Errors](/api-reference/errors).

## Conventions

<AccordionGroup>
  <Accordion title="Write bodies must be application/json" icon="brackets-curly" iconType="duotone">
    POST/PATCH/DELETE requests with bodies require
    `Content-Type: application/json`; anything else is rejected with
    `415 unsupported_media_type`. (This doubles as CSRF protection.)
  </Accordion>

  <Accordion title="Amounts are decimal strings" icon="calculator" iconType="duotone">
    Human units, string-typed: `"125.50"` means 125.5 tokens. No wei, no base
    units, no floats. The one exception: `GET /gas` additionally reports `wei`
    strings for precision-sensitive tooling.
  </Accordion>

  <Accordion title="IDs are opaque strings" icon="id-badge" iconType="duotone">
    Wallets, transactions, keys, and passkeys use cuid-style IDs. IDs from
    another account read as `404 not_found`; ownership is enforced on every
    access.
  </Accordion>

  <Accordion title="Timestamps are ISO 8601 UTC" icon="clock" iconType="duotone">
    e.g. `"2026-08-13T09:30:00.000Z"`.
  </Accordion>

  <Accordion title="Pagination is page-based" icon="list-ol" iconType="duotone">
    `GET /transactions` takes `page` (default 1) and `pageSize` (default 20,
    max 100) and returns `items`, `page`, `pageSize`, `total`.
  </Accordion>

  <Accordion title="Money movement blocks up to ~90 s" icon="hourglass-half" iconType="duotone">
    `/fund`, `/mint`, `/transfer`, `/redeem` wait for the on-chain receipt and
    return `201` with the transaction. If the receipt isn't in yet, the
    transaction returns as `PENDING`; poll `GET /transactions/{id}` until
    terminal. Reads also advance in-flight transactions (lazy reconciliation).
  </Accordion>
</AccordionGroup>

## Rate limits

30 writes and 120 reads per minute per principal; 10 login attempts per 15
minutes per IP. Exceeding a limit returns `429 rate_limited`. Details and
patterns in [Rate limits](/security/rate-limits).

## Sandbox endpoints

`GET /sandbox` (status probe) and `POST /sandbox` (JSON echo) are unauthenticated
connectivity checks with a **flat** response shape (no `data` envelope):

```json theme={null}
{ "ok": true, "service": "aropay-sandbox", "version": "v1", "environment": "sandbox", "timestamp": "2026-08-13T09:00:00.000Z" }
```

Use them to verify connectivity and JSON handling before wiring auth.

## Try it here

Every endpoint page in this reference has an interactive playground:
authenticate with your `aro_sk_…` key and requests run against the live
sandbox. A good first call is `GET /auth/session` (under **Auth** in the
sidebar): it echoes back who you are and which credential authenticated.
