Sandbox
There is one Mr Charles API. You do not get a separate host to develop against; instead, a studio site can be in sandbox mode, and you build against that.
A sandbox site answers every endpoint exactly like a live one — same payloads, same prices, same conflict rules, same errors — with four differences:
| Live site | Sandbox site |
|---|---|
| The verification code is sent by SMS or email | The code comes back in the hold response as devCode |
| Guest and studio get confirmations, reminders, cancellations | Nothing is sent to anyone |
Rooms may accept card deposits | Rooms are on_site only; stripePublishableKey is absent |
| Bookings are real | Bookings and holds are purged after 7 days |
You can tell which one you are talking to: the site payload carries "site": { "sandbox": true }, and the hosted site shows a yellow banner on every page.
Which sandbox to use
Section titled “Which sandbox to use”The platform’s demo studio — demo-studio — is permanently in sandbox mode, has two bookable rooms with opening hours seven days a week, and is what the examples in these docs use:
curl -s https://api.mrcharles.app/api/v1/public/sites/demo-studioYour own studio’s site — any studio can flip its site to sandbox from the dashboard (Studio → Web del estudio → Modo pruebas). Do this to test with the real rooms, prices and hours before launch, then switch it off. While it is on, the site tells visitors it is in test mode and refuses card payments, so nobody can book for real by accident.
The flow in sandbox
Section titled “The flow in sandbox”import { createClient } from '@mrcharles/sdk';const mc = createClient();const flow = mc.roomBooking({ slug: 'demo-studio', roomId });
await flow.loadSite(); // site.site.sandbox === trueawait flow.loadAvailability();const hold = await flow.hold({ date, startTime, durationMinutes, guestName: 'Test', channel: 'email', contact: '[email protected]' });await flow.verify(hold.devCode); // the code you would have receivedawait flow.confirm({ paymentMode: 'on_site' });Nothing above reaches a phone, an inbox or a card. Rate limits still apply (5 holds per contact and 20 per IP per hour), so vary the contact when you loop.
Going live
Section titled “Going live”Change the slug. That is the whole migration: the host, the endpoints, the SDK and your code stay the same. Then check the two things that only exist on a live site:
captchaSiteKey— present on every site outside local development, sandbox included; attach a Turnstile token (actionhold) to every hold (Bot protection).stripePublishableKeyandcardinroom.paymentModes— if the studio takes deposits, test the Payment Element with Stripe’s test cards on your own site in sandbox-off state before publishing, or ask us for a Stripe test session.
What sandbox is not
Section titled “What sandbox is not”It is not a copy of the platform. Studios, teachers and bookings you see are real production data; the demo studio and your own sandbox site are the only things that behave differently. Do not store anything you would mind losing in a sandbox booking — the purge is not negotiable.