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

> ## Agent Instructions
> When building application code, use `@naturalpay/sdk` for TypeScript or `naturalpay` for Python.
> When operating Natural directly for a user, use the payments MCP at `https://mcp.natural.com`.
> When searching Natural documentation, use the docs MCP at `https://docs.natural.com/mcp`.
> Use the Natural CLI for terminal and CI automation.
> Use REST only for unsupported languages or when the user explicitly requests raw HTTP.
> Start integration development and testing in the sandbox. Do not use production unless the user explicitly requests it.
> For sandbox requests that require `customerPartyId`, list customers first. Reuse only the intended fixture; otherwise create a customer.
> REST and SDK amounts use integer minor units. Payments MCP amounts use decimal strings with a required currency code.

# Sandbox from MCP, CLI, and SDKs

> Connect to the Natural Sandbox

Switch the [dashboard](/guides/platform/dashboard) to Sandbox to get a sandbox key (`sk_ntl_sandbox_…`, `ak_ntl_sandbox_…`).

The simulation actions listed below are available on every surface:

| Surface | Where simulations live |
| - | - |
| REST API | [`POST /simulations/*`](/api-reference/simulations/create-test-customer), grouped with the resources they test |
| SDKs | `client.simulations` in [TypeScript and Python](/guides/platform/sdks) |
| CLI | [`natural simulations <verb>`](/guides/platform/cli) commands |
| MCP | Sandbox-only tools on `mcp.sandbox.natural.com` |

## SDKs

Point the client at the sandbox and put your agent's sandbox key in `NATURAL_API_KEY`. Your integration code is unchanged; `client.simulations` acts as the counterparty.

<CodeGroup>
  ```python Python theme={null}
  from naturalpay import Natural

  # NATURAL_API_KEY=ak_ntl_sandbox_...
  client = Natural(
      instance_id="sandbox-run-1",
      base_url="https://api.sandbox.natural.com",
  )

  # Invite a test customer; one pending invitation is created per agent
  invited = client.simulations.invite_customer(
      agent_ids=["agt_019cd1798d637a4da75dce386343931d"],
      permissions=["payments.create", "payments.read", "wallets.read"],
      idempotency_key="test-customer-1",
  )
  customer_id = invited.meta.customer.party_id

  # Accept the invitation as the test customer
  client.simulations.accept_customer_invitation(
      invitation_id=invited.data[0].id,
      party_id=customer_id,
      idempotency_key="accept-invitation-1",
  )

  # Fund it so payments on its behalf can settle
  client.simulations.fund_customer(
      customer_id=customer_id,
      amount=250000,  # cents - $2,500.00
      currency="USD",
      idempotency_key="fund-customer-1",
  )

  # Run your integration exactly as it runs in production
  payment = client.payments.create(
      amount=10000,
      currency="USD",
      counterparty={"type": "email", "value": "payment-recipient@sandbox.natural.test"},
      customer_party_id=customer_id,
      idempotency_key="pay-1",
  )
  ```

  ```typescript TypeScript theme={null}
  import Natural from "@naturalpay/sdk";

  // NATURAL_API_KEY=ak_ntl_sandbox_...
  const client = new Natural({
    instanceId: "sandbox-run-1",
    baseUrl: "https://api.sandbox.natural.com",
  });

  // Invite a test customer; one pending invitation is created per agent
  const invited = await client.simulations.inviteCustomer({
    agentIds: ["agt_019cd1798d637a4da75dce386343931d"],
    permissions: ["payments.create", "payments.read", "wallets.read"],
    idempotencyKey: "test-customer-1",
  });
  const customerId = invited.meta.customer.partyId;

  // Accept the invitation as the test customer
  await client.simulations.acceptCustomerInvitation({
    invitationId: invited.data[0].id,
    partyId: customerId,
    idempotencyKey: "accept-invitation-1",
  });

  // Fund it so payments on its behalf can settle
  await client.simulations.fundCustomer({
    customerId,
    amount: 250000, // cents - $2,500.00
    currency: "USD",
    idempotencyKey: "fund-customer-1",
  });

  // Run your integration exactly as it runs in production
  const payment = await client.payments.create({
    amount: 10000,
    currency: "USD",
    counterparty: { type: "email", value: "payment-recipient@sandbox.natural.test" },
    customerPartyId: customerId,
    idempotencyKey: "pay-1",
  });
  ```
</CodeGroup>

Both SDKs expose every simulation. TypeScript names methods in camelCase, Python in snake\_case:

| Method | Simulates |
| - | - |
| `inviteCustomer` | [A test customer with a pending invitation per agent](/api-reference/simulations/create-test-customer) |
| `fundCustomer` | [A deposit into a test customer's wallet](/api-reference/simulations/fund-test-customer) |
| `linkExternalAccount` | [A linked test bank account](/api-reference/simulations/link-test-bank-account) |
| `completePaymentClaim` | [An unregistered payee claiming your payment](/api-reference/simulations/complete-payment-claim) |
| `fulfillPaymentRequest` / `declinePaymentRequest` | [The payer answering your request](/api-reference/simulations/fulfill-payment-request) |
| `acceptCustomerInvitation` / `declineCustomerInvitation` | [The customer answering your invitation](/api-reference/simulations/accept-customer-invitation) |
| `revokeAgentConnection` | [The customer revoking your agent](/api-reference/simulations/revoke-agent-connection) |
| `disconnectCustomer` | [The customer disconnecting the whole connection](/api-reference/simulations/disconnect-customer) |
| `settleRealtime` / `failRealtime` | [A realtime payment settling or failing](/api-reference/simulations/settle-realtime-payment) |
| `settleWire` / `failWire` | [A wire settling or failing](/api-reference/simulations/settle-wire) |

## CLI

Export a sandbox key and the sandbox base URL; every command then runs against the sandbox:

```bash theme={null}
export NATURAL_API_KEY=sk_ntl_sandbox_abc123...
export NATURAL_BASE_URL=https://api.sandbox.natural.com

# Invite a test customer; the response carries the customer party ID and invitation IDs
natural simulations invite-customer \
  --json '{"agentIds": ["agt_019cd1798d637a4da75dce386343931d"]}' \
  --idempotency-key "$(uuidgen)"

# Accept the invitation as the test customer
natural simulations accept-customer-invitation \
  --invitation-id adi_019cd1798d96adc082e235b426d4e04c \
  --json '{"partyId": "pty_019cd1798d6a0cf1a6076c62addacb4d"}' \
  --idempotency-key "$(uuidgen)"

# Fund it, then pay on its behalf exactly as in production
natural simulations fund-customer \
  --customer-id pty_019cd1798d6a0cf1a6076c62addacb4d \
  --amount 250000 \
  --currency USD \
  --idempotency-key "$(uuidgen)"
```

`--base-url` works per command if you prefer not to export `NATURAL_BASE_URL`.

<Note>
  `natural login` signs into production. Against the sandbox, authenticate with a sandbox key.
</Note>

## MCP

Natural runs a sandbox peer of the hosted MCP server at **`https://mcp.sandbox.natural.com`**. Connect it like the [production server](/guides/platform/mcp), alongside it if you want both:

```json theme={null}
{
  "mcpServers": {
    "natural": { "url": "https://mcp.natural.com" },
    "natural-sandbox": { "url": "https://mcp.sandbox.natural.com" }
  }
}
```

The sandbox peer exposes every production tool. On this peer, `invite_customer` creates a synthetic test customer with pending invitations instead of emailing a real person. Below are the tools that are sandbox-only:

| Tool | What it does |
| - | - |
| `simulate_customer_deposit` | Add test funds to a connected customer |
| `link_test_bank_account` | Link a synthetic bank account to your party |
| `simulate_payment_claim_completion` | Complete a held payment as the claim recipient |
| `simulate_payment_request_fulfillment` | Fulfill your payment request as the test payer |
| `simulate_payment_request_decline` | Decline your payment request as the test payer |
| `simulate_customer_invitation_accept` | Accept your customer invitation as the test customer |
| `simulate_customer_invitation_decline` | Decline your customer invitation as the test customer |
| `simulate_agent_connection_revoke` | Revoke an agent's access as the test customer |
| `simulate_customer_disconnect` | Disconnect the test customer entirely |
| `simulate_direct_settlement` | Settle a processing Direct wire or realtime payment |
| `simulate_direct_failure` | Fail a processing Direct wire or realtime payment |

`list_payment_requests` and `cancel_payment_request` work on the Sandbox MCP server too. Listing reads your requests; cancellation withdraws an open request you sent. The payment-request simulations act as the test payer, fulfilling or declining your outgoing request. They do not replace requester cancellation.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.