# Sandbox or test environment documented

> An agent cannot safely integrate against a production endpoint; a documented sandbox is the difference between a working trial and a support ticket.

- Source: /checks/sandbox-environment
- Site: AgenticWebScore
- Language: English

---
An agent cannot safely integrate against a production endpoint; a documented sandbox is the difference between a working trial and a support ticket.

| Property | Value |
| --- | --- |
| Check id | `sandbox-environment` |
| Dimension | Protocol Discovery (25%) |
| Tier | Recommended — pool 20 pts |
| Weight inside tier | 2 |
| Impact | Medium |
| Maturity | Experimental — An early convention that may still change shape. |
| Conditional | No |
| Publishing skill | `sandbox-environment` |
| Standards | — |

## What the scanner requests

- `/docs/sandbox`
- `/sandbox`
- `/developers/sandbox`
- `/docs`

## What is measured

The scanner reads the OpenAPI description the site advertises and the developer documentation it links, and looks for a non-production base URL declared as such: a servers entry whose host differs from the production host and whose description names a sandbox, staging or test environment, together with a stated way to obtain test credentials and a statement of what the sandbox does not contain. It passes when that base URL was requested by the scan, answered 200 anonymously, and the source declaring it names the URL, the credential path and what the sandbox excludes - a callable base URL and test keys still do not tell an agent whether live data sits behind them. It partially passes when a sandbox is mentioned without a callable base URL, without a credential path or without a statement of what it excludes, and when the declared base URL answered an error or its response was not observed at all - a URL on another host, or one outside the probe set, was never fetched, and an unobserved endpoint is never reported as callable. It is reported as not scored and excluded from the denominator unless the site has been positively identified as a SaaS product or an API/developer platform.

## Reproduce it yourself

You do not have to take our word for any of this. Run the same measurement against your own domain:

```bash
DOMAIN=https://your-domain.example
{ curl -sS "$DOMAIN/openapi.json" | jq -r '.servers[]?.url' 2>/dev/null | grep -iE 'sandbox|staging|test'; curl -sSL "$DOMAIN/docs/sandbox" | grep -oiE 'https://[a-z0-9.-]*(sandbox|staging)[a-z0-9./_-]*'; } | sort -u | while read -r u; do printf '%s -> ' "$u"; curl -sS -o /dev/null -w '%{http_code} %{content_type}\n' -L "$u"; done
```

## The fix

This is the artifact to ship. It is the complete change, not a description of one.

```json
{
  "openapi": "3.1.0",
  "info": {
    "title": "Example API",
    "version": "1.4.0",
    "description": "Sandbox base URL: https://api.sandbox.example.com/v1 - the same contract as production over separate data. Test keys are issued at https://example.com/docs/sandbox. The sandbox holds no live payments and no real customer records, and its data resets nightly."
  },
  "servers": [
    { "url": "https://api.example.com/v1", "description": "Production - live data and live billing" },
    { "url": "https://api.sandbox.example.com/v1", "description": "Sandbox - test keys only, data reset nightly" }
  ],
  "paths": {
    "/ping": {
      "get": {
        "operationId": "ping",
        "summary": "Liveness check, safe to call with a sandbox key",
        "responses": { "200": { "description": "Service reachable" } }
      }
    }
  }
}
```

> Merge the two servers entries into the OpenAPI document you already publish rather than replacing it: OpenAPI standardises servers but says nothing about test keys, sandbox tenants or data resets, so those can only be stated as info.description prose — and the sandbox has to be its own origin that answers an anonymous request. The scanner only counts a base URL whose response it observed, so a sandbox on a different host from the scanned site is reported as unobserved rather than as callable. The declaring source also has to say what the sandbox excludes — no live data, test data only, resets nightly — because that statement is part of what the check requires before it will pass.

## Related checks

| Check | Tier | Impact | Same skill |
| --- | --- | --- | --- |
| `mcp-card` — MCP server card | Essential | High | — |
| `openapi` — OpenAPI definition | Essential | High | — |
| `oauth-discovery` — OAuth discovery documents | Essential | High | — |
| `api-catalog` — API catalog | Recommended | Medium | — |
| `agent-skills` — Agent Skills declaration | Recommended | Medium | — |
| `a2a-card` — A2A agent card | Recommended | Medium | — |
| `a2a-signed` — Cryptographically signed agent card | Emerging | Medium | — |
| `auth-md` — /auth.md agent authentication guide | Emerging | Medium | — |
