NORTHSTAR / API v1.0.0

Public API reference

Connect accounts, work and projects to your stack. Scoped credentials, predictable responses and signed events.

OpenAPI 3.1.1 · JSON ↗

Authentication and safe retries

Authentication

Use an API key or OAuth access token. Each credential binds one actor, workspace and demo generation; scopes and current permissions limit access.

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

Idempotency

Every write requires a key and generation. After a timeout or response_unknown, reuse the exact key and body. Changing input with the same key returns 409. Tickets use their credential generation.

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

Pagination

Lists return data and nextCursor. Send that cursor to continue; limit accepts 1–100 (default 20). A changed snapshot returns 409: restart pagination.

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

Limits

120 authenticated requests per minute and credential. Rejected requests also consume quota. On 429, wait the number of seconds in Retry-After before retrying.

HTTP 429
Retry-After: 60

OAuth

Authorization code + S256 PKCE, explicit consent and an exact redirect URI. Exchange codes once; save the new refresh token after each rotation. Revoke a family to end its access.

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

Webhooks

Deduplicate by event ID. Verify HMAC SHA-256 over timestamp + "." + the original body, with a five-minute window. Five attempts, with 1/2/4/8-second backoff. Replay preserves the event ID.

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

Accounts

GET/api/v1/accountsaccounts:readHTTP 200

List accounts

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

Get accounts

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

Update account name or notes

Request schema
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 200
    },
    "notes": {
      "type": "string",
      "maxLength": 4000
    }
  },
  "required": [
    "generation"
  ],
  "additionalProperties": false
}

Work

GET/api/v1/workwork:readHTTP 200

List work

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

Get work

POST/api/v1/workwork:writeHTTP 201

Create a work request

Request schema
{
  "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

Update work status or assignee

Request schema
{
  "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
}

Projects

GET/api/v1/projectsprojects:readHTTP 200

List projects

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

Get projects

POST/api/v1/projectsprojects:writeHTTP 201

Create project

Request schema
{
  "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

Edit project

Request schema
{
  "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

Delete project (admin)

Request schema
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    }
  },
  "required": [
    "generation"
  ],
  "additionalProperties": false
}

Members

GET/api/v1/membersmembers:readHTTP 200

List members

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

Get members

POST/api/v1/membersmembers:writeHTTP 201

Invite member

Request schema
{
  "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
}

Invoices

GET/api/v1/invoicesinvoices:readHTTP 200

List invoices

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

Get invoices

POST/api/v1/invoicesinvoices:writeHTTP 201

Save invoice draft

Request schema
{
  "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
}

Operations

GET/api/v1/operationsoperations:readHTTP 200

List operations

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

Get operations

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

Download a completed redacted export

POST/api/v1/operationsoperations:writeHTTP 202

Start asynchronous redacted workspace export

Request schema
{
  "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

List webhook-deliveries

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

Get webhook-deliveries

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

Replay a webhook with its original event ID

Request schema
{
  "type": "object",
  "properties": {
    "generation": {
      "type": "integer",
      "minimum": 1
    }
  },
  "required": [
    "generation"
  ],
  "additionalProperties": false
}

Connector

GET/healthbearerHTTP 200

Authenticated connector health

GET/entitlements/{id}entitlements:readHTTP 200

Plan and SSO for signed workspace external ID

POST/ticketstickets:writeHTTP 201

Create support ticket; credential generation is its immutable precondition

Request schema
{
  "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
}

Errors

Errors use a stable code. A 503 or 504 does not confirm whether a write completed: recover its original result before starting another request.

{"error":{"code":"validation"}}
HTTP errors and recovery
HTTPMeaning / next step
401Authentication required or expired
403Insufficient scope or role
404Resource not found
409Generation, snapshot or idempotency conflict
422Invalid request body
429Quota exceeded; respect Retry-After
500Redacted internal failure
503Unknown result; recover the original request
504Timeout; completion is not confirmed