Documentation 40

Guide · Azure DevOps

How do I test an Azure DevOps integration without a real organization?

You do not need one. Point your client at a read-only Azure DevOps replica that already holds the olympus-labs data set, and your code runs unchanged.

01 / The one change

Swap the base URL. Nothing else.

Your client talks to dev.azure.com. Point it at ado.sandboxapis.dev instead: same paths, same JSON, same headers, same status codes. No organization to create, no seed script.

For CI, use a pinned host. This page uses ado-7-1-g12.snap.sandboxapis.dev, the newest pin for Azure DevOps, which answers the same bytes on every run, so an assertion written today still holds next month.

The live host, ado.sandboxapis.dev, re-rolls daily and can carry a newer generation of the data set than ado-7-1-g12.snap.sandboxapis.dev; every answer on this page is for ado-7-1-g12.snap.sandboxapis.dev.

02 / Run it now

One request, no account.

request.sh
curl -s "https://ado-7-1-g12.snap.sandboxapis.dev/olympus-labs/_apis/git/repositories?api-version=7.1"

It answers with the git repositories in the olympus-labs project, parthenon among them, each with its default branch and its clone URLs, in Azure DevOps' own count and value envelope.

With a real client, the verified quickstart for requests runs against the live host on every check. It prints the repository count and name, then the completed pull requests on it. For CI, change its base URL to https://ado-7-1-g12.snap.sandboxapis.dev.

python
# pip install requests==2.32.5

import requests

org = "https://ado.sandboxapis.dev/olympus-labs"   # the organization URL

s = requests.Session()
s.auth = ("", "any-token")            # any PAT is accepted
s.params = {"api-version": "7.1"}

repos = s.get(f"{org}/_apis/git/repositories").json()
repo = repos["value"][0]["name"]

prs = s.get(
    f"{org}/olympus-labs/_apis/git/repositories/{repo}/pullrequests",
    params={"searchCriteria.status": "completed"},
).json()

print(repos["count"], "repos:", repo)
print(prs["count"], "completed PRs, newest:", prs["value"][0]["title"])

What it prints always contains repos: parthenon and completed PRs, newest:.

03 / Writes

A write gets Azure DevOps's own error shape.

Every host is read-only. A write answers 403 with Azure DevOps's own error body, naming what you tried, so your client's existing error handling meets a shape it knows.

403 · application/json
curl -s -X POST "https://ado-7-1-g12.snap.sandboxapis.dev/olympus-labs/olympus-labs/_apis/git/repositories/parthenon/pullrequests?api-version=7.1" -H 'content-type: application/json' -d '{"title":"test"}'

{"$id":"1","innerException":null,"message":"TF400813: This universe is read-only. See what's covered at https://sandboxapis.dev/coverage. (You tried to POST /olympus-labs/olympus-labs/_apis/git/repositories/parthenon/pullrequests.) Tell us what you needed to write: https://sandboxapis.dev/feedback","typeName":"Microsoft.TeamFoundation.Framework.Server.UnauthorizedRequestException, Microsoft.TeamFoundation.Framework.Server","typeKey":"UnauthorizedRequestException","errorCode":0,"eventId":3000}

04 / Where it stops

Coverage is counted, not claimed.

205 of 232 Azure DevOps read surfaces are served and verified against Azure DevOps's own published spec. A call to one that is not covered returns a 404 with an X-SandboxAPIs-Coverage header, never invented data. The row-by-row list is on the Azure DevOps reference and the coverage page.

Next: read the Azure DevOps quickstart, or run the four-hop walk to watch one incident cross four services.

What this is not

Read this before you rely on it.

SandboxAPIs is read-only: a write returns the provider's own error unless your key has opted in to scratch writes, and those never reach anybody else. Coverage is bounded, and the manifest that says exactly where it stops is public. The data is a simulated company, not yours and not a copy of anybody's. And it reproduces what each vendor documents and publishes, not the vendor's undocumented behaviour, so keep one test against the real service for that.