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

# Testing your integration

> There is no sandbox. Build against production with your live keys, safely: a private test event, free or low-price tickets, refunds, and Send test event for webhooks.

The Partner API has **one environment: production**, at
`https://connect.laces.run/v1`. There are no test keys and no sandbox. You
build and test with the live keys from the Laces app, against your real
organization.

<Warning>
  **Payments are real.** A paid order charges a real mobile money account, and
  the money goes to your organization like any other sale. Test with free
  tickets where you can, use the smallest price you're comfortable with
  otherwise, and refund afterwards. A full refund returns everything the buyer
  paid, the Laces fee included; your organization's balance is debited only
  the ticket price.
</Warning>

## Set up a test event

<Steps>
  <Step title="Create a private event">
    In the Laces app, create an event just for testing, for example "API test
    (do not register)". Set its visibility to **unlisted**, so it never appears
    on laces.run's public listings, and open registration.
  </Step>

  <Step title="Add cheap tickets">
    Add a **free** ticket type (a total of 0 confirms without any payment) and,
    if you need to test paid flows, one at a low price. If you sell by
    distance, add a distance so you exercise that part of the form too.
  </Step>

  <Step title="Check payments are enabled">
    Your organization must be cleared to take payments before **any** order or
    checkout session can be created, free ones included. Read the event over
    the API: `payments_enabled: true` means you're ready; `false` means checkout
    is refused with `payments_disabled`. Contact Laces if it stays `false`.
  </Step>
</Steps>

<Note>
  The Partner API **does** list unlisted events: they belong to your
  organization. Make sure your site doesn't show the test event to the public
  (filter it by `event_id`), and close or end it when you launch.
</Note>

## Test each flow

| Flow | How to test it |
| - | - |
| Reading events | Call `GET /events` and `GET /events/{eventId}` with a bearer token, or with the publishable key from your page. Free to repeat. |
| [Hosted checkout](/guides/hosted-checkout) | Create a session for the test event, complete it with the free ticket, and confirm your server's session read says `complete`. Repeat once with a paid ticket and your own phone. |
| [Embedded checkout](/guides/embedded-checkout) | The same, from a page whose origin is in your allowed domains (your local dev server works). |
| [Custom UI](/guides/custom-ui) | Create an order with the free ticket and pay it (no `msisdn` needed). Then a paid order to your own number: approve the prompt on your phone, and also try declining it to see `order.failed` with `failure_kind: "declined"`. |
| Refunds | Refund a paid test order from the Laces app. You receive `order.refunded`, and the order's `status` becomes `refunded`. |
| [Webhooks](/guides/webhooks) | Tap **Send test event** in the app for a signed `ping` (no order needed), then watch `order.paid` arrive for your test orders. |
| Errors | Free to provoke: a wrong `waiver_version`, a missing `Idempotency-Key`, a wrong `Origin`, a lowercased key. None of them create an order. |

Every test order is a real order in your organization: it appears in your
dashboard and in [order reads](/api-reference/v1/orders/list), and the buyer
email address you use receives a real confirmation. Use your own address, or
one at a domain you control.

## Local development

You can develop on your own machine with your live keys:

* **Server-side calls** (token, events, orders, pay, session reads) work from
  anywhere. Keep the secret in a local `.env` file that is never committed.
* **Browser calls with the publishable key**: add your dev server's origin,
  for example `http://localhost:3000`, to **Allowed domains**. Only
  `http://localhost:<port>` and `http://127.0.0.1:<port>` are accepted over
  plain `http`, and the port is required. The app labels these "Local
  development domain: remove before launch".
* **Hosted checkout and the embedded modal** work end to end on
  `http://localhost:<port>` with your live keys. Add the origin to **Return
  URL domains** for the hosted return, and to **Allowed domains** for the
  page that opens the modal. A newly added domain can take up to 5 minutes to
  pass the browser's CORS check.
* **Webhooks** need a public `https` URL. Point a tunnel at your local
  receiver and register the tunnel URL; see
  [Test your endpoint](/guides/webhooks#test-your-endpoint).

## Use a separate key for development

Create a **separate API key** for development (for example "Club site
(dev)"), with your local and staging origins, and a different one for your
production site. Then you can regenerate or revoke the development key at any
time without touching the live site, and remove local domains from the
production key entirely.

## Before launch

Work through [Going live](/going-live): remove local domains, point webhooks
at your production server, and hide or close the test event.


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