Overview
The sandbox lets you exercise your integration without running real asset processing or consuming processing credits. It is not a separate host or base URL. You select the sandbox by using a sandbox API key: the same base URL and the same paths behave as a sandbox when the request is authenticated with ansk_test_ key.
Sandbox keys unlock two capabilities:
- A
simulationDelaySecondsquery parameter on submission creation, to control timing. - A
POST /api/integrations/sandbox/events/fireendpoint, to dispatch synthetic webhook events to your subscriptions without real processing.
Sandbox submissions are excluded from Insights — their canned results never affect your workspace’s counts, rates, or processing durations.
Using a sandbox key
Use yoursk_test_ key against the normal base URL and the normal endpoints. The asset filename selects the outcome to simulate — see Choosing a test scenario. As with live submissions, sidekickIds is required (at least one), though the sandbox does not actually run the named sidekicks.
sk_live_) key calls the same endpoints but cannot use the sandbox-only features described below.
Choosing a test scenario
Sandbox submissions never run real analysis. Instead, you pick the outcome by embedding a magic marker in the asset’s filename. The marker selects a canned result that flows through the normal read endpoints — submission status, per-asset issues, and retry — exactly as a real processing result would.blobPath always has the form {asset-id}/{filename}, where {asset-id} is a UUID. The marker goes in the filename — the part after the /. The simplest form is to use the marker as the whole filename, e.g. 11111111-1111-1111-1111-111111111111/__sandbox_pass__.
Because the sandbox never reads a real file, you do not need to upload anything first for sandbox submissions — any UUID works as the asset id. (For live submissions you obtain blobPath from the upload endpoints instead.)
| Filename marker | Submission status | Asset outcome | Issues produced | Retryable |
|---|---|---|---|---|
__sandbox_pass__ | complete | Clean pass | None | — |
__sandbox_advisory__ | complete | Passes with advisories | 2 — one minor, one info | — |
__sandbox_fail__ | complete | Completes but carries blocking issues | 3 — one critical, two major | — |
__sandbox_error__ | failed | Non-retryable processing failure | None | No |
__sandbox_retryable_error__ | failed | Transient processing failure | None | Yes |
__sandbox_pending__ | processing | Stays in processing, never finalises | None | — |
__sandbox_fail__still reportscomplete. A “fail” here means the asset finished but surfaced critical/major issues — the submission status iscompleteand the issues appear via the asset issues endpoint. Use it to exercise issue-handling logic.__sandbox_error__vs__sandbox_retryable_error__. Both drive the submission tofailed. The error variant is a permanent failure (isRetryable: false); the retryable variant setsisRetryable: trueso you can exercise the retry endpoint. The submission’serrorMessageisSandbox simulated errororSandbox simulated retryable errorrespectively.__sandbox_pending__leaves the submission inprocessingindefinitely — useful for testing polling timeouts and real-time status updates.- Mixed-scenario submissions. When a submission contains assets with different markers, the worst outcome decides the overall submission status, in this order (worst first):
error→retryable_error→fail→advisory→pass→pending. Each asset still carries its own issues and per-asset failure fields.
Example: testing the issue path
critical and two major issues to drive your review UI or compliance checks.
Example: testing the retry path
failed with isRetryable: true. Call the retry endpoint for that asset to exercise your recovery flow: the sandbox simulates a successful retry, so the asset recovers and the submission moves to complete with isRetryable: false. The retry is single-use — once the asset has recovered it is no longer in a failed state, so a second retry returns 409. Submit __sandbox_error__ instead to verify that a non-retryable failure is rejected by the retry endpoint with 409.
Simulating processing time
Add thesimulationDelaySeconds query parameter to a submission-create request to delay when the submission reaches a terminal state. This is useful for exercising your polling and webhook-handling logic.
- The parameter is camelCase:
simulationDelaySeconds. - Accepted range is 0 to 30 seconds. Default is 0.
- It works only with a sandbox key. Sending it on a live key returns a 400.
Firing synthetic webhook events
To test your webhook handler end to end, fire a synthetic event for an existing submission’s assets. The endpoint dispatches the event to every matching subscription in your workspace, exactly as a real processing event would, but without running any processing.POST /api/integrations/sandbox/events/fire
Request body (camelCase):| Field | Required | Notes |
|---|---|---|
eventType | Yes | One of asset.processing.completed or asset.processing.failed |
submissionId | Yes | A submission that exists in your workspace |
errorMessage | No | Optional message, used with asset.processing.failed |
dispatched is the number of subscriptions notified across all of the submission’s assets.
This endpoint is sandbox-only. Behaviour by condition:
| Condition | Result |
|---|---|
| Sandbox key, submission in workspace | 200 with dispatched count |
| Live key | 403 |
submissionId not found in your workspace | 404 |
| Malformed request body | 422 |
Testing the failure path
There are two complementary ways to exercise failure handling in the sandbox. To test the processing-result read path, submit an asset with the__sandbox_error__ or __sandbox_retryable_error__ marker (see Choosing a test scenario) and read the failure back from the submission status. To test webhook delivery end to end, subscribe a webhook, create a submission, then fire an asset.processing.failed event and confirm your endpoint received it.
type of asset.processing.failed, with a snake_case data object containing asset_id, submission_id, workspace_id, status of "failed", and error_message.
Key differences from production
| Aspect | Sandbox (sk_test_ key) | Production (sk_live_ key) |
|---|---|---|
| Selection | API key prefix sk_test_ | API key prefix sk_live_ |
| Base URL and paths | Same as production | Same as sandbox |
| Processing | No real analysis or credits consumed; outcome chosen by filename marker | Real processing |
| Asset filename | Must contain a __sandbox_*__ scenario marker | Real filename, no marker required |
| Webhook events | Can be fired synthetically via /sandbox/events/fire | Emitted by real processing |
| Timing control | simulationDelaySeconds (0–30) on submission create | Not available |
Best practices
Troubleshooting
Sandbox submission rejected with 400
- A sandbox key requires every asset filename to contain a scenario marker (e.g.
__sandbox_pass__). Add one of the markers from Choosing a test scenario to the filename portion ofblobPath. - The marker must appear after the first
/inblobPath— that is the filename the sandbox inspects.
Webhook not delivered
- Ensure your endpoint is publicly reachable and returns 200
- Confirm the subscription’s
eventTypesincludes the event you fired - Check that
dispatchedwas at least 1 in the fire response - Review delivery history via the subscription’s deliveries endpoint
simulationDelaySeconds rejected
- The parameter is camelCase:
simulationDelaySeconds - The value must be between 0 and 30
- A 400 means it was sent on a live key — use a sandbox (
sk_test_) key
Fire endpoint returns 403 or 404
- 403 means you used a live key; sandbox events require a
sk_test_key - 404 means the
submissionIddoes not exist in your workspace
Ready for production?
Switch to your live (sk_live_) key against the same endpoints. Create or manage keys in the control plane, or contact support at https://mediamagic-verify.support.site.