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

# How to disable email editing in checkout

> Lock the checkout email to a known customer so signed-in buyers can't mistype it — and every order maps cleanly back to your user.

If a buyer is already signed into your app, you usually don't want them retyping (or fat-fingering) their email at checkout. A typo there means a stranded order, a duplicate customer record, and a reconciliation headache later.

The fix: attach the checkout session to a customer you already know. When you do, Macropay treats the email as settled — it pre-fills the field and locks it so it can't be changed.

## What attaching a customer does

Pass `customer_id` or `external_customer_id` to `checkouts.create` and Macropay will:

* **Pre-fill** the customer's known details into the checkout form.
* **Lock the email field** so the buyer can't edit it.
* **Bind the resulting order** to that exact customer record — no duplicates, clean reconciliation.

<Note>
  Because Macropay is the **Merchant of Record**, that locked customer record is also what we use to assess the right sales tax/VAT and to put the correct legal seller on the buyer's statement. One trustworthy identity in, one clean tax-compliant order out.
</Note>

## Pick the right identifier

| Identifier             | Use when                                                      | Why                                                                                                                 |
| ---------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `external_customer_id` | You run your own auth / user table                            | **Recommended.** Map straight to your internal user ID — reconciliation stays trivial and you never store our UUID. |
| `customer_id`          | The customer already exists in Macropay and you hold our UUID | Direct, unambiguous link to an existing Macropay customer.                                                          |

## Option A — link by your own user ID (recommended)

If you already manage users, hand us your internal ID as `external_customer_id`. Macropay looks for a customer with that external ID; if one exists it links to it and pre-fills their data, and either way the order ends up attributed to that ID.

<Steps>
  <Step title="Create the checkout with external_customer_id">
    Pass your application's user ID. Here a logged-in user upgrades to the `pro-annual` plan:

    <CodeGroup>
      ```ts TypeScript theme={null}
      import { Macropay } from "@macropayments/sdk";

      const macropay = new Macropay({ accessToken: process.env["MACROPAY_ACCESS_TOKEN"] });

      const checkout = await macropay.checkouts.create({
          products: ["<product_id>"],
          externalCustomerId: "user_8f3a91", // your app's user ID // [!code ++]
      });

      console.log(checkout.url);
      ```

      ```py Python theme={null}
      from macropay_sdk import Macropay

      with Macropay(
          access_token="<YOUR_BEARER_TOKEN_HERE>",
      ) as macropay:

          checkout = macropay.checkouts.create(request={
              "products": ["<product_id>"],
              "external_customer_id": "user_8f3a91",  # your app's user ID # [!code ++]
          })

          print(checkout.url)
      ```

      ```bash cURL theme={null}
      curl --request POST \
        --url https://api.macropay.ai/v1/checkouts/ \
        --header 'Authorization: Bearer <YOUR_ACCESS_TOKEN>' \
        --header 'Content-Type: application/json' \
        --data '{
          "products": ["<product_id>"],
          "external_customer_id": "user_8f3a91"
        }'
      ```
    </CodeGroup>
  </Step>

  <Step title="Send the buyer to checkout">
    Redirect to the `url` in the response. The email arrives pre-filled and read-only, and the order comes back stamped with `user_8f3a91`.
  </Step>
</Steps>

## Option B — link by Macropay customer ID

If the customer already lives in Macropay and you have our UUID, link to it directly.

<Steps>
  <Step title="Grab the customer ID">
    Find it in your [dashboard's customer list](/api-reference/customers/list) or via the API. It's a UUID, for example `992fae2a-2a17-4b7a-8d9e-e287cf90131b`.
  </Step>

  <Step title="Create the checkout with customer_id">
    <CodeGroup>
      ```ts TypeScript theme={null}
      import { Macropay } from "@macropayments/sdk";

      const macropay = new Macropay({ accessToken: process.env["MACROPAY_ACCESS_TOKEN"] });

      const checkout = await macropay.checkouts.create({
          products: ["<product_id>"],
          customerId: "992fae2a-2a17-4b7a-8d9e-e287cf90131b", // [!code ++]
      });

      console.log(checkout.url);
      ```

      ```py Python theme={null}
      from macropay_sdk import Macropay

      with Macropay(
          access_token="<YOUR_BEARER_TOKEN_HERE>",
      ) as macropay:

          checkout = macropay.checkouts.create(request={
              "products": ["<product_id>"],
              "customer_id": "992fae2a-2a17-4b7a-8d9e-e287cf90131b",  # [!code ++]
          })

          print(checkout.url)
      ```

      ```bash cURL theme={null}
      curl --request POST \
        --url https://api.macropay.ai/v1/checkouts/ \
        --header 'Authorization: Bearer <YOUR_ACCESS_TOKEN>' \
        --header 'Content-Type: application/json' \
        --data '{
          "products": ["<product_id>"],
          "customer_id": "992fae2a-2a17-4b7a-8d9e-e287cf90131b"
        }'
      ```
    </CodeGroup>
  </Step>

  <Step title="Send the buyer to checkout">
    Redirect to the returned `url`. The email field is pre-filled and locked, and the order links back to that customer.
  </Step>
</Steps>

<Tip>
  Building agent or usage-based billing? The same trick keeps your records clean: bind every checkout to an `external_customer_id` and downstream usage events, meters, and agent value receipts all roll up under one stable customer — so per-customer revenue and margin stay accurate without any post-hoc stitching.
</Tip>
