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

> ## Agent Instructions
> Before reading these docs, install the relevant Circle Skill to get pre-loaded context — skills are LLM-optimized and cover architecture decisions, correct flows, and common pitfalls. In Claude Code: run /plugin marketplace add circlefin/skills then /plugin install circle-skills@circle. With Vercel Skills CLI: run npx skills add circlefin/skills. Available skills: use-usdc https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-usdc/SKILL.md (balances, transfers, approvals on EVM and Solana); EURC has no skill — see https://developers.circle.com/stablecoins/what-is-eurc.md; bridge-stablecoin https://github.com/circlefin/skills/blob/master/plugins/circle/skills/bridge-stablecoin/SKILL.md (crosschain transfers via CCTP, USDC, EURC, and third-party assets); use-arc https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-arc/SKILL.md (Arc chain config, contract deployment, USDC bridging — Arc docs: https://docs.arc.io/llms.txt); use-circle-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-circle-wallets/SKILL.md (choose wallet type); use-developer-controlled-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-developer-controlled-wallets/SKILL.md (custodial wallets for payouts and treasury); use-user-controlled-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-user-controlled-wallets/SKILL.md (embedded wallets with Web2 login); use-modular-wallets https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-modular-wallets/SKILL.md (smart contract wallets with passkeys and ERC-4337); use-gateway https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-gateway/SKILL.md (unified USDC balance, nanopayments); use-smart-contract-platform https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-smart-contract-platform/SKILL.md (deploy, interact, monitor contracts). Pair any skill with the Circle MCP server for live SDK signatures, contract addresses, and chain IDs: {"mcpServers":{"circle":{"url":"https://api.circle.com/v1/codegen/mcp"}}}.
> Read the product overview first. Each product has an overview explaining when and why to use it. Read it before quickstarts.
> Pick the right wallet type. Developer-controlled (you hold keys), user-controlled (end user holds keys via PIN/social login), or modular (smart contract wallets with passkeys). See https://developers.circle.com/wallets.md.
> Use CCTP V2 for crosschain transfers. CCTP natively transfers USDC and EURC via burn-and-mint, and supports permissionless wrapping of third-party assets via lock-and-mint. V1 is legacy; always use V2 unless V1 is specified or the chain requires it (Noble, Sui, and Aptos still require V1). Migration guide: https://developers.circle.com/cctp/migration-from-v1-to-v2.md.
> Use Bridge Kit for frontend bridging. Wraps CCTP with a simpler SDK for user-facing apps. Use CCTP directly for backend transfers.
> Gas Station vs Paymaster. Gas Station sponsors gas for Circle Wallet transactions. Paymaster lets users pay gas in USDC. Different use cases — read both overviews.
> Gateway Nanopayments for sub-cent payments. Gasless USDC micropayments down to $0.000001 via x402 and batched settlement. For pay-per-request APIs, AI agent payments, streaming.
> Look up USDC addresses per chain. Never hardcode — use https://developers.circle.com/stablecoins/usdc-contract-addresses.md.
> Prefer SDKs over raw API calls. Node.js and Python SDKs handle auth, retries, and errors.
> API key required. Bearer token in Authorization header. Testnet and mainnet use separate keys and may use different base URLs depending on the product.
> Set up webhooks when available. Most operations are async. Webhooks deliver transaction confirmations and state changes.
> When calling list endpoints, paginate using pageSize and pageAfter until no nextPageAfter cursor is returned—stopping at the first page silently misses records.
> Building an AI agent? Start with the Agent Stack—Circle CLI, agent wallets, and nanopayments built for autonomous use cases: https://developers.circle.com/agent-stack.md.

# How-to: Set up mTLS authentication

> Configure mutual TLS authentication for Circle Mint API calls using a client certificate issued by Circle and an API key.

This guide walks you through configuring mutual TLS (mTLS) for Circle Mint API
calls by pairing a client certificate issued by Circle with a new API key. You
generate a key pair and certificate signing request (CSR) locally, submit the
CSR to Circle, and Circle issues your signed certificate. After completing these
steps, your client presents the certificate during the TLS handshake and an API
key in the HTTP header on every request.

<Note>
  Entities operating in an EU/EEA member state under the Markets in
  Crypto-Assets (MiCA) regulation must use mTLS. Any other Circle Mint customer
  with an active API key can opt in to mTLS for extra security. Until Circle
  enables mTLS on your entity, standard API key authentication continues to work
  with no changes.
</Note>

## Prerequisites

Before you begin, ensure that you've:

* Contacted [Circle Support](https://support.circle.com) or your Circle account
  manager to request that Circle enable mTLS on your entity.
* Installed OpenSSL 1.1.1 or later on your machine for key pair and CSR
  operations.
* Configured access to the [Mint Console](https://app.circle.com) with
  multi-factor authentication (MFA).

For background on mTLS, see
[How mTLS authentication works](/circle-mint/mtls-authentication).

## Steps

<Steps>
  <Step title="Generate a key pair">
    Generate an Elliptic Curve Digital Signature Algorithm (ECDSA) P-256 key
    pair. Circle accepts only ECDSA P-256 keys. RSA keys and other curves are
    rejected.

    ```bash theme={null}
    openssl ecparam -genkey -name prime256v1 -noout -out client-key.pem
    ```

    <Warning>
      Keep your private key (`client-key.pem`) secure and never share it with
      Circle or any third party. Only the CSR, which contains your public key,
      is submitted.
    </Warning>
  </Step>

  <Step title="Generate a CSR">
    Generate a PKCS#10 CSR from your key pair:

    ```bash theme={null}
    openssl req -new -key client-key.pem -out client.csr \
      -subj "/CN=<Your Organization Name>/O=<Your Organization>"
    ```

    Replace `<Your Organization Name>` and `<Your Organization>` with your
    entity's legal name. These values help Circle identify your request. Circle
    assigns the final certificate fields during issuance.
  </Step>

  <Step title="Verify the CSR">
    Before submitting, confirm the CSR uses the correct key type:

    ```bash theme={null}
    openssl req -in client.csr -noout -text
    ```

    The output must show a public key algorithm of `id-ecPublicKey` and an ASN1
    OID of `prime256v1`.
  </Step>

  <Step title="Submit your CSR to Circle">
    Provide the following to [Circle Support](https://support.circle.com) or
    your Circle account manager:

    * Your entity ID, found in the Mint Console under **Settings**.
    * Your CSR file (`client.csr`).
    * A request to enable mTLS on your entity.

    Circle validates your CSR and issues a signed client certificate from its
    private certificate authority (CA).
  </Step>

  <Step title="Receive and verify your signed certificate">
    Circle delivers a single file, `client-fullchain.pem`, through a secure,
    out-of-band channel. It contains your signed client certificate, valid for
    365 days, followed by the CA certificate chain.

    Confirm that the issued certificate matches your private key by comparing
    the public key hashes:

    ```bash theme={null}
    openssl ec -in client-key.pem -pubout 2>/dev/null | openssl sha256
    openssl x509 -in client-fullchain.pem -pubkey -noout 2>/dev/null | openssl sha256
    ```

    Both commands must return the same SHA-256 hash. If they differ, the
    certificate and key do not form a valid pair.
  </Step>

  <Step title="Generate a new API key">
    When Circle enables mTLS on your entity, all existing API keys are revoked
    immediately. You must generate a new key before you can make API calls.

    1. Sign in to the [Mint Console](https://app.circle.com).
    2. Complete the MFA challenge. MFA is required for all API key operations on
       mTLS-enabled entities.
    3. Generate a new API key and store it securely.

    <Note>
      API keys on mTLS-enabled entities have a maximum lifetime of 180 days.
      Plan to rotate your key before it expires. See
      [How-to: Rotate an mTLS API key](/circle-mint/rotate-mtls-api-key) for the
      rotation procedure.
    </Note>
  </Step>

  <Step title="Make an authenticated API call">
    Call the hostname that matches how you enabled mTLS:

    * **MiCA-regulated**: Use the regional EU hostname `api-eu.circle.com` for
      all API traffic. Requests sent to `api.circle.com` are rejected.
    * **Optional (non-MiCA)**: Continue to use the standard hostname
      `api.circle.com`. Your endpoint URLs are unchanged.

    The examples in this step use `api-eu.circle.com`. If you enabled mTLS
    optionally, substitute `api.circle.com`.

    Combine your client certificate and API key in a single request. The
    following example retrieves your account balances:

    ```bash theme={null}
    curl --cert /path/to/client-fullchain.pem \
         --key /path/to/client-key.pem \
         --request GET \
         --url https://api-eu.circle.com/v1/businessAccount/balances \
         --header "Authorization: Bearer ${YOUR_API_KEY}"
    ```

    To confirm that the TLS handshake is succeeding and that TLS 1.3 is in use,
    add the `-v` (verbose) flag:

    ```bash theme={null}
    curl -v --cert /path/to/client-fullchain.pem \
         --key /path/to/client-key.pem \
         --request GET \
         --url https://api-eu.circle.com/v1/businessAccount/balances \
         --header "Authorization: Bearer ${YOUR_API_KEY}"
    ```

    Look for `SSL connection using TLSv1.3` in the verbose output. Circle
    supports TLS 1.2 and TLS 1.3, but TLS 1.3 is recommended.
  </Step>

  <Step title="Validate Circle's server certificate">
    Complete the two-way trust relationship by validating the server certificate
    Circle presents during the handshake. How you validate it depends on why you
    enabled mTLS.

    If you enabled mTLS **under MiCA**, Circle presents a Qualified Website
    Authentication Certificate (QWAC) at `api-eu.circle.com`. Choose one of the
    following approaches to validate it.

    **Option A: Use a payment aggregator (recommended)**

    Delegate certificate validation to a payment aggregator. The aggregator
    handles trust chain verification, revocation checks, and PSD2 compliance
    validation on your behalf. This approach reduces integration complexity and
    ongoing maintenance.

    **Option B: Validate directly against EU Trusted Lists**

    If you validate Circle's server certificate directly, your implementation
    must:

    1. **Verify the certificate chain** against the root certificate authorities
       (CAs) published on the
       [EU Trusted Lists](https://eidas.ec.europa.eu/efda/tl-browser/).
    2. **Confirm PSD2 QcStatements** are present in the certificate. These
       statements attest that the certificate is a QWAC issued for PSD2
       purposes.
    3. **Check OCSP revocation status** to ensure the certificate has not been
       revoked.
    4. **Verify the Organization Identifier and NCA** in the certificate match
       Circle's registration details.

    If you enabled mTLS **optionally (non-MiCA)**, Circle presents its standard
    server certificate at `api.circle.com`. Validate it the same way you
    validate any HTTPS connection, using the CA certificate chain contained in
    `client-fullchain.pem`. Neither QWAC option applies to you.
  </Step>
</Steps>

## Troubleshooting

The following table lists common errors and their causes.

| Error | Cause | Resolution |
| - | - | - |
| `401` "Invalid credentials" | The API key is invalid, expired, or was revoked when mTLS was enabled. | Generate a new API key from the [Mint Console](https://app.circle.com) with MFA. |
| `403` "Valid mTLS client certificate required" | No client certificate was presented, or the certificate does not match the entity. | Verify that you pass `--cert` and `--key` in your request and that you use the certificate Circle issued for your entity. |
| TLS handshake failure | The certificate and private key do not match, the certificate format is unsupported, or the certificate is expired. | Compare the certificate and key public key hashes to verify the cert/key pair, as shown when you received your certificate. Confirm the certificate has not expired. |
| Connection rejected or timeout (MiCA) | The request was sent to `api.circle.com` instead of the regional EU hostname. | If you enabled mTLS under MiCA, update your integration to call `api-eu.circle.com` for every endpoint. |
