VectorKan API

A REST API for putting VectorKan inside your own systems — create tickets from your app, sync status with your tools, and pull everything your customers have reported. JSON in, JSON out, over HTTPS.

Base URL http://www.vectorkan.com/api/v1 The API is available on the Business plan.

Getting started

  1. Create a key. In VectorKan, go to API keys in the sidebar and create one. The secret is shown once — store it somewhere safe.
  2. Check it works. Call GET /me — it returns the workspace the key opens.
  3. Find your project. GET /projects returns each project's id, which you need to create tickets.
  4. Create your first ticket. POST /issues with that project id and a title.
curl http://www.vectorkan.com/api/v1/me \
  -H "X-Api-Key: vk_your_key_here"

Authentication

Every request needs your key in an X-Api-Key header. The key identifies your workspace, so you never pass a workspace id — and a key can only ever see its own company's data.

X-Api-Key: vk_1a2b3c4d5e6f...
Keep keys server-side. A key carries full access to your workspace, so never ship it in browser or mobile code. If one leaks, revoke it on the API keys page — revoking takes effect immediately.

Errors & status codes

Failures return a JSON body with a single error field explaining what went wrong.

{ "error": "Title is required." }
CodeMeaning
200Success.
201Created — returned by POST endpoints.
400Something in the request was wrong; the message says what.
401Missing or invalid API key.
402Your plan doesn't include API access — upgrade to Business.
403The key isn't allowed to do that.
404No such record in this workspace.
429Too many requests — see rate limits below.

Rate limits

Each API key gets 120 requests a minute, replenished continuously, and one key's usage never affects another's. Go over it and you'll get a 429 with a Retry-After header saying how many seconds to wait.

If you're backfilling or syncing a lot, spread the work out rather than retrying immediately — and if the limit is genuinely too low for what you're building, tell us.

Workspace

GET /api/v1/me

Confirms your key works and shows which workspace and plan it opens.

{
  "workspaceId": "7be742fe-...",
  "workspaceName": "Acme Inc",
  "plan": "Business",
  "authenticatedAs": "api:Production key"
}
GET /api/v1/members

Lists the people in your workspace. Use a userId here to assign tickets.

Projects

GET /api/v1/projects

All projects in your workspace.

GET /api/v1/projects/{projectId}

A single project.

GET /api/v1/projects/{projectId}/statuses

The project's workflow columns. You need these names (or ids) to move a ticket.

[
  { "id": "bf0eb0af-...", "name": "Backlog",     "category": "ToDo",       "order": 0 },
  { "id": "016585fc-...", "name": "In Progress", "category": "InProgress", "order": 2 },
  { "id": "fc8b8161-...", "name": "Done",        "category": "Done",       "order": 4 }
]

Tickets

GET /api/v1/issues

Lists tickets. Every filter is optional and they combine.

Query parameterDescription
projectIdOnly tickets in this project.
statusStatus name, e.g. In Progress.
assigneeIdOnly tickets assigned to this user.
qSearch the title and ticket key.
limit / offsetPaging. Default 50, max 200.
curl "http://www.vectorkan.com/api/v1/issues?status=In%20Progress&limit=10" \
  -H "X-Api-Key: $VECTOR_KEY"

Responses are paged:

{
  "total": 36, "limit": 10, "offset": 0,
  "items": [ { "id": "...", "key": "ENG-36", "title": "Add dark mode", "status": "Backlog", ... } ]
}
GET /api/v1/issues/{issueId}

A single ticket in full.

POST /api/v1/issues

Creates a ticket. This is the one most integrations start with.

projectId and title are required; everything else is optional.

curl -X POST http://www.vectorkan.com/api/v1/issues \
  -H "X-Api-Key: $VECTOR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "projectId": "0854e185-...",
    "title": "Payment webhook is failing",
    "description": "Started after the 4.2 release.",
    "type": "Bug",
    "priority": "High",
    "assigneeId": null
  }'

type: Bug, Task, Story or Epic. priority: Low, Medium, High or Urgent. Unknown values fall back to Task and Medium rather than failing.

PATCH /api/v1/issues/{issueId}

Updates a ticket. Only the fields you send are changed.

curl -X PATCH http://www.vectorkan.com/api/v1/issues/ISSUE_ID \
  -H "X-Api-Key: $VECTOR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "priority": "Urgent", "dueDate": "2026-08-30", "storyPoints": 5 }'

Send "dueDate": "" to clear a due date.

POST /api/v1/issues/{issueId}/transitions

Moves a ticket to another status — the endpoint for syncing state from your system.

curl -X POST http://www.vectorkan.com/api/v1/issues/ISSUE_ID/transitions \
  -H "X-Api-Key: $VECTOR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "In Progress" }'

Use the status name as above, or statusId if you prefer ids. Send an unknown status and the error lists the valid ones for that project.

POST /api/v1/issues/{issueId}/assign

Assigns a ticket. Send an empty assigneeId to unassign.

-d '{ "assigneeId": "16fb32e3-..." }'

Comments

GET /api/v1/issues/{issueId}/comments

Every comment on a ticket, oldest first.

POST /api/v1/issues/{issueId}/comments

Adds a comment.

-d '{ "body": "Deployed the fix — @jordan can you confirm?" }'
Comments posted through the API behave exactly like ones typed in the app: watchers are notified and @username mentions email the person you tagged.

Customer requests

Requests are what your own customers file through your public portal (see below). Pull them into your systems, then convert the real ones into tracked tickets.

GET /api/v1/projects/{projectId}/requests

Requests for a project. Optional ?status=New|Triaged|Closed.

POST /api/v1/requests/{requestId}/convert

Turns a customer request into a ticket and links the two.

curl -X POST http://www.vectorkan.com/api/v1/requests/REQUEST_ID/convert \
  -H "X-Api-Key: $VECTOR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "priority": "High" }'

Every project can publish a public request form. Your customers open the link, describe their problem, and it lands in your triage queue — no VectorKan account needed, and they never see anything else in your workspace.

  1. Open the project in VectorKan and go to Requests.
  2. Switch Public request form on. (Pro and Business plans.)
  3. Copy the link that appears and share it — email it, or link it from your website, help centre or app.

The link looks like this:

http://www.vectorkan.com/request/YOUR_PROJECT_ID

You can also fetch it programmatically, which is handy if you generate support pages per client:

GET /api/v1/projects/{projectId}/portal

Returns the shareable portal link and whether it's currently open.

{
  "projectId": "0854e185-...",
  "enabled": true,
  "url": "http://www.vectorkan.com/request/0854e185-...",
  "hint": "Share this link with your customers — no account needed to file a request."
}
Prefer your own form? Build any UI you like and call POST /issues from your backend instead. The portal is the no-code option; the API is the flexible one.

Common recipes

Raise a ticket when something breaks

Call the API from your error handler or alerting webhook so incidents land in your board automatically.

await fetch("http://www.vectorkan.com/api/v1/issues", {
  method: "POST",
  headers: {
    "X-Api-Key": process.env.VECTOR_KEY,
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
    projectId: process.env.VECTOR_PROJECT_ID,
    title: `Checkout failed: ${error.code}`,
    description: error.stack,
    type: "Bug",
    priority: "Urgent"
  })
});

Close the VectorKan ticket when your system closes the job

curl -X POST http://www.vectorkan.com/api/v1/issues/$ID/transitions \
  -H "X-Api-Key: $VECTOR_KEY" -H "Content-Type: application/json" \
  -d '{ "status": "Done" }'

Poll for new customer requests every few minutes

curl "http://www.vectorkan.com/api/v1/projects/$PROJECT/requests?status=New" \
  -H "X-Api-Key: $VECTOR_KEY"

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.