What you’ll build

An agent flow that takes a name, an email, and a card_token and produces a paid order, without juggling three separate tool calls.

Where the card comes from

create_customer_and_charge takes a single-use card_token (cct_…). Your frontend captures the card in the browser with EPD Elements (the epd.js SDK loaded with a publishable key), which returns the card_token. The raw card number never reaches the agent or the API. See the EPD Elements guide for the browser code. A card_token is single-use and expires 15 minutes after capture.

The single call

Use create_customer_and_charge (a composite tool).

{
  "name": "create_customer_and_charge",
  "arguments": {
    "email": "jane@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "phone": "+14155551234",
    "card_token": "cct_3f8a1c9e7b2d4a6f0e1c3b5d7f9a1c3e5b7d9f0a2c4e6b8d",
    "items": [
      { "product_id": "prod_9b2c1e7a5d3f4b6c8e0a2c4e6b8d0f1a", "quantity": 1 }
    ],
    "currency": "usd",
    "description": "Welcome order",
    "idempotency_key": "onboard-2026-04-21-abc123"
  }
}

The order total comes from the product catalog: you pass items, not an amount. Update the product’s price first if you need a different total.

What EPD does internally:

Create the customer

Equivalent to create_customer with the customer fields.

Attach the payment method

Equivalent to add_payment_method with the card_token and set_as_default: true.

Charge

Builds and charges an order from items behind the scenes.

Return one consolidated response

Returns the customer, payment_method, and order objects together.

Why use the composite tool

Doing it yourselfcreate_customer_and_charge
3 MCP round-trips (≥ 3× latency)1 round-trip
Partial-failure recovery you write yourselfEPD orchestrates the flow and returns a consolidated outcome
3 idempotency keys to trackOne key per intent
3 request_ids to correlateOne logical trace by request_id

Handling outcomes

On success the response contains the three objects:

{
  "customer": { "id": "550e8400-e29b-41d4-a716-446655440000" },
  "payment_method": { "id": "6ba7b815-9dad-11d1-80b4-00c04fd430c8" },
  "order": { "id": "6ba7b811-9dad-11d1-80b4-00c04fd430c8", "status": "succeeded", "total": 2999 }
}

The order’s charged amount is total (in cents). If the charge declines, the order still comes back in the normal response with order.status: "failed" and a failure_reason: the customer and payment method are kept, so your agent can prompt for a different card and call create_order directly without re-creating the customer:

{
  "customer": { "id": "550e8400-e29b-41d4-a716-446655440000" },
  "payment_method": { "id": "6ba7b815-9dad-11d1-80b4-00c04fd430c8" },
  "order": { "id": "6ba7b811-9dad-11d1-80b4-00c04fd430c8", "status": "failed", "failure_reason": "insufficient funds", "failure_code": "insufficient_funds" }
}

Only a genuine failure before the charge (e.g. the customer is created but the card can’t be attached) rolls the customer back and returns an error envelope. If that rollback itself fails, you get error.code: "partial_rollback_failed" with the orphaned customer_id in the message. Surface it and clean up manually.

Sandbox example

To exercise a decline through this tool in sandbox, capture one of the declining test cards (e.g. the insufficient-funds card) with EPD Elements against your sandbox publishable key; that yields a card_token, which you then pass here:

{
  "name": "create_customer_and_charge",
  "arguments": {
    "email": "test@example.com",
    "first_name": "Decline",
    "last_name": "Test",
    "phone": "+14155550100",
    "card_token": "cct_<captured from the insufficient-funds sandbox test card>",
    "items": [
      { "product_id": "prod_9b2c1e7a5d3f4b6c8e0a2c4e6b8d0f1a", "quantity": 1 }
    ],
    "currency": "usd"
  }
}

You’ll see the customer get created and the order come back with status: "failed", failure_code: "insufficient_funds" (with failure_reason as the human-readable companion).

There is no server-only sandbox card_token for this composite tool. A cct_… is minted only by a real EPD Elements browser capture (sandbox or live). For pure server-to-server sandbox testing without a browser, use Inbound Card Capture with a sandbox test card number to save the payment method directly, then charge it with the primitive create_order tool instead of this composite. See the testing reference.