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

# Production Configuration

Use this guide to move beyond the [seller quickstart](/x402/seller/quickstart) defaults and
configure your x402 server for production. Choose the sections relevant to your deployment.

## Use CDP with an existing x402 server

<Tabs>
  <Tab title="TypeScript">
    Already have an x402 server? Add `createCdpFacilitatorClient()` for CDP settlement without
    migrating to `createX402Server`. It uses your CDP API key and secret.

    ```typescript theme={null}
    import { createCdpFacilitatorClient } from "@coinbase/cdp-sdk/x402";
    import { x402ResourceServer } from "@x402/core/server";
    import { ExactEvmScheme } from "@x402/evm/exact/server";

    const facilitator = createCdpFacilitatorClient();

    const server = new x402ResourceServer(facilitator).register(
      "eip155:8453",
      new ExactEvmScheme(),
    );
    ```

    This works with `x402HTTPResourceServer` and `x402MCPResourceServer`. See
    [`server.ts`](https://github.com/coinbase/cdp-sdk/blob/main/examples/typescript/x402/servers/express/server.ts)
    for a runnable example.
  </Tab>

  <Tab title="Python">
    Python servers can replace their existing facilitator configuration with
    `create_facilitator_config` from `cdp.x402`. The
    [Python seller setup](/x402/seller/quickstart#2-price-a-route) shows how to pass it to
    `HTTPFacilitatorClient`.
  </Tab>
</Tabs>

## Choose your environment

`createX402Server` supports Base and Solana by default:

* `"development"` uses testnets and test funds.
* `"production"` uses mainnets and real funds.

<Tabs>
  <Tab title="TypeScript">
    Routes inherit this setting unless they list specific networks. Switching `environment` changes
    every inherited route:

    ```typescript theme={null}
    const server = await createX402Server({
      environment: "production",
      routes: {
        "GET /report": { price: "$0.01" },
      },
    });
    ```

    To accept specific networks, list them on the route:

    ```typescript theme={null}
    "GET /report": { price: "$0.01", networks: ["eip155:8453", "eip155:137"] },
    ```
  </Tab>

  <Tab title="Python">
    Python servers configure each network and payment option explicitly:

    ```python theme={null}
    server = x402ResourceServer(HTTPFacilitatorClient(create_facilitator_config()))
    server.register("eip155:8453", ExactEvmServerScheme())
    server.register("solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp", ExactSvmServerScheme())

    routes = {
        "GET /report": RouteConfig(
            accepts=[
                PaymentOption(
                    scheme="exact",
                    pay_to=PAY_TO_EVM,
                    price="$0.01",
                    network="eip155:8453",
                ),
                PaymentOption(
                    scheme="exact",
                    pay_to=PAY_TO_SVM,
                    price="$0.01",
                    network="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
                ),
            ],
            mime_type="application/json",
            description="AI-generated report",
        ),
    }
    ```
  </Tab>
</Tabs>

For the complete chain and token matrix, see the CDP Facilitator's
[supported networks, tokens, and schemes](/x402/seller/facilitator#advanced).

## Choose a payment scheme

A payment scheme defines when the amount is determined and how the payment settles:

* `exact` charges a known price for a synchronous endpoint.
* `upto` authorizes a maximum, then settles the amount used by a synchronous endpoint.
* `batch-settlement` supports repeated, high-throughput payments by redeeming per-request
  commitments later in batches.

Use `exact` unless your endpoint requires usage-based pricing or payment channels.

### Configure non-default schemes

<Tabs>
  <Tab title="TypeScript">
    `exact` is registered automatically and is the default for every route. To use `upto`, set it on
    the route:

    ```typescript theme={null}
    "GET /usage": { price: "$0.10", scheme: "upto", description: "Usage-based billing" },
    ```

    Your handler must report the final amount. See the
    [Express usage-based pricing example](https://github.com/coinbase/cdp-sdk/blob/main/examples/typescript/x402/servers/express/server.ts)
    for the complete flow.

    `batch-settlement` requires the full x402 `RouteConfig` and direct scheme registration. See the
    [x402 batch-settlement guide](https://docs.x402.org/schemes/batch-settlement).
  </Tab>

  <Tab title="Python">
    Register every scheme and network pair the server accepts:

    ```python theme={null}
    from x402.mechanisms.evm.upto import UptoEvmServerScheme
    from x402.mechanisms.evm.batch_settlement.server import BatchSettlementEvmScheme

    server.register(NETWORK, UptoEvmServerScheme())
    server.register(NETWORK, BatchSettlementEvmScheme(PAY_TO))
    ```

    The route's `PaymentOption` must request the same scheme. See the x402 guides for
    [usage-based pricing](https://docs.x402.org/schemes/upto) and
    [batch settlement](https://docs.x402.org/schemes/batch-settlement).
  </Tab>
</Tabs>

## Configure who receives payment

<Tabs>
  <Tab title="TypeScript">
    By default, `createX402Server` provisions a CDP Server Wallet. Use `payToConfig` to provision a
    Smart Contract Wallet or receive payment at an address you provide:

    ```typescript theme={null}
    const server = await createX402Server({
      payToConfig: {
        type: "smart",
        accountName: "x402-receiver",
        ownerAccountName: "x402-owner",
      },
      routes,
    });
    ```

    ```typescript theme={null}
    const server = await createX402Server({
      payToConfig: {
        type: "address",
        evm: "0x...",
        solana: "...",
      },
      routes,
    });
    ```

    ### Resolve the recipient dynamically

    Use the full x402 route format when the receiving address depends on the request:

    ```typescript theme={null}
    const server = await createX402Server({
      payToConfig: { type: "address" },
      routes: {
        "GET /report": {
          accepts: [
            {
              scheme: "exact",
              network: "eip155:8453",
              price: "$0.01",
              payTo: async (context) => resolveRecipient(context),
            },
          ],
        },
      },
    });
    ```
  </Tab>

  <Tab title="Python">
    Set `pay_to`, `price`, `network`, and `scheme` in each `PaymentOption`. The receiving address can
    come from a CDP account or an address you manage.

    ### Resolve the recipient dynamically

    Pass a synchronous or asynchronous function to `pay_to` when the receiving address depends on the
    request:

    ```python theme={null}
    from x402.http import HTTPRequestContext, PaymentOption
    from x402.http.types import RouteConfig


    async def resolve_recipient(context: HTTPRequestContext) -> str:
        return await lookup_recipient(context)


    routes = {
        "GET /report": RouteConfig(
            accepts=[
                PaymentOption(
                    scheme="exact",
                    network="eip155:8453",
                    price="$0.01",
                    pay_to=resolve_recipient,
                )
            ]
        )
    }
    ```
  </Tab>
</Tabs>

## Accept other tokens

Routes can accept tokens other than USDC.

<Tabs>
  <Tab title="TypeScript">
    Use the full x402 `RouteConfig` to set the asset for each payment option. Check the CDP
    Facilitator's [supported networks and tokens](/x402/seller/facilitator#advanced) first.
  </Tab>

  <Tab title="Python">
    Set the asset on each `PaymentOption`. Check the CDP Facilitator's
    [supported networks and tokens](/x402/seller/facilitator#advanced) first.
  </Tab>
</Tabs>

## Add onchain attribution

[Builder Codes](https://docs.base.org/apps/builder-codes/builder-codes) attribute the application
that exposed a paid endpoint. The CDP Facilitator records this code in ERC-8021 Schema 2 calldata
when it settles an EVM payment.

<Tabs>
  <Tab title="TypeScript">
    Pass your Builder Code to `createX402Server`:

    ```typescript theme={null}
    const server = await createX402Server({
      builderCode: "my_app",
      routes,
    });
    ```

    The server advertises the code on every EVM route. Solana-only routes are skipped because Builder
    Code attribution uses EVM calldata.
  </Tab>

  <Tab title="Python">
    Add the standard x402 Builder Code declaration to each route:

    ```python theme={null}
    from x402.extensions.builder_code import BUILDER_CODE, declare_builder_code_extension

    routes = {
        "GET /report": RouteConfig(
            accepts=[...],
            extensions={
                BUILDER_CODE: declare_builder_code_extension("my_app"),
            },
        ),
    }
    ```
  </Tab>
</Tabs>

Each code must contain 1–32 lowercase letters, numbers, or underscores. Omit the option or
extension to leave application attribution unset. See the
[builder-code specification](https://github.com/x402-foundation/x402/blob/main/specs/extensions/builder_code.md)
for the attribution fields and protocol flow.

## Lifecycle hooks

<Tabs>
  <Tab title="TypeScript">
    Use resource-server hooks for payment lifecycle events. Available hooks include
    `onProtectedRequest`, `onBeforeVerify`, `onAfterVerify`, `onVerifyFailure`, `onBeforeSettle`,
    `onAfterSettle`, `onSettleFailure`, and `onVerifiedPaymentCanceled`.

    ```typescript theme={null}
    server.resourceServer.onAfterSettle(async ({ result }) => {
      console.info("Payment settled", {
        network: result.network,
        transaction: result.transaction,
      });
    });
    ```
  </Tab>

  <Tab title="Python">
    Register Python lifecycle hooks directly on `server`:

    ```python theme={null}
    def log_settlement(context) -> None:
        print(
            "Payment settled",
            {"network": context.result.network, "transaction": context.result.transaction},
        )


    server.on_after_settle(log_settlement)
    ```
  </Tab>
</Tabs>

## What to read next

* [CDP Facilitator](/x402/seller/facilitator) for supported chains, tokens, and schemes.
* [Charge over MCP](./mcp-payments.mdx) to protect an MCP tool instead of an HTTP route.
