Service Manifest
The service manifest is the single source of truth for what an emulator supports. Each service plugin owns its manifest, and the control plane serves it at /_emulate/manifest. Consoles, agents, SDK generators, and tests all read the same manifest, so nothing can claim a capability the emulator does not actually provide.
# The manifest plus the resolved instance and copyable connection snippets
curl -s http://localhost:4001/_emulate/manifest
# The manifest on a service host, before any instance exists
curl -s https://github.emulators.dev/_emulate/manifestThe manifest advertises only the surfaces that match the real service. OpenAPI, GraphQL schemas, MCP manifests, OAuth metadata, and Google discovery documents are useful inputs, but they are not treated as proof that a protocol exists. A curated subset with honest coverage is preferred over a broad fake that quietly lies. See Architecture.
Response shape
GET /_emulate/manifest returns the manifest alongside the resolved instance and connection snippets:
| Field | Description |
|---|---|
manifest | The service manifest described below |
instance | The resolved instance: service, instance, baseUrl, controlBaseUrl, providerBaseUrl. On a service host with no instance this is null and a sampleInstance is shown instead |
connections | Connection snippets resolved against the instance, ready to copy. See Connections |
Manifest fields
| Field | Description |
|---|---|
id, name, description | Service identity, display name, and short description |
surfaces | Supported surfaces such as REST, OAuth, OIDC, GraphQL, MCP, webhooks, UI, and provider-specific, each with a status of supported, partial, or unsupported |
auth | Auth capabilities: API keys, bearer tokens, OAuth client credentials, OAuth authorization code, OIDC, JWT app auth, dynamic client registration, and webhook secrets |
specs | Spec sources with per-operation coverage. Each spec lists its kind, title, optional url, an overall coverage label, and an operations array marking each operation as generated, hand-authored, partial, or unsupported. GET /_emulate/coverage reports these with a summary by status |
scenarios | Named scenarios the instance can load |
seedSchema | The seedable areas of the instance plus an example body that can be POSTed to /_emulate/seed |
stateModel | The collections the instance keeps in state |
resetBehavior | What POST /_emulate/reset does: whether it reseeds and clears the ledger and webhooks |
inspectorTabs | The console tabs this service exposes, such as Overview, Ledger, State, Credentials, Seed, Spec, and Webhooks |
ledger | Request ledger capabilities: recorded fields, redaction, correlation ids, side effects, webhook deliveries, and whether the ledger is persistent on this host. See Request Ledger |
connections | Copyable SDK, CLI, env, curl, config, and MCP snippets, as templates the control plane resolves against the live instance |
docsUrl | The human docs for the service, at https://docs.emulators.dev/<service> |
Connections
Connection snippets are templates with {{placeholders}} that the control plane resolves against the live instance, including {{baseUrl}}, {{controlBaseUrl}}, {{service}}, {{instance}}, {{token}}, {{clientId}}, and {{clientSecret}}. Fetch the resolved snippets directly from GET /_emulate/connections, and pass ?token=, ?client_id=, or ?client_secret= to inject a real credential. This is how a human or agent copies ready-to-run SDK, CLI, or app config without repository context.
Example
{
"manifest": {
"id": "github",
"name": "GitHub",
"description": "Stateful GitHub API emulator.",
"surfaces": [
{ "id": "rest", "kind": "rest", "title": "REST API", "basePath": "/", "status": "supported" },
{ "id": "oauth", "kind": "oauth", "title": "OAuth app flow", "status": "supported" },
{ "id": "webhooks", "kind": "webhooks", "title": "Webhooks", "status": "supported" }
],
"auth": [
{ "id": "token", "title": "Bearer token", "type": "bearer-token", "status": "supported" },
{ "id": "app", "title": "GitHub App JWT", "type": "jwt-app", "status": "supported" }
],
"specs": [
{
"kind": "openapi",
"title": "GitHub REST API",
"coverage": "partial",
"operations": [
{ "operationId": "issues/create", "method": "POST", "path": "/repos/{owner}/{repo}/issues", "status": "hand-authored" },
{ "operationId": "repos/get", "method": "GET", "path": "/repos/{owner}/{repo}", "status": "generated" }
]
}
],
"resetBehavior": { "description": "Resets the instance to its seeded baseline.", "reseeds": true, "clearsLedger": true, "clearsWebhooks": true },
"ledger": { "redactsSensitive": true, "correlationId": true, "webhookDeliveries": true, "sideEffects": true, "persistent": true },
"connections": [
{ "id": "base-url", "title": "Base URL (env)", "kind": "env", "template": "GITHUB_BASE_URL={{baseUrl}}" }
],
"docsUrl": "https://docs.emulators.dev/github"
},
"instance": {
"service": "github",
"instance": "my-run",
"baseUrl": "https://github.my-run.emulators.dev",
"controlBaseUrl": "https://github.my-run.emulators.dev/_emulate",
"providerBaseUrl": "https://github.my-run.emulators.dev"
},
"connections": [
{ "id": "base-url", "title": "Base URL (env)", "kind": "env", "body": "GITHUB_BASE_URL=https://github.my-run.emulators.dev" }
]
}Reset behavior, ledger capabilities, inspector tabs, and the base connection snippets are shared across every emulator because they run on the same core control plane, so per-plugin manifests stay focused on the service-specific surfaces, auth, seed, and SDK details.