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

# Get started

> Request access, authenticate, and run your first transaction on the Open Money Stack.

OMS gives you a single API for moving money between fiat and stablecoins. This guide takes you from zero to a working transaction in five steps.

<Steps>
  <Step title="Request access and authenticate">
    OMS is in early access. Start by requesting access from the dashboard.

    <Card title="Request OMS access" icon="envelope" href="https://info.polygon.technology/get-early-access?utm_source=docs&utm_medium=card&utm_campaign=oms_access">
      Submit your details to get sandbox credentials.
    </Card>

    Once approved, open the OMS Dashboard and navigate to **API Keys**. Generate a new key and store the secret immediately, it is shown only once. Keys do not expire by default, support an optional enforced expiration, and can be rotated from the dashboard at any time.

    <Warning>
      Treat your API key secret like a password. If it is ever compromised, revoke the key from the dashboard and generate a new one immediately.
    </Warning>

    You do not send the API key directly on requests. Exchange the key and secret for a short-lived bearer token at `POST /auth/token`, then send that token on every other call.

    <CodeGroup>
      ```bash Sandbox theme={null}
      curl -X POST https://sandbox-api.polygon.technology/v0.10/auth/token \
        -H "Content-Type: application/json" \
        -d '{
          "apiKey": "{api_key}",
          "apiSecret": "{api_secret}"
        }'
      ```

      ```bash Production theme={null}
      curl -X POST https://api.polygon.technology/v0.10/auth/token \
        -H "Content-Type: application/json" \
        -d '{
          "apiKey": "{api_key}",
          "apiSecret": "{api_secret}"
        }'
      ```
    </CodeGroup>

    ```json theme={null}
    {
      "accessToken": "eyJhbGc...",
      "tokenType": "bearer",
      "expiresIn": 3600,
      "expiresAt": "2026-01-15T11:00:00Z"
    }
    ```

    The token is valid for 60 minutes. Send the `accessToken` as a bearer token on every other request:

    ```text theme={null}
    Authorization: Bearer {accessToken}
    ```

    Every mutating request (`POST` and `PATCH`) also requires an `Idempotency-Key` header. Replaying the same key returns the original result instead of re-executing.

    <Note>
      When a request returns `401`, the token has expired. Exchange your key for a fresh one and retry. If `POST /auth/token` returns `429`, the endpoint is rate-limited: back off before retrying using the `Retry-After` header.
    </Note>
  </Step>

  <Step title="Create a customer">
    Every wallet, transaction, and payment route in OMS belongs to a customer record. Create one before anything else. To onboard a customer who can move USD or use cash services, send the full set of identifying fields, not just a name, and request the `endorsements` the customer needs.

    <CodeGroup>
      ```bash Sandbox theme={null}
      curl -X POST https://sandbox-api.polygon.technology/v0.10/customers \
        -H "Authorization: Bearer {accessToken}" \
        -H "Content-Type: application/json" \
        -H "Idempotency-Key: cst-first-customer-001" \
        -d '{
          "type": "individual",
          "firstName": "Jane",
          "lastName": "Smith",
          "email": "jane@example.com",
          "phone": "+12125551234",
          "birthDate": "1990-05-15",
          "nationality": "US",
          "residentialAddress": {
            "line1": "123 Main St",
            "city": "New York",
            "state": "NY",
            "country": "US",
            "zipCode": "10001"
          },
          "identifyingInformation": [
            { "type": "ssn", "issuingCountry": "US", "number": "123-45-6789" }
          ],
          "endorsements": ["basic", "cryptoCustody", "usd"]
        }'
      ```

      ```bash Production theme={null}
      curl -X POST https://api.polygon.technology/v0.10/customers \
        -H "Authorization: Bearer {accessToken}" \
        -H "Content-Type: application/json" \
        -H "Idempotency-Key: cst-first-customer-001" \
        -d '{
          "type": "individual",
          "firstName": "Jane",
          "lastName": "Smith",
          "email": "jane@example.com",
          "phone": "+12125551234",
          "birthDate": "1990-05-15",
          "nationality": "US",
          "residentialAddress": {
            "line1": "123 Main St",
            "city": "New York",
            "state": "NY",
            "country": "US",
            "zipCode": "10001"
          },
          "identifyingInformation": [
            { "type": "ssn", "issuingCountry": "US", "number": "123-45-6789" }
          ],
          "endorsements": ["basic", "cryptoCustody", "usd"]
        }'
      ```
    </CodeGroup>

    ```json theme={null}
    {
      "id": "cst_01H9Xa...",
      "object": "customer",
      "type": "individual",
      "status": "active",
      "endorsements": [
        { "name": "basic", "status": "ACTIVE" },
        { "name": "cryptoCustody", "status": "ACTIVE" },
        { "name": "usd", "status": "PENDING" }
      ],
      "wallets": [],
      "createdAt": "2026-01-15T10:00:00Z"
    }
    ```

    Store the `cst_` ID; you pass it to every wallet, quote, and transaction. Each endorsement tracks its own `status` in SCREAMING\_CASE and must reach `ACTIVE` before its capability unlocks. PII fields (`birthDate`, `residentialAddress`, `ipAddress`, `identifyingInformation`) are write-only: OMS accepts them but never returns them.

    <Warning>
      The API accepts a customer with only `type`, but a customer created without the identifying fields below cannot be provisioned to move fiat. The record is created, yet calls that need a provisioned fiat account (cash-in or a fiat transaction) fail. For USD and cash flows, always provide:

      * A structured `residentialAddress` (the object above, not a free-text string)
      * `phone` in E.164 format
      * `birthDate`
      * A government ID in `identifyingInformation` (for US customers, an `ssn` or `itin`)

      Supply these at creation, or add them later with `PATCH /customers/{customerId}`. Products that never touch fiat rails may not need them. Only `individual` is supported for `type` today.
    </Warning>

    <Note>
      In sandbox, endorsements are auto-approved so you can test without a live KYC integration. Provisioning still reads the identifying fields above, so include them in sandbox too.
    </Note>
  </Step>

  <Step title="Provision a wallet">
    Create a custodial wallet for the customer. The path carries the customer ID; the body names the `asset` and `chain` to hold. OMS derives the on-chain address and manages the keys, with no wallet SDK or user signing.

    <CodeGroup>
      ```bash Sandbox theme={null}
      curl -X POST https://sandbox-api.polygon.technology/v0.10/customers/cst_01H9Xa.../wallets \
        -H "Authorization: Bearer {accessToken}" \
        -H "Content-Type: application/json" \
        -H "Idempotency-Key: wlt-first-wallet-001" \
        -d '{
          "asset": "usdc",
          "chain": "polygon"
        }'
      ```

      ```bash Production theme={null}
      curl -X POST https://api.polygon.technology/v0.10/customers/cst_01H9Xa.../wallets \
        -H "Authorization: Bearer {accessToken}" \
        -H "Content-Type: application/json" \
        -H "Idempotency-Key: wlt-first-wallet-001" \
        -d '{
          "asset": "usdc",
          "chain": "polygon"
        }'
      ```
    </CodeGroup>

    ```json theme={null}
    {
      "id": "wlt_01H9Xb...",
      "object": "wallet",
      "customerId": "cst_01H9Xa...",
      "type": "internal",
      "status": "active",
      "asset": "usdc",
      "chain": "polygon",
      "address": "0xBEEF4a2c891D56e72b67a3f21d0cf94F1D7c5911",
      "blockchainAsset": {
        "protocol": "evm",
        "chainId": "137",
        "tokenId": "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359"
      },
      "createdAt": "2026-01-15T10:01:00Z"
    }
    ```

    The `address` is the on-chain address. The `wlt_` ID is what you pass as the source or destination in quotes and transactions. Read the current balance with `GET /wallets/{walletId}/balance`.
  </Step>

  <Step title="Run your first transaction">
    The cash-in flow is the quickest path for your first run: it needs no external account. The bank transfer flow shows the standard quote-to-transaction pattern for fiat payouts.

    <Tabs>
      <Tab title="Cash-in">
        Let a customer deposit physical cash at a retail location and receive USDC in their wallet.

        <CodeGroup>
          ```bash Sandbox theme={null}
          curl -X POST https://sandbox-api.polygon.technology/v0.10/cash-ins \
            -H "Authorization: Bearer {accessToken}" \
            -H "Content-Type: application/json" \
            -H "Idempotency-Key: ci-first-001" \
            -d '{
              "customerId": "cst_01H9Xa...",
              "cash": {
                "locationId": "loc_01H9Xd...",
                "locationReference": "R1JFRU5ET1QtMjQzNDpsYXQ9..."
              },
              "source": {
                "asset": "usd",
                "indicatedAmount": "100.00"
              },
              "destination": {
                "asset": "usdc",
                "network": "polygon",
                "wallet": { "id": "wlt_01H9Xb..." }
              }
            }'
          ```

          ```bash Production theme={null}
          curl -X POST https://api.polygon.technology/v0.10/cash-ins \
            -H "Authorization: Bearer {accessToken}" \
            -H "Content-Type: application/json" \
            -H "Idempotency-Key: ci-first-001" \
            -d '{
              "customerId": "cst_01H9Xa...",
              "cash": {
                "locationId": "loc_01H9Xd...",
                "locationReference": "R1JFRU5ET1QtMjQzNDpsYXQ9..."
              },
              "source": {
                "asset": "usd",
                "indicatedAmount": "100.00"
              },
              "destination": {
                "asset": "usdc",
                "network": "polygon",
                "wallet": { "id": "wlt_01H9Xb..." }
              }
            }'
          ```
        </CodeGroup>

        OMS returns a `depositInstructions.code` valid for one hour. The customer presents the code at the retail location, hands over cash, and USDC lands in their wallet automatically.

        See the [Cash-in guide](/api-reference/guide-cash-in) for the full flow.
      </Tab>

      <Tab title="Bank transfer">
        Pay out from a wallet to a bank account. Register the destination bank account with `POST /external-accounts`, then quote and execute against the returned `ext_bankUs_` ID. A quote's source is always an OMS wallet or a card.

        <Note>
          Bank payouts require the customer's `usd` endorsement to be `ACTIVE`.
        </Note>

        **Register the destination bank account:**

        The body carries an `owner`, a `type`, and exactly one per-type object matching the type (here `bankUs`).

        <CodeGroup>
          ```bash Sandbox theme={null}
          curl -X POST https://sandbox-api.polygon.technology/v0.10/external-accounts \
            -H "Authorization: Bearer {accessToken}" \
            -H "Content-Type: application/json" \
            -H "Idempotency-Key: ext-bank-first-001" \
            -d '{
              "owner": { "kind": "customer", "customerId": "cst_01H9Xa..." },
              "type": "bankUs",
              "bankUs": {
                "accountNumber": "123456789012",
                "routingNumber": "021000021",
                "accountType": "checking",
                "bankName": "Chase"
              }
            }'
          ```

          ```bash Production theme={null}
          curl -X POST https://api.polygon.technology/v0.10/external-accounts \
            -H "Authorization: Bearer {accessToken}" \
            -H "Content-Type: application/json" \
            -H "Idempotency-Key: ext-bank-first-001" \
            -d '{
              "owner": { "kind": "customer", "customerId": "cst_01H9Xa..." },
              "type": "bankUs",
              "bankUs": {
                "accountNumber": "123456789012",
                "routingNumber": "021000021",
                "accountType": "checking",
                "bankName": "Chase"
              }
            }'
          ```
        </CodeGroup>

        The response returns the `ext_bankUs_` ID. The account starts `pending` and flips to `active` once provisioning completes. The full account number is write-only; reads expose only `bankUs.accountNumberLast4`.

        **Pay out from a wallet to a bank account (USDC to fiat):**

        <CodeGroup>
          ```bash Sandbox theme={null}
          # Step 1: create a quote against the registered bank account
          curl -X POST https://sandbox-api.polygon.technology/v0.10/quotes \
            -H "Authorization: Bearer {accessToken}" \
            -H "Content-Type: application/json" \
            -H "Idempotency-Key: qt-bank-out-001" \
            -d '{
              "customerId": "cst_01H9Xa...",
              "source": {
                "type": "walletOms",
                "details": { "id": "wlt_01H9Xb...", "asset": "usdc", "network": "polygon" },
                "amount": "100.00"
              },
              "destination": {
                "type": "bankUs",
                "details": {
                  "id": "ext_bankUs_01H9X...",
                  "asset": "usd",
                  "network": "ach",
                  "accountHolder": "customer"
                }
              }
            }'

          # Step 2: execute
          curl -X POST https://sandbox-api.polygon.technology/v0.10/transactions \
            -H "Authorization: Bearer {accessToken}" \
            -H "Content-Type: application/json" \
            -H "Idempotency-Key: txn-bank-out-001" \
            -d '{ "quoteId": "qt_01H9Xq..." }'
          ```

          ```bash Production theme={null}
          # Step 1: create a quote against the registered bank account
          curl -X POST https://api.polygon.technology/v0.10/quotes \
            -H "Authorization: Bearer {accessToken}" \
            -H "Content-Type: application/json" \
            -H "Idempotency-Key: qt-bank-out-001" \
            -d '{
              "customerId": "cst_01H9Xa...",
              "source": {
                "type": "walletOms",
                "details": { "id": "wlt_01H9Xb...", "asset": "usdc", "network": "polygon" },
                "amount": "100.00"
              },
              "destination": {
                "type": "bankUs",
                "details": {
                  "id": "ext_bankUs_01H9X...",
                  "asset": "usd",
                  "network": "ach",
                  "accountHolder": "customer"
                }
              }
            }'

          # Step 2: execute
          curl -X POST https://api.polygon.technology/v0.10/transactions \
            -H "Authorization: Bearer {accessToken}" \
            -H "Content-Type: application/json" \
            -H "Idempotency-Key: txn-bank-out-001" \
            -d '{ "quoteId": "qt_01H9Xq..." }'
          ```
        </CodeGroup>

        See the [Bank transfers guide](/api-reference/guide-bank-transfers) for both directions and ACH-specific flows.
      </Tab>
    </Tabs>
  </Step>

  <Step title="Configure webhooks">
    OMS fires webhooks at every meaningful state change. You can poll `GET /transactions/{transactionId}` instead, but webhooks are strongly recommended for production.

    Register an endpoint with `POST /webhooks` (or in the OMS Dashboard under **Webhooks**). OMS returns a signing secret with the `whsec_` prefix once in the create response, so store it immediately.

    <CodeGroup>
      ```bash Sandbox theme={null}
      curl -X POST https://sandbox-api.polygon.technology/v0.10/webhooks \
        -H "Authorization: Bearer {accessToken}" \
        -H "Content-Type: application/json" \
        -H "Idempotency-Key: whk-first-001" \
        -d '{
          "url": "https://api.yourapp.com/webhooks/oms",
          "events": []
        }'
      ```

      ```bash Production theme={null}
      curl -X POST https://api.polygon.technology/v0.10/webhooks \
        -H "Authorization: Bearer {accessToken}" \
        -H "Content-Type: application/json" \
        -H "Idempotency-Key: whk-first-001" \
        -d '{
          "url": "https://api.yourapp.com/webhooks/oms",
          "events": []
        }'
      ```
    </CodeGroup>

    Pass an empty `events` array (or `["*"]` / `["ALL"]`) to subscribe to every event, or list specific event names to filter. Manage endpoints with `GET /webhooks`, `PATCH /webhooks/{id}` (set `enabled: false` to pause), and `DELETE /webhooks/{id}`. Every event carries the full resource object under `payload`, so you rarely need to poll for additional data.

    Some events you will see early on:

    | Event                                | Fires when                                                          |
    | ------------------------------------ | ------------------------------------------------------------------- |
    | `transaction.fiatToCrypto.completed` | A fiat-funded transaction delivered crypto to the destination       |
    | `transaction.cryptoToFiat.completed` | A payout from a wallet delivered fiat to the destination            |
    | `cashIn.completed`                   | A cash deposit was received and converted                           |
    | `externalAccount.verified`           | A registered bank account passed validation and is usable on quotes |

    See [Webhook events](/api-reference/webhook-events) for the envelope and the full catalog.

    <Tip>
      Verify every webhook with the `Webhook-Signature` header before acting on it. The signature is an HMAC-SHA256 keyed with your signing secret; compare it in constant time and reject events with a stale timestamp.
    </Tip>
  </Step>
</Steps>

***

## What's next

<CardGroup cols={2}>
  <Card title="Cash-in" icon="coins" href="/api-reference/guide-cash-in">
    Full walkthrough of the cash deposit flow, including deposit code generation and retail location selection.
  </Card>

  <Card title="Bank transfers" icon="building-columns" href="/api-reference/guide-bank-transfers">
    Move money between bank accounts and wallets in both directions using ACH and card rails.
  </Card>

  <Card title="Payments overview" icon="arrow-right-arrow-left" href="/payments/overview">
    How OMS handles payments, stablecoin settlement, and compliant fiat access end to end.
  </Card>

  <Card title="API reference" icon="code" href="/api-reference/overview">
    Complete endpoint reference for all OMS resources.
  </Card>
</CardGroup>
