Api.Airforce
PROVEEDOR OAUTH

Iniciar sesión con Airforce

Permite que tus usuarios autoricen a tu aplicación a acceder a su cuenta de Api.Airforce. Flujo estándar OAuth 2.0 Authorization Code con PKCE.

Para quién es esto

Estás creando una aplicación (playground, agente, cliente móvil, …) y quieres que tus usuarios conecten su cuenta de Airforce para ejecutar chat o generación de imágenes a través de tu interfaz sin compartir contigo su API Key en bruto. Usa este flujo.

Obtendrás un access_token opaco (24h TTL) limitado a lo que tu app solicitó y el usuario aprobó. Úsalo como cabecera Bearer contra los endpoints /v1/* o /oauth/userinfo.

1. Obtén un client_id + client_secret

La Fase 1 es un registro gestionado por el administrador. Escríbenos con:

  • Nombre de la app (se muestra en la pantalla de consentimiento a tus usuarios)
  • Descripción de una frase
  • URL del sitio web (opcional, se muestra en el consentimiento)
  • URL del logo cuadrado (opcional)
  • Una o más redirect_uri exactas (solo https://, excepto http://localhost para desarrollo)
  • Qué scopes necesitas (ver abajo)

Te devolvemos client_id y un client_secret. Guarda el secret en el lado del servidor — si eres una SPA pura o app nativa sin backend, puedes omitir el secret y confiar solo en PKCE.

2. Scopes

ScopeQué concede
profileLee el objeto user vía /oauth/userinfo (id, username, plan, emails vinculados cuando estén verificados).
chatPOST /v1/chat/completions, /v1/messages, /v1/messages/count_tokens, /v1/responses.
imagesPOST /v1/images/generations.
keys:readReservado — lista las API Keys de Airforce del usuario (Phase 2).
keys:write (SENSIBLE)Reservado — crea + revoca las API Keys de Airforce del usuario (Phase 2). Scope sensible.

Múltiples scopes se separan con espacios en el parámetro de consulta scope : scope=profile chat images.

3. El flujo

3.1 Generar par PKCE

En tu cliente, antes de redirigir a /oauth/authorize, genera un verifier aleatorio y el challenge SHA-256 correspondiente.

// In your app, before redirecting to /oauth/authorize:
const verifier = randomString(64); // 43..128 chars [A-Z][a-z][0-9]-._~
const challenge = base64UrlNoPad(sha256(verifier));
sessionStorage.setItem('airforce_pkce_verifier', verifier);

3.2 Redirigir a /oauth/authorize

Construye la URL de autorización y envía al usuario allí. Verá nuestra pantalla de consentimiento, decidirá y será redirigido de vuelta a ti.

https://api.airforce/oauth/authorize?
  response_type=code
  &client_id=airforce_xxxxxxxxxxxxxxxxxxxxxxxxx
  &redirect_uri=https://your.app/oauth/callback
  &scope=profile chat
  &state=<random opaque>
  &code_challenge=<base64url(sha256(verifier))>
  &code_challenge_method=S256

El usuario aterriza en nuestra pantalla de consentimiento, inicia sesión (si aún no lo ha hecho), y aprueba o rechaza. Redirigimos de vuelta a tu redirect_uri con un ?code=… de corta duración al aprobar, ?error=access_denied al rechazar. Tu state original se devuelve — verifica que coincida.

3.3 Intercambiar el code por access_token

Desde tu backend, intercambia el code (más el verifier de PKCE) por un access token.

curl -X POST https://api.airforce/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  --data-urlencode "grant_type=authorization_code" \
  --data-urlencode "code=$CODE" \
  --data-urlencode "redirect_uri=https://your.app/oauth/callback" \
  --data-urlencode "code_verifier=$VERIFIER"

Respuesta (24h TTL):

{
  "access_token": "airf_oat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "token_type": "Bearer",
  "expires_in": 86400,
  "scope": "profile chat"
}

3.4 Usar el token

Llama al endpoint userinfo o cualquier ruta /v1/* que los scopes otorgados permitan:

# Profile lookup
curl https://api.airforce/oauth/userinfo \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# Chat (requires scope=chat)
curl https://api.airforce/v1/chat/completions \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Hi"}]}'

Respuesta de /oauth/userinfo

{
  "id": "user-uuid",
  "username": "foo",
  "plan": "free",
  "is_admin": false,
  "email": "[email protected]",
  "email_verified": true,
  "github_email": "[email protected]",
  "discord_username": "foo#1234"
}

Campos como email, github_email, discord_username solo aparecen cuando el usuario los ha verificado / vinculado realmente. Planifica tanto su presencia como ausencia.

Revocar un token

Cuando un usuario cierre sesión en tu app, revoca el token para que no siga facturando a su cuenta en segundo plano:

curl -X POST https://api.airforce/oauth/revoke \
  --data-urlencode "token=$ACCESS_TOKEN"

RFC 7009. Siempre devuelve 200 independientemente de si el token existía (sin oracle).

Notas de seguridad

  • PKCE es obligatorio para clientes públicos (sin client_secret del lado del servidor). Solo aceptamos S256 — code_challenge_method=plain se rechaza.
  • redirect_uri es de coincidencia exacta. Sin coincidencia por prefijo / comodines. Si necesitas múltiples entornos, registra una URI por entorno.
  • Los tokens tienen una TTL de 24h y aún no hay refresh tokens — cuando expiren, vuelve a ejecutar el flujo del usuario por /oauth/authorize otra vez. Para agentes de larga duración, pide al inicio y guarda el token en almacenamiento seguro.
  • No almacenes client_secret en código del cliente. Si tu app es una SPA solo de navegador o cliente nativo, regístrate sin servidor y confía en PKCE.
  • Los usuarios pueden revocar tu app en cualquier momento desde su dashboard → pestaña Apps. Maneja el 401 reiniciando el flujo OAuth.
  • Cobertura de la Fase 1: Los bearer tokens OAuth funcionan en /v1/chat/completions, /v1/messages, /v1/messages/count_tokens, /v1/responses, /v1/images/generations, y /oauth/userinfo. Los endpoints de audio, vídeo, voz y character todavía requieren una API Key regular de Airforce en la Fase 1.

Registrarse

Escribe a [email protected] o contáctanos en Discord con los detalles de registro listados arriba. Te enviaremos tus credenciales en unas pocas horas.

¿Problemas con la configuración o quieres una clave gratis? Pregunta a la comunidad en nuestro Discord.

Únete a nuestro Discord