API de máquina del proveedor
La API para máquinas del marketplace de proveedores: crea una clave sk-sup-… en el gabinete, llama a cada endpoint con Authorization: Bearer, incorpora conexiones en lotes y lee conexiones, ofertas, cambios de precio, ganancias y estadísticas.
El gabinete del proveedor tiene una interfaz para máquinas: un proveedor puede incorporar cuentas en bloque y leer sus propias conexiones, ofertas, precios, historial de cambios de precio, ganancias y estadísticas desde un script, usando una clave de API con alcance de proveedor en lugar de una sesión del navegador.
Esto es adicional. El panel del navegador no cambia y las rutas de máquina ensamblan los mismos payloads que usan las páginas del panel, por lo que las dos superficies no pueden informar números diferentes.
Obtener una clave
Las claves de máquina se crean y revocan en el panel del proveedor. El token completo se muestra una vez, al crearlo, y nunca vuelve a devolverse.
- Abre el panel del proveedor y busca la sección Machine API keys.
- Asigna una etiqueta a la clave (opcional) y presiona «crear».
- Copia el token inmediatamente. Comienza con
sk-sup-. - Guárdalo en un gestor de secretos o en una variable de entorno. Nunca lo incluyas en un commit ni lo envíes en un mensaje de soporte.
Endpoints de gestión de gabinetes
Estas rutas usan la sesión del panel o el token de seguimiento. Deliberadamente no aceptan una clave de máquina, para que una clave de máquina filtrada no pueda crear ni revocar otras claves.
| Parámetro | Tipo | Descripción |
|---|---|---|
GET /api/marketplace/suppliers/me/api-keys | list | Claves incluidas: id, label, prefix, active, lastUsedAt, createdAt. Nunca el token ni su hash. |
POST /api/marketplace/suppliers/me/api-keys | mint | Cuerpo { "label"?: string }. Devuelve { "key": "sk-sup-…", "apiKey": { … } } — la única vez que aparece el token. |
DELETE /api/marketplace/suppliers/me/api-keys/{id} | revoke | Revoca una clave. 404 cuando el id no pertenece a quien realiza la solicitud. |
Autenticación
Cada ruta de máquina requiere la clave del proveedor como token bearer:
Authorization: Bearer sk-sup-<64 hex>curl https://getvibeapi.com/api/marketplace/suppliers/api/v1/connections \
-H "Authorization: Bearer $SUPPLIER_API_KEY"Una solicitud resuelve la clave a exactamente un proveedor, y cada consulta se filtra por ese id. La revocación está limitada tanto por el id de la clave como por su propietario, de modo que un proveedor no puede revocar la clave de otro. Nunca registres ni transmitas la clave.
401, para que quien realiza la llamada no pueda distinguir los casos. Envía la clave únicamente mediante HTTPS.Endpoints de lectura
Todos son GET, se autentican con una clave de API y están limitados al proveedor autenticado. El dinero en micro-USD se devuelve como cadenas; los recuentos de tokens son números.
Conexiones
Las cuentas conectadas del proveedor, cada una con lo que ha ganado (solo lo que se puede pagar).
{
"connections": [
{
"id": "…",
"connectionType": "subscription-api-key",
"subscriptionProductLabel": "…",
"verifiedEndpoint": "https://…",
"status": "ACTIVE",
"enabled": true,
"verificationState": "verified",
"verifiedBy": "…",
"label": "nightly-1",
"account": "…",
"verifiedModels": ["…"],
"servingModels": ["…"],
"lastVerifiedAt": "2026-09-18T09:00:00.000Z",
"proxy": "…",
"proxySource": "pool",
"proxyCountry": "de",
"proxyExpiresAt": "2026-10-18T09:00:00.000Z",
"proxyExpiryDays": 30,
"proxyLost": false,
"probedVia": "…",
"lastError": null,
"needsReauth": false,
"accountLimits": null,
"accountLimitsSource": null,
"accountLimitsCheckedAt": null,
"earnings": { "earnedMicros": "1250000", "requestCount": 42 },
"createdAt": "2026-09-01T09:00:00.000Z"
}
]
}Ofertas
Las ofertas del proveedor con los precios actuales y el porcentaje en tiempo real de la tarjeta oficial.
{
"offers": [
{
"id": "…",
"baseModel": "claude-opus-5",
"claimedModel": "claude-opus-5",
"providerLabel": "…",
"status": "ACTIVE",
"statusReason": null,
"inputMicrosPer1M": "1000000",
"outputMicrosPer1M": "2000000",
"cacheReadMicrosPer1M": null,
"blendedPctOfOfficial": "0.42",
"officialPrice": null,
"pctOfOfficial": 42,
"trafficTier": "…",
"cooldownUntil": null,
"cooldownReason": null,
"firstVerifiedAt": "2026-09-01T09:00:00.000Z",
"activatedAt": "2026-09-01T09:00:00.000Z",
"lastManualPriceChangeAt": null,
"maxConcurrentRequests": 8,
"servingEnabled": true
}
]
}Historial de cambios de precios
El registro de cambios de precio de una de las propias ofertas del proveedor: cambios planificados, aplicados y cancelados. Una oferta perteneciente a otro proveedor responde 404.
{
"offerId": "…",
"schedules": [
{
"id": "…",
"offerId": "…",
"priceInUsd": "1.000000",
"priceOutUsd": "2.000000",
"effectiveFrom": "2026-10-01T00:00:00.000Z",
"createdAt": "2026-09-18T09:00:00.000Z",
"cancelledAt": null,
"appliedAt": null
}
]
}Estadísticas
La misma estructura que muestra la página de estadísticas del gabinete: totals, una serie de daily de 14 días y un desglose de byOffer por oferta.
{
"totals": {
"requests": 12000,
"successes": 11880,
"errors": 90,
"timeouts": 30,
"successRatePct": 99,
"promptTokens": 9000000,
"completionTokens": 4000000,
"cacheTokens": 2500000,
"sourceCostMicros": 12345678,
"avgLatencyMs": 812.4,
"p50LatencyMs": 640,
"p95LatencyMs": 2100
},
"daily": [
{ "date": "2026-09-05", "requests": 800, "successes": 795, "errors": 4, "promptTokens": 600000, "completionTokens": 250000, "sourceCostMicros": 900000 }
],
"byOffer": [
{ "offerId": "…", "baseModel": "claude-opus-5", "requests": 12000, "successRatePct": 99, "promptTokens": 9000000, "completionTokens": 4000000, "tokens": 13000000, "sourceCostMicros": 12345678, "hitRate": 0.28, "effTotal": 3.14, "rank": 1 }
]
}Ingresos
Hasta 500 intentos de ruta recientes aptos para liquidación, del más reciente al más antiguo.
{
"events": [
{
"id": "…",
"baseModel": "claude-opus-5",
"result": "SUCCESS",
"promptTokens": "1200",
"completionTokens": "800",
"paidMicros": "420000",
"settlementEligible": true,
"finishedAt": "2026-09-18T09:00:00.000Z",
"settlementStatus": "pending_or_settled"
}
]
}Crear conexiones
Crea una cuenta o un paquete completo a partir de una credencial que ya tienes, sin un intercambio de OAuth en el navegador. El cuerpo es un elemento, un sobre { "items": [ … ] }, o un arreglo sin envoltorio. Los tres se normalizan al mismo resultado por elemento. La ruta anterior /api/marketplace/suppliers/api/v1/connections/batch es un alias del mismo controlador.
Estructuras de credenciales
Cada elemento identifica el grupo con provider (el nombre legible del grupo, por ejemplo, codex o claude-code) y lleva exactamente una forma de credencial:
| Parámetro | Tipo | Descripción |
|---|---|---|
codexAuthJson | codex-bundle | El archivo ~/.codex/auth.json de Codex CLI pegado literalmente: auth_mode, tokens.{id_token,access_token,refresh_token,account_id}, _meta.{plan_type,email}. |
accessToken + refreshToken | claude-tokens | El token de acceso de Claude Code (sk-ant-oat01-…) y su token de actualización. |
refreshToken | antigravity-refresh | Un token de actualización de Antigravity. |
apiKey | api-key | Una clave de API de suscripción lista para usar. |
bindToken + oauthCode | oauth-code | El resultado de OAuth del flujo del navegador, cuando lo usaste en lugar de pegar un paquete. |
Cada elemento lleva un proxy de salida operativo y no existe ninguna conexión sin proxy. Pasa tu propio proxy, o un proxyCountry para dar preferencia a uno de los nuestros; si no pasas ninguno, el servidor asigna y valida uno propio antes de realizar cualquier solicitud al proveedor. Si no se puede validar ningún proxy del grupo, el elemento se rechaza como proxy_unavailable. externalId se devuelve sin cambios para la correlación.
curl https://getvibeapi.com/api/marketplace/suppliers/api/v1/connections \
-H "Authorization: Bearer $SUPPLIER_API_KEY" \
-H "Content-Type: application/json" \
--data @pack.jsonpack.json — un proxy propio y un proxy de grupo de países:
[
{
"externalId": "codex-1",
"provider": "codex",
"connectionLabel": "nightly-codex-1",
"codexAuthJson": "{\"auth_mode\":\"chatgpt\",\"tokens\":{\"id_token\":\"…\",\"access_token\":\"…\",\"refresh_token\":\"…\",\"account_id\":\"…\"},\"_meta\":{\"plan_type\":\"plus\",\"email\":\"…\"}}",
"proxy": { "scheme": "http", "host": "proxy.example.com", "port": 8899, "username": "u", "password": "p" },
"offers": [{ "baseModel": "deepseek-v4.1-flash", "inputMicrosPer1M": 1000000, "outputMicrosPer1M": 2000000 }]
},
{
"externalId": "claude-1",
"provider": "claude-code",
"connectionLabel": "nightly-claude-1",
"accessToken": "sk-ant-oat01-…",
"refreshToken": "sk-ant-ort01-…",
"proxyCountry": "de",
"offers": [{ "baseModel": "claude-opus-5", "inputMicrosPer1M": 1000000, "outputMicrosPer1M": 2000000 }]
}
]duplicate por elemento y no escribe nada nuevo. Reintenta los elementos fallidos del paquete uno por uno.El éxito parcial es el contrato
Cada elemento se valida frente al proveedor y se escribe por separado. Una fila incorrecta nunca hace fallar el lote, y un elemento solo se informa como ok: true después de confirmar su fila de conexión.
{
"supplierId": "…",
"accepted": 1,
"rejected": 1,
"results": [
{
"index": 0,
"externalId": "row-1",
"ok": true,
"connectionId": "…",
"connectionType": "subscription-api-key",
"verificationState": "verified",
"verifiedModels": ["…"],
"subscriptionProduct": "codebuddy-cn",
"verifiedEndpoint": "https://…",
"latencyMs": 210
},
{
"index": 1,
"externalId": "row-2",
"ok": false,
"code": "bind_session_invalid",
"error": "the authorization session expired or did not match"
}
]
}Códigos de rechazo por elemento
| Parámetro | Tipo | Descripción |
|---|---|---|
invalid_credential | code | El proveedor rechazó el formato o el valor de la credencial. |
connection_type_unavailable | code | Ese tipo de conexión aún no está disponible. |
subscription_product_unavailable | code | El producto de suscripción indicado no está disponible. |
provider_unavailable | code | El proveedor seleccionado no está disponible. |
bind_session_invalid | code | La sesión de OAuth expiró o no coincidió. |
proxy_required | code | El proxy resuelto no tenía una URL utilizable. (A un elemento que no especifica ningún proxy se le asigna uno en su lugar.) |
proxy_unavailable | code | No se pudo demostrar la existencia de un proxy de grupo para el país solicitado ni para ningún país cuando no se especificó uno. |
proxy_race_lost | code | Otra conexión acaba de tomar ese proxy. |
probe_failed | code | El proveedor rechazó la credencial durante la comprobación en tiempo real. |
model_not_served | code | La cuenta no confirmó un modelo solicitado; los modelos rechazados están en el array "models" del elemento. |
duplicate | code | La misma huella de credencial ya está conectada. |
encryption_unavailable | code | El cifrado de credenciales no está configurado en el proyecto. |
internal_error | code | Un error inesperado del servidor. Vuelve a intentar el elemento individual más tarde. |
Comprobación previa del proxy
Prueba un proxy antes de entregar una credencial: proporciona tu propio proxy o un proxyCountry y el servidor abre el mismo túnel que usará para la conexión y accede a un host neutral a través de él. Esto solo es una comprobación previa: la llamada de creación ejecuta la misma comprobación y rechaza la solicitud antes de intercambiar un token o consultar al proveedor, por lo que un proxy defectuoso nunca consume una credencial.
curl https://getvibeapi.com/api/marketplace/suppliers/proxy-check \
-H "Content-Type: application/json" \
-d '{ "proxy": { "scheme": "http", "host": "proxy.example.com", "port": 8899, "username": "u", "password": "p" } }'{ "ok": true, "outcome": "ok", "latencyMs": 42 }422 con outcome: "proxy_failed"; un país sin un proxy disponible en el grupo gratuito responde 409 con proxy_unavailable.OAuth en el navegador (cabinet)
El flujo OAuth propio de dos pasos del panel, para cuando vinculas una cuenta en un navegador en lugar de tener un paquete.
Cuerpo { "connectionType": "claude-code" | "codex-oauth" }. Devuelve el authorizeUrl que se debe abrir y el bindToken firmado que vincula el código con la sesión PKCE. No se conserva nada.
Envía la concesión completada: el bindToken más el oauthCode y los mismos campos offers / proxy que en un elemento de creación. El proxy se verifica antes de intercambiar el código. Estas dos rutas usan la sesión del panel; una clave de máquina no puede llamarlas (usa POST /connections con bindToken + oauthCode en su lugar).
Límites de frecuencia
| Parámetro | Tipo | Descripción |
|---|---|---|
Create connections | limit | Como máximo, 25 elementos por llamada. 20 llamadas por hora por proveedor, además de un límite de 120/hora por IP. Cada elemento es una comprobación saliente del proveedor. |
Proxy pre-flight | limit | 30 llamadas por hora por IP. Cada llamada abre un túnel a un host neutral. |
Read endpoints | limit | 600 solicitudes por hora por IP para la superficie compartida de la máquina, a menos que una ruta establezca su propio límite. |
Cabinet key management | limit | 120 por hora por IP para listar claves, 20 por hora para crear claves y 60 por hora para revocarlas. |
429 incluye Retry-After en segundos. Espera y vuelve a intentarlo después de ese intervalo; volver a enviar la misma credencial se rechaza como duplicate debido a la huella digital de credencial única.Respuestas de error
| Parámetro | Tipo | Descripción |
|---|---|---|
401 | status | Falta la clave de API, es desconocida o fue revocada. Un único mensaje fijo impide que quien realiza la llamada distinga entre estos casos. |
404 | status | La ruta no existe en este proyecto (el marketplace no está habilitado aquí) o la oferta indicada pertenece a otro proveedor. |
429 | status | Límite de frecuencia. El limitador compartido devuelve Retry-After. |
400 | status | JSON con formato incorrecto o un lote que supera el límite. El cuerpo indica cuál es la entrada no válida. |
El documento OpenAPI incluye una descripción legible por máquinas de cada endpoint en /api/openapi. Indica esta dirección a un generador de clientes OpenAPI para crear un cliente tipado.