GreenStack API v2 — Especificación Técnica
Versión 2.1.0 · Actualizado 2026-06-12 · Acceso solo para integradores certificados.
Esta especificación describe todos los endpoints REST de la plataforma GreenStack para la gestión de huella de carbono empresarial. La API sigue los principios REST; los recursos devuelven JSON y las respuestas de error siguen RFC 9457.
Autenticación
OAuth 2.0 — Client Credentials
La API usa el flujo Client Credentials de OAuth 2.0. Obtén un token de acceso con:
POST https://auth.greenstack.io/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=emissions:read emissions:write reports:read
Respuesta:
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "emissions:read emissions:write reports:read"
}
Incluye el token en cada petición:
Authorization: Bearer {access_token}
Scopes disponibles
| Scope | Descripción |
|---|---|
emissions:read | Leer registros de emisiones |
emissions:write | Crear y editar registros |
reports:read | Descargar informes PDF/CSV |
reports:generate | Lanzar generación de informes asíncronos |
admin:orgs | Gestionar organizaciones (solo partners) |
Recursos
Organizaciones
Una organización representa a la empresa cliente. Todas las peticiones van namespaced por org_id.
GET /v2/orgs/{org_id}
Devuelve los metadatos de una organización.
GET /v2/orgs/org_01HXYZ1234 HTTP/1.1
Host: api.greenstack.io
Authorization: Bearer {token}
Respuesta 200 OK:
{
"id": "org_01HXYZ1234",
"name": "Café Raíz SL",
"country": "ES",
"sector": "food_beverage",
"reporting_year": 2025,
"baseline_year": 2022,
"created_at": "2024-03-15T09:22:00Z",
"status": "active"
}
PATCH /v2/orgs/{org_id}
Actualiza campos de la organización. Solo name, country y reporting_year son mutables.
{
"reporting_year": 2025
}
Emisiones
Los registros de emisiones representan actividades con impacto de carbono. Cada registro pertenece a un scope (1, 2 o 3) y a una categoría GHG Protocol.
Modelo de datos
| Campo | Tipo | Obligatorio | Descripción | ||
|---|---|---|---|---|---|
id | string | — | ULID generado por servidor | ||
org_id | string | sí | ID de la organización | ||
scope | `1\ | 2\ | 3` | sí | Alcance GHG Protocol |
category | string | sí | Código de categoría (ej. stationary_combustion) | ||
activity_value | number | sí | Cantidad de la actividad (kWh, km, t…) | ||
activity_unit | string | sí | Unidad de medida (ISO 80000) | ||
emission_factor_id | string | sí | ID del factor de emisión usado | ||
co2e_kg | number | — | Calculado automáticamente por el servidor | ||
date | string | sí | ISO 8601 (YYYY-MM-DD) | ||
notes | string | no | Texto libre, máx. 500 chars | ||
tags | string[] | no | Etiquetas para filtrado | ||
source_doc | string | no | URL del documento fuente |
GET /v2/orgs/{org_id}/emissions
Lista registros con paginación tipo cursor.
Parámetros de query:
| Parámetro | Tipo | Default | Descripción | ||
|---|---|---|---|---|---|
scope | `1\ | 2\ | 3` | todos | Filtrar por alcance GHG |
category | string | todos | Filtrar por categoría | ||
date_from | date | — | Desde fecha (YYYY-MM-DD) | ||
date_to | date | — | Hasta fecha (YYYY-MM-DD) | ||
tag | string | — | Filtrar por etiqueta | ||
cursor | string | — | Cursor para siguiente página | ||
limit | integer | 50 | Máx. 200 |
Respuesta 200 OK:
{
"data": [
{
"id": "01HXAB1234",
"scope": 1,
"category": "stationary_combustion",
"activity_value": 1200.5,
"activity_unit": "kWh",
"co2e_kg": 264.11,
"date": "2025-10-01",
"tags": ["planta-madrid", "produccion"]
}
],
"cursor_next": "eyJpZCI6IjAxSFhBQjEyMzQifQ",
"total_count": 847,
"has_more": true
}
POST /v2/orgs/{org_id}/emissions
Crea un nuevo registro.
{
"scope": 2,
"category": "purchased_electricity",
"activity_value": 8540.0,
"activity_unit": "kWh",
"emission_factor_id": "ef_es_grid_2025",
"date": "2025-11-30",
"notes": "Factura nov 2025, contrato Endesa verde",
"tags": ["oficina-bcn"]
}
Respuesta 201 Created:
{
"id": "01HXBC5678",
"co2e_kg": 1282.6,
"co2e_kg_details": {
"factor_value": 0.15,
"factor_unit": "kgCO2e/kWh",
"factor_version": "MiTECO-2025"
}
}
DELETE /v2/orgs/{org_id}/emissions/{emission_id}
Elimina un registro. Operación irreversible. Requiere scope emissions:write.
Respuesta: 204 No Content.
Factores de emisión
Base de datos de referencia con más de 12.000 factores certificados (DEFRA, MiTECO, IPCC AR6).
GET /v2/emission-factors
GET /v2/emission-factors?country=ES&category=purchased_electricity&year=2025
Respuesta 200 OK:
{
"data": [
{
"id": "ef_es_grid_2025",
"name": "Red eléctrica española 2025",
"country": "ES",
"category": "purchased_electricity",
"value": 0.15,
"unit": "kgCO2e/kWh",
"source": "MiTECO",
"year": 2025,
"status": "active"
}
]
}
Informes
Los informes se generan de forma asíncrona. El flujo es: lanzar → polling de estado → descargar.
POST /v2/orgs/{org_id}/reports
Lanza la generación de un informe.
{
"type": "annual_ghg",
"year": 2025,
"format": "pdf",
"standard": "GHG_Protocol",
"locale": "es"
}
Tipos de informe disponibles:
annual_ghg— Inventario anual completo GHG Protocolscope3_deep— Desglose detallado alcance 3 (15 categorías)carbon_footprint_product— Huella de producto (PCF ISO 14067)executive_summary— Resumen ejecutivo de 4 páginas
Respuesta 202 Accepted:
{
"report_id": "rpt_01HXDE1234",
"status": "queued",
"estimated_seconds": 45
}
GET /v2/orgs/{org_id}/reports/{report_id}
Polling de estado.
| Estado | Descripción |
|---|---|
queued | En cola de generación |
processing | Generando el documento |
ready | Listo para descarga |
failed | Error en generación (ver error) |
GET /v2/orgs/{org_id}/reports/{report_id}/download
Descarga el archivo. Redirige (302) al URL firmado de S3 (válido 15 minutos).
Manejo de errores
La API sigue RFC 9457 (Problem Details for HTTP APIs):
{
"type": "https://errors.greenstack.io/validation-error",
"title": "Validation Error",
"status": 422,
"detail": "activity_value must be a positive number",
"instance": "/v2/orgs/org_01HXYZ1234/emissions",
"errors": [
{ "field": "activity_value", "code": "must_be_positive", "value": -10 }
]
}
Códigos de estado habituales
| Código | Significado |
|---|---|
200 | OK — petición exitosa |
201 | Creado — recurso nuevo |
202 | Aceptado — trabajo asíncrono iniciado |
204 | Sin contenido — operación exitosa sin cuerpo |
400 | Petición malformada |
401 | No autenticado — token inválido o expirado |
403 | Prohibido — scope insuficiente |
404 | No encontrado |
422 | Error de validación — ver errors[] |
429 | Rate limit — ver cabecera Retry-After |
500 | Error interno del servidor |
Rate Limiting
Los límites se aplican por client_id:
| Plan | Peticiones/minuto | Peticiones/día |
|---|---|---|
| Starter | 60 | 5.000 |
| Business | 300 | 50.000 |
| Enterprise | 1.000 | sin límite |
Las cabeceras X-RateLimit-Limit, X-RateLimit-Remaining y X-RateLimit-Reset están presentes en cada respuesta.
Webhooks
Suscríbete a eventos asíncronos para evitar polling activo.
Eventos disponibles
emission.created— nuevo registro creadoemission.updated— registro modificadoreport.ready— informe listo para descargareport.failed— error en generaciónorg.limit_warning— acercándose al límite de emisiones del plan
Firma de seguridad
Cada entrega incluye la cabecera X-GreenStack-Signature:
import hmac, hashlib
def verify_webhook(payload_bytes: bytes, signature_header: str, secret: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), payload_bytes, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header)
SDKs y ejemplos
Librerías oficiales mantenidas por el equipo GreenStack:
| Lenguaje | Repositorio | Versión |
|---|---|---|
| Python | greenstack-io/sdk-python | 2.1.0 |
| TypeScript / Node | greenstack-io/sdk-ts | 2.1.0 |
| Go | greenstack-io/sdk-go | 2.0.3 |
| Java | greenstack-io/sdk-java | 2.0.1 |
Ejemplo completo Python
from greenstack import GreenStackClient
client = GreenStackClient(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
)
# Crear registro de emisiones
record = client.emissions.create(
org_id="org_01HXYZ1234",
scope=2,
category="purchased_electricity",
activity_value=8540.0,
activity_unit="kWh",
emission_factor_id="ef_es_grid_2025",
date="2025-11-30",
)
print(f"Registro {record.id}: {record.co2e_kg:.2f} kgCO2e")
# Generar informe anual
report = client.reports.generate(
org_id="org_01HXYZ1234",
type="annual_ghg",
year=2025,
format="pdf",
)
report.wait() # bloquea hasta status=ready
report.download(path="./informe_ghg_2025.pdf")
print("Informe descargado.")
Changelog
v2.1.0 (2026-06-12)
- Nuevo tipo de informe
carbon_footprint_product(PCF ISO 14067) - Endpoint
GET /v2/emission-factorsahora aceptayearcomo parámetro - Tiempo de expiración de informes extendido de 7 a 30 días
- SDK Python actualizado a 2.1.0 con soporte
async/await
v2.0.0 (2025-09-01)
- Migración a OAuth 2.0 (abandono de API Keys v1)
- Modelo de datos de emisiones rediseñado (campo
co2e_kgcalculado en servidor) - Nuevos scopes granulares:
reports:generate,admin:orgs - Webhooks con firma HMAC-SHA256
v1.9 (deprecada)
- Última versión con API Keys. Soporte hasta 2026-09-01.
Documentación generada por CULTIVA IA para GreenStack SaaS. Para soporte de integración: developers@greenstack.io