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

# Accept privacy terms

> **Session-only.** Accept the current data-privacy terms. Echo the
`version` and `contentHash` from `GET /me/terms`, so a page still
showing an older text cannot accept it; a stale pair returns
`409 terms_version_mismatch`. Idempotent: accepting again keeps the
first acceptance. The platform records the version, content hash,
time, IP address and user agent as the consent record. Returns the
same shape as `GET /me/terms`.

Consent is given by a person, so API keys get `403 session_required`;
an API-key integration needs someone to accept once in the dashboard.




## OpenAPI

````yaml /api-reference/openapi.yaml post /me/terms
openapi: 3.1.0
info:
  title: AroPay API
  version: 1.0.0
  description: |
    The AroPay API for orchestrating sealed, private payments on public
    ledgers, built on the Aro Confidential Rails (Zama Protocol FHE). Two
    environments run the same API: Production on Ethereum Mainnet
    (`aropay.aro.media`, real funds) and the Sandbox on Sepolia
    (`dev.aropay.aro.media`, test funds and a faucet). Integrations built
    against the sandbox carry over unchanged; the faucet (`POST /fund`) is
    sandbox-only and returns 404 on production.

    Every response (except the flat Sandbox probes)
    uses the shared envelope: `{ "ok": true, "data": … }` on success and
    `{ "ok": false, "error": { "code", "message", "details?" } }` on failure.

    Amounts are decimal strings in human units (e.g. `"125.50"`). Write
    requests must send `Content-Type: application/json`.
  contact:
    name: Aro Media
    url: https://aro.media
servers:
  - url: https://aropay.aro.media/api/v1
    description: Production (Ethereum Mainnet)
  - url: https://dev.aropay.aro.media/api/v1
    description: Sandbox (Sepolia)
  - url: http://aropay.localhost:3000/api/v1
    description: Local development
security:
  - apiKeyAuth: []
  - sessionCookie: []
tags:
  - name: Auth
    description: Password, TOTP, and passkey login; session inspection and logout.
  - name: Profile & security
    description: >-
      Profile, password, privacy terms, two-factor authentication, and passkey
      management.
    x-group: Profile & security
  - name: API keys
    description: Programmatic credentials. Creation and revocation are session-only.
  - name: Wallets
    description: Custodial and external (watch-only) wallets.
  - name: Balances
    description: Balance triples and lightweight gas reads.
  - name: Money movement
    description: |
      Faucet funding, minting, transfers, and redemptions. All four are
      asynchronous: the request is validated and recorded, the response is
      `201` with the transaction in status `QUEUED` (`txHash: null`), and a
      background worker executes it. Poll `GET /transactions/{id}` until
      `status` is `CONFIRMED`, `SETTLED`, or `FAILED`. Execution failures
      surface as status `FAILED` with `errorCode` on the transaction, never
      as an HTTP error on the POST. All four return `403 terms_not_accepted`
      until the account has accepted the current data-privacy terms
      (`GET /me/terms`), for API keys as well as sessions.
  - name: Aro Mail
    description: >-
      Letters of value: escrow cAROUSD, print or mail through Lob, and let the
      recipient claim by QR or code.
  - name: Transactions
    description: >-
      History, single-transaction reads (pure database reads), and notarized
      receipts.
  - name: Sandbox
    description: Unauthenticated status and echo probes with a flat response shape.
paths:
  /me/terms:
    post:
      tags:
        - Profile & security
      summary: Accept privacy terms
      description: |
        **Session-only.** Accept the current data-privacy terms. Echo the
        `version` and `contentHash` from `GET /me/terms`, so a page still
        showing an older text cannot accept it; a stale pair returns
        `409 terms_version_mismatch`. Idempotent: accepting again keeps the
        first acceptance. The platform records the version, content hash,
        time, IP address and user agent as the consent record. Returns the
        same shape as `GET /me/terms`.

        Consent is given by a person, so API keys get `403 session_required`;
        an API-key integration needs someone to accept once in the dashboard.
      operationId: acceptPrivacyTerms
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - version
                - contentHash
              properties:
                version:
                  type: string
                  minLength: 1
                  maxLength: 40
                  description: '`terms.current.version` from `GET /me/terms`.'
                contentHash:
                  type: string
                  pattern: ^[0-9a-f]{64}$
                  description: >-
                    `terms.current.contentHash` from `GET /me/terms` (sha256,
                    lowercase hex).
            example:
              version: '1'
              contentHash: b0bbc4565026cd60a601bb366b4a2da8dfdbe96492a3b9cb3a46e3709112f3cd
      responses:
        '200':
          description: Accepted (or already accepted); `required` is now `false`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TermsEnvelope'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/SessionRequired'
        '409':
          description: |
            `version` or `contentHash` is not the current terms
            (`terms_version_mismatch`): they changed after the client fetched
            them. `details` carries `currentVersion` and `contentHash`; fetch
            `GET /me/terms` again and show the new text before accepting.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                ok: false
                error:
                  code: terms_version_mismatch
                  message: >-
                    These terms have been updated. Reload them and review the
                    current version before accepting.
                  details:
                    currentVersion: '2'
                    contentHash: >-
                      eb65dc168367ab14e68105fbd9146313dc927ca99af13507fd8e1c7de6156427
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - sessionCookie: []
components:
  schemas:
    TermsEnvelope:
      type: object
      required:
        - ok
        - data
      properties:
        ok:
          const: true
        data:
          type: object
          required:
            - terms
          properties:
            terms:
              $ref: '#/components/schemas/TermsState'
    ErrorResponse:
      type: object
      description: The shared failure envelope.
      required:
        - ok
        - error
      properties:
        ok:
          const: false
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Machine-readable error code; match on this, not `message`.
            message:
              type: string
            details:
              description: Structured context, e.g. per-field validation issues.
    TermsState:
      type: object
      description: >-
        The current data-privacy terms and whether this account has accepted
        them.
      required:
        - current
        - accepted
        - required
      properties:
        current:
          type: object
          required:
            - version
            - effectiveDate
            - contentHash
            - url
            - document
          properties:
            version:
              type: string
              description: Current terms version; send it back to `POST /me/terms`.
            effectiveDate:
              type: string
              format: date
            contentHash:
              type: string
              pattern: ^[0-9a-f]{64}$
              description: sha256 (hex) of `document`; send it back to `POST /me/terms`.
            url:
              type: string
              description: Path of the public terms page on the AroPay host.
              examples:
                - /terms
            document:
              $ref: '#/components/schemas/TermsDocument'
        accepted:
          description: >-
            Acceptance of the **current** version; `null` if it has not been
            accepted (including after a new version is published).
          oneOf:
            - $ref: '#/components/schemas/TermsAcceptance'
            - type: 'null'
        required:
          type: boolean
          description: >-
            `true` while fund, mint, transfer, redeem and Aro Mail create, mail
            and claim return `403 terms_not_accepted`.
    TermsDocument:
      type: object
      description: >-
        The data-privacy terms as published; `contentHash` is the sha256 of this
        object.
      required:
        - version
        - effectiveDate
        - title
        - keyPoints
        - sections
      properties:
        version:
          type: string
          examples:
            - '1'
        effectiveDate:
          type: string
          format: date
          description: Date (`YYYY-MM-DD`) this version takes effect.
        title:
          type: string
          examples:
            - AroPay Sandbox Data Privacy Terms
        keyPoints:
          type: array
          items:
            type: string
          description: The points a reader must not miss, shown above the full text.
        sections:
          type: array
          items:
            type: object
            required:
              - heading
            properties:
              heading:
                type: string
              paragraphs:
                type: array
                items:
                  type: string
              bullets:
                type: array
                items:
                  type: string
    TermsAcceptance:
      type: object
      description: This account's acceptance of the current terms version.
      required:
        - version
        - acceptedAt
      properties:
        version:
          type: string
        acceptedAt:
          type: string
          format: date-time
  responses:
    BadRequest:
      description: Malformed body or failed validation.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            ok: false
            error:
              code: validation_error
              message: Request validation failed.
              details:
                - path: amount
                  message: Required
    Unauthorized:
      description: Missing or invalid credential.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            ok: false
            error:
              code: invalid_api_key
              message: Invalid API key.
    SessionRequired:
      description: Session-only endpoint called with an API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            ok: false
            error:
              code: session_required
              message: This action requires a browser session.
    RateLimited:
      description: Rate limit exceeded.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            ok: false
            error:
              code: rate_limited
              message: Too many requests. Try again shortly.
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            ok: false
            error:
              code: internal_error
              message: An unexpected error occurred.
  securitySchemes:
    apiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: aro_sk_…
      description: |
        AroPay API key, sent as `Authorization: Bearer aro_sk_…`. Created in
        the dashboard under Settings → API keys. Takes precedence over a
        session cookie when both are present.
      x-default: aro_sk_your_key_here
    sessionCookie:
      type: apiKey
      in: cookie
      name: aropay_session
      description: |
        Browser session cookie minted by `POST /auth/login` (or passkey
        login). httpOnly, `SameSite=Lax`, 24 h TTL. Endpoints marked
        **Session-only** accept only this credential and return
        `403 session_required` for API keys.

````

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