Building in the Sandbox
Build and verify your Partner app in sandbox before you certify its OAuth handshake in production.
Where sandbox fits
Sandbox is where you build. It has its own database and synthetic operators, so nothing you do there touches a real customer. You build and certify almost your entire integration here—every endpoint, every webhook, and the install lifecycle—then complete one final step in production. See Going live for that step.
What you get
| Capability | In sandbox |
|---|---|
| Full Partner API surface—every endpoint and scope | ✅ |
| An install representing an operator's grant | ✅ Provisioned by Monta |
install.created / install.revoked / install.config.updated webhooks | ✅ Real deliveries and signatures |
403 NEEDS_REAUTH behavior after a scope change | ✅ |
| Per-install rate limiting | ✅ |
| Synthetic operators, sites, and charge points | ✅ |
| The OAuth authorization-code handshake | ❌ Certified in production; see Going live |
Why the handshake is not in sandbox
The consent screen is part of the Monta operator experience: an operator signs in and approves your scopes. Reproducing that outside production would require a second identity provider and a second Hub, and would have you rehearse against endpoints you never ship with—a common source of launch-day invalid_client failures.
Sandbox gives you everything the handshake produces: a live install, credentials, data, and webhooks. Monta certifies the handshake once, with you, against production endpoints scoped to a Monta-owned test operator. In practice, the deferred work is limited to exchanging a code and refreshing a token.
Get set up
Ask Monta for sandbox access and provide:
- Your app name and the scopes you need
- Your publicly reachable HTTPS webhook URL
- The contact address that should receive credentials
Monta registers your app and provisions an install against a synthetic operator. You receive an install.created webhook containing install_id, operator_id, and your sandbox client_id and client_secret. Monta also sends the credentials directly as a fallback.
Sandbox credentials are sandbox-only
They do not work in production, and Monta issues production credentials separately. See Going live.
Authenticate
Sandbox uses the Partner API's own credential exchange rather than the OAuth handshake:
curl -X POST https://partner-api.sandbox.monta.com/api/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"clientId": "<your_sandbox_client_id>", "clientSecret": "<your_sandbox_client_secret>"}'A successful response contains access and refresh tokens:
{
"accessToken": "…",
"refreshToken": "…"
}Call the API with the access token:
curl https://partner-api.sandbox.monta.com/api/v1/charge-points?perPage=50 \
-H "Authorization: Bearer <accessToken>"Refresh the token with POST /api/v1/auth/refresh and your refreshToken.
What changes in production
Only token acquisition changes. In production, you exchange an authorization code at the identity provider's token endpoint rather than calling
/api/v1/auth/token. Every API call, payload, scope, and webhook is identical—the API authorizes against the install, not how you authenticated. Keep token acquisition behind one interface in your code so the production switch needs one implementation change.
Build and prove the integration
Work through this list in sandbox so production certification becomes a formality:
- Exercise the read paths you depend on with realistic pagination.
- Request the narrowest scopes and confirm that you never call an endpoint outside them.
- Verify webhooks: read
X-Monta-Signature: sha256=<hex>, calculate HMAC-SHA256 over the raw body with yourwebhook_secret, compare in constant time before parsing, and reject staledelivered_attimestamps. - Stop using an install immediately after
install.revoked, and ensure nothing retries against it. - Re-read configuration after
install.config.updatedrather than caching it indefinitely. - Handle
403 NEEDS_REAUTHseparately from other403responses: surface it and stop calling the API for that install. - Apply backoff for the default limit of 1,000 requests per 60 seconds per install.
- Implement reconciliation that can recover state from the API without relying on a webhook delivery.
Webhook delivery is best-effort
Monta does not automatically retry a timeout, non-
2xxresponse, or transport error. Monta can replay deliveries on request. Treat webhooks as an accelerator and the API as your source of truth. Your endpoint must return2xxwithin 10 seconds.
Test the lifecycle
Ask Monta to drive these events against your sandbox install:
| To test | Ask for |
|---|---|
| First install | A fresh install; you receive install.created |
| Uninstall | The install revoked; you receive install.revoked |
| Configuration change | A config update; you receive install.config.updated |
| Re-authorization | A scope widening so calls begin returning 403 NEEDS_REAUTH |
Each is a one-command operation on Monta's side, so iterate as often as you need.
Endpoints
| Purpose | Sandbox |
|---|---|
| Partner API | https://partner-api.sandbox.monta.com/api/v1 |
| Credential exchange | POST /api/v1/auth/token |
| Refresh | POST /api/v1/auth/refresh |
| API reference | See the API Reference section |
When you are ready
Work through the checklist in Going live. Production issues new credentials, and your first production install is against a Monta test operator before any real customer sees your app.
Updated 2 days ago