NORTHSTAR / API v1.0.0

Referencia de API pública

Conecta cuentas, trabajo y proyectos con tu stack. Credenciales con permisos, respuestas predecibles y eventos firmados.

OpenAPI 3.1.1 · JSON ↗

Autenticación y reintentos seguros

Autenticación

Usa una API key o un access token OAuth. Cada credencial vincula un actor, workspace y generación de demo; los scopes y permisos actuales limitan el acceso.

GET /api/v1/accounts
Authorization: Bearer <token>

Idempotencia

Cada escritura requiere clave y generation. Tras un timeout o response_unknown, reutiliza la clave y el cuerpo exactos. Cambiar datos con la misma clave devuelve 409. Tickets usa la generación de su credencial.

Idempotency-Key: work-request-001
{"generation": <current-generation>, "status": "resolved"}

Paginación

Las listas devuelven data y nextCursor. Envía ese cursor para continuar; limit admite 1–100 (20 por defecto). Un snapshot modificado devuelve 409: reinicia la paginación.

GET /api/v1/accounts?limit=20&cursor=<nextCursor>

Límites

120 peticiones autenticadas por minuto y credencial. Los rechazos también consumen cuota. Ante 429, espera los segundos de Retry-After antes de reintentar.

HTTP 429
Retry-After: 60

OAuth

Authorization code + PKCE S256, consentimiento explícito y redirect URI exacta. Canjea cada código una vez; guarda el refresh token nuevo tras cada rotación. Revoca una familia para retirar su acceso.

GET  /api/oauth/authorize
POST /api/oauth/token
POST /api/oauth/revoke

Webhooks

Deduplica por event ID. Verifica HMAC SHA-256 sobre timestamp + "." + el cuerpo original, con ventana de cinco minutos. Cinco intentos, con esperas de 1/2/4/8 segundos. Replay conserva el event ID.

Northstar-Event-Id: evt_<id>
Northstar-Signature: t=<timestamp>,v1=<signature>

Cuentas

GET/api/v1/accountsaccounts:readHTTP 200

Listar cuentas

GET/api/v1/accounts/{id}accounts:readHTTP 200

Consultar un registro de cuentas

PATCH/api/v1/accounts/{id}accounts:writeHTTP 200

Actualizar nombre o notas de una cuenta

Esquema de petición
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "notes": {
      "type": "string",
      "maxLength": 4000
    }
  },
  "required": [
    "generation"
  ],
  "additionalProperties": false
}

Trabajo

GET/api/v1/workwork:readHTTP 200

Listar trabajo

GET/api/v1/work/{id}work:readHTTP 200

Consultar un registro de trabajo

POST/api/v1/workwork:writeHTTP 201

Crear una solicitud de trabajo

Esquema de petición
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    },
    "accountId": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "pattern": "^[A-Za-z0-9_-]+$"
    },
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "description": {
      "type": "string",
      "minLength": 1,
      "maxLength": 4000
    },
    "priority": {
      "type": "string",
      "enum": [
        "P1",
        "P2",
        "P3"
      ]
    }
  },
  "required": [
    "generation",
    "accountId",
    "title",
    "description",
    "priority"
  ],
  "additionalProperties": false
}
PATCH/api/v1/work/{id}work:writeHTTP 200

Actualizar estado o responsable de trabajo

Esquema de petición
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    },
    "status": {
      "type": "string",
      "enum": [
        "open",
        "pending-customer",
        "escalated",
        "resolved"
      ]
    },
    "assigneeId": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "pattern": "^[A-Za-z0-9_-]+$"
    }
  },
  "required": [
    "generation"
  ],
  "additionalProperties": false
}

Proyectos

GET/api/v1/projectsprojects:readHTTP 200

Listar proyectos

GET/api/v1/projects/{id}projects:readHTTP 200

Consultar un registro de proyectos

POST/api/v1/projectsprojects:writeHTTP 201

Crear proyecto

Esquema de petición
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    },
    "accountId": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "pattern": "^[A-Za-z0-9_-]+$"
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "ownerId": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "pattern": "^[A-Za-z0-9_-]+$"
    },
    "dueAt": {
      "type": "string",
      "format": "date-time"
    },
    "nextMilestone": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    }
  },
  "required": [
    "generation",
    "accountId",
    "name",
    "ownerId",
    "dueAt",
    "nextMilestone"
  ],
  "additionalProperties": false
}
PATCH/api/v1/projects/{id}projects:writeHTTP 200

Editar proyecto

Esquema de petición
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "ownerId": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "pattern": "^[A-Za-z0-9_-]+$"
    },
    "dueAt": {
      "type": "string",
      "format": "date-time"
    },
    "nextMilestone": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "blocked",
        "at-risk",
        "complete"
      ]
    }
  },
  "required": [
    "generation",
    "name",
    "ownerId",
    "dueAt",
    "nextMilestone",
    "status"
  ],
  "additionalProperties": false
}
DELETE/api/v1/projects/{id}projects:writeHTTP 200

Borrar proyecto (administrador)

Esquema de petición
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    }
  },
  "required": [
    "generation"
  ],
  "additionalProperties": false
}

Miembros

GET/api/v1/membersmembers:readHTTP 200

Listar miembros

GET/api/v1/members/{id}members:readHTTP 200

Consultar un registro de miembros

POST/api/v1/membersmembers:writeHTTP 201

Invitar miembro

Esquema de petición
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "email": {
      "type": "string",
      "pattern": "^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$",
      "maxLength": 254
    },
    "role": {
      "type": "string",
      "enum": [
        "admin",
        "member",
        "viewer"
      ]
    }
  },
  "required": [
    "generation",
    "name",
    "email",
    "role"
  ],
  "additionalProperties": false
}

Facturas

GET/api/v1/invoicesinvoices:readHTTP 200

Listar facturas

GET/api/v1/invoices/{id}invoices:readHTTP 200

Consultar un registro de facturas

POST/api/v1/invoicesinvoices:writeHTTP 201

Guardar borrador de factura

Esquema de petición
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    },
    "accountId": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200,
      "pattern": "^[A-Za-z0-9_-]+$"
    },
    "amount": {
      "type": "number",
      "minimum": 0.01,
      "maximum": 10000000
    },
    "dueAt": {
      "type": "string",
      "format": "date-time"
    }
  },
  "required": [
    "generation",
    "accountId",
    "amount",
    "dueAt"
  ],
  "additionalProperties": false
}

Operaciones

GET/api/v1/operationsoperations:readHTTP 200

Listar operaciones

GET/api/v1/operations/{id}operations:readHTTP 200

Consultar un registro de operaciones

GET/api/v1/operations/{id}/downloadoperations:readHTTP 200

Descargar una exportación completada con datos protegidos ocultos

POST/api/v1/operationsoperations:writeHTTP 202

Iniciar exportación asíncrona del workspace con datos protegidos ocultos

Esquema de petición
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    },
    "type": {
      "type": "string",
      "enum": [
        "export-workspace"
      ]
    }
  },
  "required": [
    "generation",
    "type"
  ],
  "additionalProperties": false
}

Webhooks

GET/api/v1/webhook-deliverieswebhooks:readHTTP 200

Listar entregas de webhooks

GET/api/v1/webhook-deliveries/{id}webhooks:readHTTP 200

Consultar un registro de entregas de webhooks

POST/api/v1/webhook-deliveries/{id}/replaywebhooks:writeHTTP 201

Repetir una entrega con su event ID original

Esquema de petición
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    }
  },
  "required": [
    "generation"
  ],
  "additionalProperties": false
}

Conector

GET/healthbearerHTTP 200

Comprobar conexión autenticada del conector

GET/entitlements/{id}entitlements:readHTTP 200

Consultar plan y SSO de la cuenta firmada

POST/ticketstickets:writeHTTP 201

Crear ticket; la generación de la credencial es su precondición inmutable

Esquema de petición
{
  "type": "object",
  "properties": {
    "subject": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "body": {
      "type": "string",
      "minLength": 1,
      "maxLength": 8000
    },
    "requester_email": {
      "type": "string",
      "maxLength": 254
    },
    "page_url": {
      "type": "string",
      "maxLength": 2048
    }
  },
  "required": [
    "subject",
    "body",
    "requester_email"
  ],
  "additionalProperties": false
}

Errores

Los errores usan un código estable. Un 503 o 504 no confirma si una escritura terminó: recupera su resultado original antes de iniciar otra petición.

{"error":{"code":"validation"}}
Errores HTTP y recuperación
HTTPSignificado / siguiente paso
401Autenticación ausente o vencida
403Scope o rol insuficiente
404Recurso no encontrado
409Conflicto de generación, snapshot o idempotencia
422Cuerpo de petición inválido
429Cuota agotada; respeta Retry-After
500Fallo interno redactado
503Resultado incierto; recupera la petición original
504Timeout; la finalización no está confirmada