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

# Testing and Sandbox

> Use the sandbox environment to run the full quote-to-cash lifecycle with test payments before switching your integration to production.

Sandbox is a complete, separate copy of Alguna with its own dashboard, its own API keys and its own data. Nothing you do there touches production, and no money moves: payments run against your processor's test mode. Use it to build an integration, rehearse a migration, or reproduce a customer problem without risk. Run the whole lifecycle there — create a customer, price and activate a subscription, meter usage, invoice, pay, refund, cancel — before you point anything at production.

***

## The two environments

|              | Production                             | Sandbox                                                |
| ------------ | -------------------------------------- | ------------------------------------------------------ |
| Dashboard    | [app.alguna.io](https://app.alguna.io) | [app.sandbox.alguna.io](https://app.sandbox.alguna.io) |
| API base URL | `https://api.alguna.io`                | `https://api.sandbox.alguna.io`                        |
| Payments     | Real money                             | Your processor's test mode                             |
| Data         | Live customers and revenue             | Independent; created by you                            |

The environments share nothing. **A key issued in one is rejected by the other**, customers and subscriptions do not exist across both, and there is no promote or copy step — configuration you want in production is set up in production. Treat "it worked in sandbox" as a statement about your integration, not about your production data.

***

## Getting set up

1. Sign in at [app.sandbox.alguna.io](https://app.sandbox.alguna.io).
2. Create a sandbox key under **Settings → Connections → Developers → API keys**.
3. Point your integration at the sandbox base URL.

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.sandbox.alguna.io/customers?limit=20&offset=0&sort=name:asc" \
    -H "Authorization: Bearer $ALGUNA_SANDBOX_API_KEY" \
    -H "Alguna-Version: 2026-04-01"
  ```

  ```python Python theme={null}
  import os

  import requests

  response = requests.get(
      "https://api.sandbox.alguna.io/customers",
      headers={
          "Authorization": f"Bearer {os.environ['ALGUNA_SANDBOX_API_KEY']}",
          "Alguna-Version": "2026-04-01",
      },
      params={"limit": 20, "offset": 0, "sort": "name:asc"},
      timeout=10,
  )
  response.raise_for_status()
  ```

  ```typescript TypeScript SDK theme={null}
  const alguna = new Alguna({
    apiKey: process.env.ALGUNA_SANDBOX_API_KEY,
    baseUrl: "https://api.sandbox.alguna.io/beta",
  });
  ```
</CodeGroup>

<Note>
  The SDK's `baseUrl` carries the same path prefix as its production default, so the sandbox host is `https://api.sandbox.alguna.io/beta`. See [TypeScript SDK](/docs/api-reference/v2/sdks/typescript#configuration).
</Note>

Keep the two keys in separate environment variables. Reading `ALGUNA_API_KEY` in a script you meant to run against sandbox is the failure mode worth designing against.

***

## Test payments

Alguna is not the payment processor — it decides what is owed, and your processor moves the money. **Test cards therefore come from your processor, not from Alguna.** Connect the processor's test mode to your sandbox environment under **Settings → Connections → Integrations**, then use that processor's published test numbers at [checkout](/docs/hosted/checkout) or on a hosted invoice.

With [Stripe](/docs/integrations/payments/stripe), that means connecting a Stripe test-mode account and using [Stripe's test cards](https://docs.stripe.com/testing) — including the numbers that force a decline, a 3-D Secure challenge, or a dispute, which are the cases worth exercising deliberately. [ACH](/docs/integrations/payments/ach) and other bank rails have their own test account numbers in the same reference.

What runs end to end in sandbox: the payment succeeds or fails as the test instrument dictates, the invoice moves to paid, a [receipt](/docs/hosted/emails) is emailed, and `payment.created` / `payment.updated` [webhooks](/docs/api-reference/v2/webhooks) fire exactly as they would in production.

***

## Testing webhooks

Webhook endpoints are configured per environment under **Settings → Connections → Developers → Webhooks**, so a sandbox endpoint never receives production events.

Your endpoint must be publicly reachable — `localhost` will not work. During development, expose your local server with a tunnel (ngrok or similar) or point the sandbox endpoint at a request-capture service to inspect payloads. See the [webhooks quick start](/docs/guides/webhooks-quickstart).

***

## A pass worth running before go-live

<Steps>
  <Step title="Catalog">
    Create the products, [prices](/docs/pricing/pricing-models) and [plans](/docs/pricing/plans) you actually sell, including the awkward one — the tiered metric, the ramp, the annual with a mid-term add-on.
  </Step>

  <Step title="Acquisition">
    Run both motions that apply to you: a [checkout session](/docs/hosted/checkout) end to end, and a [quote](/docs/quotes/create-quotes) through signature to an active subscription.
  </Step>

  <Step title="Usage">
    Send [events](/docs/billable-metrics/send-usage) with the same shape your production code will send, and confirm they attribute to the right customer and metric.
  </Step>

  <Step title="Billing">
    Let a period close and an [invoice](/docs/invoices/recurring-invoices) generate. Check the line items, the [proration](/docs/subscriptions/proration), the [tax](/docs/tax/overview) and the total against what you expect — not just that an invoice exists.
  </Step>

  <Step title="Money out and back">
    Pay the invoice with a test instrument, then [refund](/docs/invoices/refunds) it and issue a [credit note](/docs/invoices/credit-notes). Refunds and credit notes are where integrations most often turn out to be incomplete.
  </Step>

  <Step title="Failure paths">
    Force a declined payment and watch [dunning](/docs/collections/dunning) and the retry schedule do their work. Confirm your webhook consumer handles a failed payment as well as a successful one.
  </Step>
</Steps>

***

## Next steps

<CardGroup cols={2}>
  <Card title="Developer quick start" icon="code" href="/docs/quickstarts/developers">
    Keys, base URLs and the first calls, end to end.
  </Card>

  <Card title="API overview" icon="book" href="/docs/api-reference/v2/overview">
    Authentication, versioning, pagination and errors.
  </Card>

  <Card title="Webhooks quick start" icon="bell" href="/docs/guides/webhooks-quickstart">
    Receive and verify events from your sandbox.
  </Card>

  <Card title="Migrations" icon="right-left" href="/docs/migrations/migrations">
    Rehearse a move from another billing system in sandbox first.
  </Card>
</CardGroup>
