Providers
Run an OpenAI-compatible inference endpoint? List it on the marketplace: the gateway routes customer traffic to you, bills at the rates you publish, and shows your lane in the public catalog with measured latency, throughput, and uptime.
The self-serve lane accepts public OpenAI-compatible https endpoints only. If your service needs a native SDK integration, that is a hand-built engagement: contact us instead of registering. Everything here describes what is built today; anything not yet built is marked planned.
As a provider you control three things:
Settled revenue on your lanes accrues to a provider wallet on the platform, net of an agreed platform fee, with payouts on request. The Provider guide covers earnings and day-to-day operations in detail.
Both doors register the same identity: your slug, endpoint, contact and escalation channels, terms acceptance, and data-policy declaration. Neither ever carries a credential.
providers/<your-slug>/manifest.json. The manifest records your terms acceptance in a reviewed, versioned artifact. Listing models is optional; most providers onboard with identity only and add models in bulk inside the platform after merge. A credential-free CI workflow validates the whole file on every PR, forks included.The prompt carries the full manifest schema, the CI checks the PR must pass, and the hard rules (no secrets in the PR, no invented prices or capabilities, no fabricated data-policy values). Fill in the facts section first; the agent does the rest.
Prepare a provider onboarding pull request for the Experiential Labsplatform marketplace. Follow these instructions exactly; do not improvise.## Facts about us (filled in by a human)- Provider name: [DISPLAY NAME]- Desired slug: [slug, lowercase, letter first, matching ^[a-z][a-z0-9._-]{0,63}$]- OpenAI-compatible endpoint base URL: [https://... , public, no query/fragment]- Auth mode: [house_key if we will issue them an API key after merge, or none]- Ops contact email: [email]- Escalation channel: [free text, optional]- Status page: [public https URL, optional]- Terms accepted by: [name and role], version [version], at [ISO timestamp with timezone]- Data policy: retains_prompts=[true/false], retention_days=[int, ONLY ifretains_prompts is true], trains_on_data=[true/false],zero_data_retention=[true/false], policy_url=[public https URL, optional]- Declared limits: max_concurrency=[int > 0, optional], advertised_tps=[number > 0, optional]- Initial models: [list of wire ids with prices, or "none: identity-only PR"]## The taskOpen a PR against https://github.com/experientiallabs/platform (base branchmain) adding exactly one file: providers/<slug>/manifest.json. The directoryname must equal provider.slug inside the file. Touch no other file, with oneexception noted under "CI checks" below.## The JSON schema (unknown keys are rejected everywhere)Top level: {"schema_version": 1, "provider": {...}, "limits": {...}?, "models": [...]?}provider (required object):- slug: string, ^[a-z][a-z0-9._-]{0,63}$- display_name: non-empty string- family: the literal string "openai_compatible" (only value accepted)- base_url: public https URL, <= 2048 chars, no query string, no fragment,no localhost/private/internal hosts- auth_mode: "house_key" or "none"- contact: {"email": required plain address, "escalation": optional string,"status_page": optional public https URL}- terms: {"version": non-empty string, "accepted_by": non-empty string,"accepted_at": ISO timestamp WITH timezone offset, e.g. 2026-08-25T00:00:00Z}- data_policy (required): {"retains_prompts": bool, "retention_days": int >= 0present exactly when retains_prompts is true and omitted when false,"trains_on_data": bool, "zero_data_retention": bool (may be true only whenretains_prompts and trains_on_data are both false), "policy_url": optionalpublic https URL}limits (optional object): {"max_concurrency": int > 0 optional,"advertised_tps": number > 0 optional}models (optional array, may be omitted; wire_id unique within the file):- wire_id: string, ^[A-Za-z0-9][A-Za-z0-9._/:@-]*$- binding: either {"kind": "existing", "slug": "<catalog model slug>"} or{"kind": "new", "model": {"slug": ^[a-z][a-z0-9._-]{0,127}$,"display_name": required, "description": optional,"context_window": optional int > 0, "max_output_tokens": optional int > 0,"input_modalities": optional non-empty unique subset of["text","image","audio","video","pdf"], "huggingface_url": optional,exactly https://huggingface.co/<org>/<repo>, "release_url": optional httpsURL with a dotted host}}- prices: {"input_nano_usd_per_million": int >= 0 required,"output_nano_usd_per_million": int >= 0 required,"cached_input_nano_usd_per_million": optional int >= 0,"reasoning_nano_usd_per_million": optional int >= 0,"effective_at": optional ISO timestamp with timezone}. Unit: integernano-USD per million tokens (1000000000 = $1.00 per million). Omit a rate tomean "no such rate"; never use 0 as a placeholder.- capabilities: object mapping capability name -> bool. Allowed keys ONLY(the engine's capability vocabulary): supports_developer_messages,supports_streaming, supports_streaming_tool_arguments,supports_strict_tools, supports_parallel_tool_calls,supports_structured_text, supports_stop_sequences, supports_image_input,supports_image_url_input, supports_video_input, supports_video_url_input,supports_audio_input, supports_pdf_input, supports_pdf_url_input,supports_media_handle_input, supports_async_tools,supports_mid_turn_steering, supports_reasoning_effort_update,reasoning_effort_required, reports_refusals, reports_cached_input_tokens,reports_reasoning_tokens. Every model entry MUST declare"supports_streaming": true.- context_window: optional int > 0. region: optional string.- deprecation: optional {"eol_at": timezone-aware timestamp,"replacement_slug": optional string}. Omit for new lanes.## CI checks the PR must pass (workflow: "Provider manifests")1. Schema: the file parses against the schema above; one bad entry rejectsthe whole file; the directory name equals provider.slug.2. Identity guards: the provider slug is not already registered; a wire idalready routed in the catalog may not be proposed as a new model orre-bound to a different catalog model; a proposed new slug may notcollide with or normalize onto an existing model; binding"kind": "existing" requires the slug to exist in the catalog. If CIreports needs-alias-entry, the fix is to add the exact CANONICAL_ALIASESentry the message spells out (file explabs/gateway/model_aliases.py);that is the only other file the PR may touch, and only when CI asks.3. A :free wire id must bind a catalog slug ending in -free.4. Serving completeness: supports_streaming true on every model; ifreports_cached_input_tokens or reports_reasoning_tokens is true, thematching rate must be present.5. Price sanity: all rates are non-negative integers in nano-USD permillion tokens, taken from the provider's real published pricing.6. Reachability probe: credential-free GET {base_url}/models must completea TLS request. Any HTTP status (401, 404, 5xx) counts as reachable; DNSfailure, connection failure, or resolution to a private IP fails.## Do NOT- Do not put any API key, token, or secret anywhere in the PR. Credentialsare exchanged out-of-band after merge; a PR containing a secret is closedand the secret must be rotated.- Do not bind a wire id to a different model's identity, and do not proposea new model for something the catalog already carries under another name.If unsure whether a model exists in the catalog, bind nothing and say soin the PR description; identity-only PRs are normal.- Do not invent prices, use negative numbers, use floats for money, or use0 to mean "unknown". Omit optional rates you do not have.- Do not invent capability keys or set capabilities you have not verifiedagainst the real endpoint.- Do not fabricate the data_policy values; they are contractually binding.If a value is not confirmed by a human, stop and ask.- Do not touch any file other than providers/<slug>/manifest.json (and aCANONICAL_ALIASES entry only when CI explicitly asks for it).## PR descriptionState who the provider is, link the pricing page and the data policy page,and note whether models are included or the PR is identity-only.## What happens after mergeA platform admin links the provider's platform organization (it gains aInference page in the sidebar), the API key is exchanged out-of-band andstored in Vault (house_key mode), and model additions, price changes,limits, and smoke checks are then managed inside the platform asadmin-approved requests, not through further PRs. New lanes start ascanaries at the tail of the fallback chain. Price increases require aneffective date at least 7 days out; decreases apply on approval.
Registration requires a machine-readable declaration of what you do with customer prompt and completion data: whether content persists after the response (and for how long), whether you train on it, and an explicit zero-data-retention claim that may only be true when both are false. The declaration is self-reported: the platform surfaces it to customers, who filter and choose providers by it, and binds you to it contractually through the terms acceptance recorded alongside. A false declaration is a terms violation and grounds for immediate offboarding. If your practice changes, update the declaration before the change takes effect.
house_key endpoints you issue us an API key through a private channel after registration. It is stored in our secrets vault, never appears in a PR or the manifest, and is never displayed back once stored (rotation replaces it).From there, day-to-day changes never go through PRs: you submit model, price, and limit requests from the Inference page and a platform admin approves them. The Provider guide is the operational reference once you are onboarded.