Citeri Developers
Ayuda citeri.es

Empezar

Autenticación

Las integraciones que leen o cambian datos de un negocio actúan siempre en nombre de su titular y solo sobre ese negocio. Hay dos formas de conseguir acceso: OAuth 2.1, que es la recomendada, o una clave de API que el titular crea en su panel.

MétodoPara quéQuién lo concede
OAuth 2.1 + PKCEAsistentes de IA y aplicaciones que conectan la cuenta de un negocioEl titular, iniciando sesión en Citeri y aceptando
Clave de API ctk_…Clientes MCP sin soporte de OAuth o integraciones de servidor a servidorEl titular, en su panel → Developer → Claves de API

Las rutas públicas de disponibilidad y el widget de reservas no necesitan autenticación.

Descubrimiento#

Citeri publica sus metadatos para que el cliente no tenga que configurar nada a mano:

DocumentoURL
Servidor de autorización (RFC 8414)https://citeri.es/.well-known/oauth-authorization-server
OpenID Connecthttps://citeri.es/.well-known/openid-configuration
Recurso protegido del MCP (RFC 9728)https://citeri.es/.well-known/oauth-protected-resource/api/mcp
curl https://citeri.es/.well-known/oauth-authorization-server
CampoValor
authorization_endpointhttps://citeri.es/oauth/authorize
token_endpointhttps://citeri.es/oauth/token
registration_endpointhttps://citeri.es/oauth/register
grant_types_supportedauthorization_code
code_challenge_methods_supportedS256
token_endpoint_auth_methods_supportednone (clientes públicos con PKCE)
scopes_supportedopenid, citeri

1. Registrar el cliente#

Registra tu aplicación una vez con registro dinámico (RFC 7591). Solo se admiten clientes públicos: sin client_secret y siempre con PKCE.

POSThttps://citeri.es/oauth/register
curl -X POST https://citeri.es/oauth/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "Mi integración",
    "redirect_uris": ["https://mi-app.example/callback"],
    "token_endpoint_auth_method": "none"
  }'

Respuesta 201:

JSON
{
  "client_id": "8f3c…",
  "client_name": "Mi integración",
  "redirect_uris": ["https://mi-app.example/callback"],
  "grant_types": ["authorization_code"],
  "token_endpoint_auth_method": "none"
}

2. Pedir autorización#

Genera un code_verifier aleatorio (43–128 caracteres), calcula code_challenge = BASE64URL(SHA256(code_verifier)) y abre en el navegador:

URL de autorización
https://citeri.es/oauth/authorize
  ?response_type=code
  &client_id=CLIENT_ID
  &redirect_uri=https%3A%2F%2Fmi-app.example%2Fcallback
  &code_challenge=CODE_CHALLENGE
  &code_challenge_method=S256
  &scope=citeri
  &state=VALOR_ALEATORIO

El titular inicia sesión con su cuenta de Citeri, ve qué podrá hacer la integración y acepta. Citeri vuelve a tu redirect_uri con ?code=…&state=…. Comprueba que state coincide con el que enviaste.

El redirect_uri debe ser exactamente uno de los registrados. El código caduca a los 10 minutos y solo se puede canjear una vez.

3. Canjear el código#

POSThttps://citeri.es/oauth/token
curl -X POST https://citeri.es/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d grant_type=authorization_code \
  -d code=CODIGO \
  -d client_id=CLIENT_ID \
  -d redirect_uri=https://mi-app.example/callback \
  -d code_verifier=CODE_VERIFIER
JSON
{
  "access_token": "…",
  "token_type": "Bearer",
  "expires_in": 31536000,
  "scope": "citeri"
}

Si pides el scope openid, la respuesta incluye además un id_token con el email de la cuenta. Si mandas el parámetro resource (RFC 8707), debe ser la URL del MCP: https://citeri.es/api/mcp.

No hay refresh tokens. El token dura un año. Cuando caduque o el titular lo revoque, repite la autorización.

Usar el token#

Envía el token en la cabecera Authorization de cada petición al servidor MCP. El token queda ligado a un solo negocio: el que el titular eligió al autorizar.

curl
curl https://citeri.es/api/mcp \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Claves de API#

Para clientes MCP que no soportan OAuth, el titular puede crear una clave en Panel → Developer → Claves de API. Empieza por ctk_, se muestra una sola vez y Citeri solo guarda su huella (SHA-256). Desde el mismo sitio se revoca.

  • Úsala exactamente igual que un token: Authorization: Bearer ctk_….
  • Da acceso al negocio que la creó, con los mismos permisos que el titular. Trátala como una contraseña: nunca en el navegador ni en un repositorio.
  • Si el negocio deja de tener una suscripción activa, las peticiones devuelven 402.

Errores de OAuth#

CódigoCuándo
invalid_requestFalta un parámetro obligatorio, como code.
invalid_grantCódigo caducado o ya usado, client_id o redirect_uri distintos, o code_verifier incorrecto.
unsupported_grant_typeSolo se admite authorization_code.
invalid_targetEl resource no es el del MCP.
invalid_client_metadataRegistro con un método de autenticación distinto de none.