Designing REST APIs (YPFB Standards)
Endpoint típico siguiendo el estándar:
GET /api/v1/solicitudes?q=salud&sort=+nombre,-fecha&offset=0&limit=25
Respuesta exitosa (listado):
JSON{ "success": true, "code": 200, "message": "OK", "data": [ { "id": "1001", "nombre": "..." } ], "paginacion": { "count": 25, "offset": 0, "limit": 25, "total": 77 } }
Respuesta de error:
JSON{ "success": false, "code": 400, "message": "Petición incorrecta", "errorList": [ { "ci": "El número de la cédula de identidad ya existe." } ] }
Progress:
- 1. Definir el recurso (sustantivo plural) y su URL versionada:
/api/v1/recursos - 2. Elegir el método HTTP correcto según la acción (GET/POST/PUT/PATCH/DELETE)
- 3. Definir atributos de query:
q(búsqueda),sort(ordenación),limit/offset(paginación) - 4. Definir headers obligatorios:
Content-Type: application/json; charset=utf-8y autenticación (Authorization: Bearer [JWT]ouser-access-tokenpara legados) - 5. Diseñar el response envelope (
success,code,message,data/errorList) para cada código HTTP posible - 6. Verificar codificación UTF-8 y formato ISO 8601 para fechas
- 7. Documentar en RAML (sistemas legados) o Swagger (Spring Boot)
- 8. Validar contra la tabla de códigos HTTP permitidos (sección Best Practices)
- Versión obligatoria en la URL:
api/v1/... - Recurso = sustantivo plural, nunca verbo:
solicitudes-permisos, nogetSolicitudes - Nomenclatura en kebab-case para recursos compuestos:
solicitudes-permisos - Atributos que cambian la lógica del resultado → van en la URL (query params)
- Atributos que NO cambian la lógica (ej. auth) → van en el header HTTP
- Identificador de recurso como segmento de ruta:
/personas/12345
| Método | Uso | Código éxito |
|---|---|---|
| GET | Obtener recurso(s) | 200 |
| POST | Crear recurso | 201 (o 202 si es asíncrono) |
| PUT | Actualizar recurso completo | 200 |
| PATCH | Actualización parcial | 200 |
| DELETE | Eliminar recurso | 204 |
Ejemplo por recurso:
GET /v1/personas -> listado
GET /v1/personas/12345 -> detalle
POST /v1/personas -> crear
PUT /v1/personas/12345 -> actualizar (error si no existe)
DELETE /v1/personas/12345 -> eliminar
2xx Éxito: 200 (OK/GET/PUT/PATCH), 201 (Creado/POST), 202 (Aceptado/async), 204 (Sin contenido/DELETE)
3xx Redirección: 301 (Permanente), 302 (Temporal)
4xx Error cliente: 400 (Petición incorrecta), 401 (No autorizado), 403 (Prohibido), 404 (No encontrado), 409 (Conflicto)
5xx Error servidor: 500 (Error interno — incluir codigoError), 503 (No disponible)
No usar códigos fuera de esta lista sin justificación documentada.
Toda respuesta debe tener el envelope base success, code, message:
Listado (200):
JSON{ "success": true, "code": 200, "message": "OK", "data": [ ... ], "paginacion": { "count": 25, "offset": 0, "limit": 25, "total": 77 } }
Objeto único (200):
JSON{ "success": true, "code": 200, "message": "OK", "data": { ... } }
Creación (201):
JSON{ "success": true, "code": 201, "message": "Creado", "data": { "id": "..." } }
Error de validación (400):
JSON{ "success": false, "code": 400, "message": "Petición incorrecta", "errorList": [ { "campo": "mensaje de error" } ] }
Error de servidor (500):
JSON{ "success": false, "code": 500, "message": "Error interno en el servidor", "codigoError": "Código a mostrar al usuario final / reportar en mesa de ayuda" }
Errores simples (401, 403, 404, 409, 503) solo requieren success, code, message.
- Búsqueda:
q→?q=MAR - Ordenación:
sortcon prefijo+(ascendente) /-(descendente), múltiples separados por coma →?sort=+nombre,-fecha. Default: id ascendente. - Paginación:
limit(default 25),offset(default 0). Siempre responder con bloquepaginacion.
- Header obligatorio:
Content-Type: application/json; charset=utf-8 - Nuevas apps:
Authorization: Bearer [JWT_TOKEN] - Apps legadas:
user-access-token: [ACCESS_TOKEN] - Autenticación inicial (login) puede ser HTTP Basic (credenciales en Base64) o body con
ypfb_app_token/clientCode+clientSecretpara legados. - Se permite adoptar OAuth2/JWT adicional según necesidades de seguridad.
- Tipos JSON estándar: Number, String, Boolean, Array, Object, Null
- Fechas: siempre string en formato ISO 8601 (
2001-08-22,1997-07-16T19:20:30) - Codificación: UTF-8 en toda la comunicación
- Número entero con prefijo
v:v1,v2,v3(nunca decimales comov1.2)
- Sistemas legados → RAML
- Nuevos desarrollos (Spring Boot) → Swagger/OpenAPI
Example 1 — Listado con filtro y orden: Input: Solicitud de listado de solicitudes por tema, ordenado Output:
GET https://ejemplo.cl/api/v1/solicitudes?tema=salud,educacion&sort=asc
Example 2 — Creación de recurso: Input: Crear una persona nueva Output:
POST /v1/personas
Response 201:
{
"success": true,
"code": 201,
"message": "Operación exitosa",
"data": { "id": "1001000000017417" }
}
Example 3 — Error de validación: Input: CI duplicado al crear persona Output:
JSON{ "success": false, "code": 400, "message": "Solicitud incorrecta", "errorList": [ {"ci": "El número de la cédula de identidad ya existe."} ] }
- Sustantivos plurales en URL, nunca verbos (
/solicitudes/creares aceptado como excepción legada, pero preferir métodos HTTP semánticos) - Mantener consistencia del envelope de respuesta en TODOS los endpoints, incluso errores
- Incluir siempre
codedentro del body, redundante con el status HTTP pero exigido por el estándar - Validar que códigos de error 500 incluyan
codigoErrortrazable para mesa de servicio - Documentar cada servicio en RAML o Swagger antes de pasar a control de calidad
- No usar verbos en los recursos (
/getPersonas❌ →/personas✅) - No omitir el bloque
paginacionen respuestas de listados - No mezclar singular/plural entre endpoints del mismo dominio
- No usar decimales en el versionado (
v1.1❌) - No olvidar
errorListcomo array en respuestas 400 - No enviar fechas en formato libre; siempre ISO 8601
- No omitir
Content-Type: application/json; charset=utf-8