Skip to content

Sandbox (test mode)

The sandbox lets you try the API without touching your real data. It is a separate test organization with made-up sample data; test tokens only ever see that data — never your real data, and real tokens never see the sandbox. The database enforces the separation, not only the application.

First response in four steps

StepWhat you do
1Administration → API access → Sandbox: create the sandbox (API access must be active, also during the trial).
2Generate a test token (prefix m2h_test_, optionally with the scope webhooks:manage) and copy it at once: it is shown only once.
3Read with the test token: GET /v1/locations. The response header X-M2H-Sandbox: true confirms the sandbox.
4Create a webhook and trigger an event with POST /v1/sandbox/events (see below).

Getting started

Under Administration → API access → Sandbox create the sandbox (right “API access: full access”, at most one per organization) and generate a test token. It is part of the “API access” add-on and can only be used while API access is active (free trial or booking); use during the trial is not a booking and changes no prices. Without active access no sandbox can be created, and an existing one is blocked: a valid test token then gets `403 sandbox_unavailable` with a pointer to the add-on module (an invalid token still gets `401`); once access is active the same token works again.

curl -H "Authorization: Bearer m2h_test_…" https://api.manage2hero.com/v1/locations

The address is the same as for real tokens. You recognise the sandbox by the token prefix m2h_test_ and by the response header X-M2H-Sandbox: true, which every response to a test token carries. Test tokens work in every environment (production, staging, development); the sandbox lives in each environment’s own database.

What the sandbox contains

One company, two locations, three garage types, 20 units (twelve rented, two reserved, one blocked, five available), twelve tenants and twelve running contracts. All names and addresses are made up; e-mail addresses end in @sandbox.invalid (never deliverable), and there are no phone numbers (prospects carry a placeholder number).

On top come the data the read endpoints show: three monthly rents per contract (charges, bookings, open items; three tenants are in arrears), 27 incoming payments allocated to the rents, three invoices (open, paid, partially paid), three dunning notices (levels 1 and 2), six electricity meters with three readings each, two damage cases and two tenant reports, two general appointments and two handovers, three prospects, four documents (metadata only, without a file) and six entries in the e-mail history (log rows only, nothing is sent). The bank account is an example IBAN from public documentation, not a connection. “Reset” restores this data; a sandbox that already exists shows it after its next reset.

What the sandbox does not do

No e-mails ever leave the sandbox — not even through the system mailbox. There are no real payments (the incoming payments are made-up examples), no bank connection and no real documents.

Webhooks in the sandbox

A test token may carry the scope webhooks:manage. Sandbox webhooks run through the same delivery service as real ones: signed POST, retries, self-disabling after six failed attempts, replay and pausing, only https on port 443 to public addresses (the same protection against access to internal addresses). Every message carries "livemode": false in the body and the header X-M2H-Livemode: false (real events: true), so test and real events are never mixed up. Delivery only happens with active API access of the organization. As with real webhooks, only production sends; in development and staging the deliveries stay pending.

You trigger an event without any real booking with POST /v1/sandbox/events (body { "type": "payment.received" }, Idempotency-Key required): it is queued for a sample object of the sandbox and sent to your active webhooks subscribing to the type. The history is in GET /v1/webhooks/{id}/deliveries. With a real token the call does not exist (404).

The response names the event id, the chosen sample object, how many webhooks the event went to (recipients, queued) and whether this server sends (delivery: enabled in production, not_in_this_environment in development and staging). Repeat the call with the same Idempotency-Key and you get the same response; nothing is queued twice.

Response 200
{
  "data": {
    "event_id": "6f1d3c52-8b0e-4a67-9c21-3d5e7a90b4f8",
    "event_type": "payment.received",
    "object_id": "b2a4c6e8-1f3d-4b5a-8c7e-9d0f1a2b3c4d",
    "recipients": 2,
    "queued": 2,
    "delivery": "enabled"
  }
}
curl -X POST https://api.manage2hero.com/v1/sandbox/events \
  -H "Authorization: Bearer m2h_test_…" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"type":"payment.received"}'

Differences from real data

TopicSandbox (test token)Real (live token)
Datamade-up sample data of a separate test organizationyour real data
Token prefixm2h_test_ (valid in every environment)m2h_live_, m2h_stg_ or m2h_dev_
Response headerX-M2H-Sandbox: truenot present
Webhook messagelivemode: false, header X-M2H-Livemode: falselivemode: true, header X-M2H-Livemode: true
E-mails, payments, banknever: nothing goes out, there is no connectiondepending on configuration
Webhook deliveryfrom production only, only with active API accessfrom production only
Limitstighter limits and quotas (see below)standard limits of the API
Lifetime30 days after the last use, then deletedunlimited

Typical error responses

ResponseMeaning
401Token invalid, revoked or expired.
403 sandbox_unavailableThe test token is valid, but API access of your organization is not active (trial over, not booked or blocked by the operator). With active access the same token works again.
404 not_foundThe call exists only for test tokens (e.g. /v1/sandbox/events), or there is no matching sample object.
409 webhook_limit_reachedThere are already 3 webhooks in the sandbox.
409 idempotency_conflictThe same Idempotency-Key was used with different content or a different event type.
422 sandbox_limit_reachedA quota of the sandbox is reached (data volume or simulated events).
429Too many requests: wait for the time in the Retry-After header.

Limits and retention

LimitValue
Read requests per test token60 per minute
Write requests per test token10 per minute
All requests per sandbox300 per minute
Write requests per sandbox500 per day
Active test tokens per sandbox5
Webhooks per sandboxat most 3, otherwise 409 webhook_limit_reached
Simulated eventsat most 100 waiting and 500 per 24 hours per sandbox, otherwise 422 sandbox_limit_reached; deliveries of the sandbox are deleted after 7 days
Data volume (tenants, prospects, damages, meter readings, appointments, import records)at most 3000 combined, otherwise 422 sandbox_limit_reached
Imports via APIat most 3 open imports and 5 new ones per hour and token
Validity of a test token7, 30 or 90 days
Lifetime of the sandbox30 days after its last use, then deleted

“Reset” in the management app replaces the sandbox with a fresh one with new sample data (data you created yourself is lost); your active test tokens stay valid and afterwards work in the new sandbox. Once the sandbox has expired, “Create new sandbox” in the management app creates a fresh one; the test tokens of the old one stop working. The operator emergency stop of your organization also blocks the sandbox. Creating and revoking test tokens appear in your organization’s activity log.