API discovery
OpenAPI and x402 well-known manifests on gateway hosts
Paid APIs on launa gateways publish discovery documents automatically. Agents and indexes fetch them from the gateway hostname — not the seller API.
Gateway routes (public, unpaid)
| Route | Format |
|---|---|
GET https://{api-host}/openapi.json | OpenAPI 3.1 + x-payment-info |
GET https://{api-host}/.well-known/x402.json | Origin manifest (x402 #2582) |
{api-host} is the platform subdomain ({slug}.{platform_domain}) or any verified custom domain.
Documents regenerate on each request from live endpoint config.
Ephemeral (TTL) and disabled endpoints are excluded.
Validate
Fetch the returned public discovery URLs and compare methods, paths, schemas, and payment terms with your configured API. No external checker is required.
launa discovery urls --api-id API_ID --jsonUse launa_discovery_urls for the same discovery URLs through MCP.
API fields
API (POST /apis, PUT /apis/{id})
| Field | Type | Notes |
|---|---|---|
discovery_guidance | string? | Maps to OpenAPI info.x-guidance |
discovery_contact_email | string? | Overrides info.contact.email |
openapi_version | string? | OpenAPI info.version (default 1.0.0) |
Contact email resolution: API override → verified owner email → omit.
Endpoint (POST/PUT .../endpoints)
| Field | Type | Notes |
|---|---|---|
request_schema | object? | JSON Schema for request body |
response_schema | object? | JSON Schema for 200 response |
schema_source | string? | Read-only: openapi | inferred | manual |
clear_schemas | bool? | On update: clear and re-infer |
ttl | number? | Lifetime in seconds (create only). Endpoint removed after first settle or expiry. |
expires_at | string? | Read-only ISO timestamp when ttl was set |
Write semantics:
- Create without schemas → infer minimal schemas (
schema_source: inferred) - OpenAPI import → extract schemas when present (
openapi) - Update with schemas →
manual clear_schemas: true→ re-infer
Set or import a response_schema so agents can read output shape on 402 probes.
Ephemeral endpoints
Set ttl (seconds) when creating an endpoint to make it temporary. The control plane returns expires_at and removes the endpoint after the first successful payment or when the timer elapses. Ephemeral endpoints are excluded from gateway openapi.json and .well-known/x402.json discovery output.
Dashboard: API detail → Endpoints → Lifetime → Temporary.
launa endpoints create --api-id API_ID --path "/pay/{id}" --price-usdc 1.00 --ttl 3600 --jsonawait client.endpoints.create(apiId, {
method: "GET",
path_pattern: "/pay/*",
accepts: [/* ... */],
ttl: 3600,
});GET /apis/{id}/discovery
{
"primary_host": "myapi.example.com",
"hosts": ["myapi.example.com", "api.mycompany.com"],
"openapi_url": "https://myapi.example.com/openapi.json",
"well_known_url": "https://myapi.example.com/.well-known/x402.json",
"endpoint_count": 12,
"discoverable_endpoint_count": 10,
"host_urls": [
{
"host": "myapi.example.com",
"openapi_url": "https://myapi.example.com/openapi.json",
"well_known_url": "https://myapi.example.com/.well-known/x402.json",
"is_primary": true
}
]
}Auth: apis:read.
SDK
Discovery fields are accepted on create and update.
TypeScript
await client.apis.create({
name: "Search",
slug: "search",
upstream_base_url: "https://upstream.example.com",
discovery_guidance: "Use POST /search with a query field.",
discovery_contact_email: "support@example.com",
openapi_version: "1.0.0",
});
const urls = await client.apis.discovery(apiId);
await client.endpoints.update(apiId, endpointId, {
request_schema: { type: "object", properties: { query: { type: "string" } }, required: ["query"] },
response_schema: { type: "object", additionalProperties: true },
});Go
api, err := client.CreateAPI(ctx, launa.CreateAPIInput{
Name: "Search", Slug: "search", UpstreamBaseURL: "https://upstream.example.com",
DiscoveryGuidance: "Use POST /search with a query field.",
DiscoveryContactEmail: "support@example.com",
})
disc, err := client.GetAPIDiscovery(ctx, api.ID)Python
api = client.apis.create({
"name": "Search",
"slug": "search",
"upstream_base_url": "https://upstream.example.com",
"discovery_guidance": "Use POST /search with a query field.",
"discovery_contact_email": "support@example.com",
})
urls = client.apis.discovery(api.id)Language guides: TypeScript · Go · Python
CLI
launa apis create --name Search --slug search --upstream https://upstream.example.com \
--discovery-guidance "Use POST /search." --discovery-contact-email support@example.com
launa apis discovery --id API_ID --json
launa discovery urls --api-id API_ID --json
launa endpoints update --api-id API_ID --endpoint-id EP \
--request-schema '{"type":"object","properties":{"query":{"type":"string"}}}' \
--response-schema '{"type":"object","additionalProperties":true}'Full command list: CLI reference
MCP
| Tool | Purpose |
|---|---|
launa_discovery_urls | GET /apis/{id}/discovery |
launa_set_discovery_guidance | Set guidance / contact / OpenAPI version |
launa_update_endpoint_schemas | Set or clear endpoint JSON Schemas |
launa_create_api | Create API; optional discovery fields on create |
launa_import_openapi | Import ops; schemas persisted when present |
Full tool list: MCP server