Octopus
Octopus Developersgateway.octopusoperations.co.za/v1

Start here

Quickstart

A key, a call, and a change you can see. About five minutes, and you need nothing installed beyond curl.

1. Create a key

In Octopus, open Settings → Integrations and create an API key. You will be asked to name it and tick the scopes it should hold. For this walkthrough, tick organisation.read and tasks.manage.

The key is shown exactly once

Octopus stores only a hash of it, so it genuinely cannot be shown again, by anyone, including support. Copy it into your secret store before you close the dialog. If you lose it, revoke it and make another.

Keep it in an environment variable rather than pasting it into files:

bash
export OCTOPUS_API_KEY="oct_live_..."

2. Confirm it works

Ask the API to describe itself. One call tells you the key is valid, which organisation it belongs to, and exactly which scopes it holds.

Request
curl https://gateway.octopusoperations.co.za/v1 \
  -H "Authorization: Bearer $OCTOPUS_API_KEY"
Response · 200
{
  "success": true,
  "version": "v1",
  "changeVersion": 1,
  "organisation": "4bca402b-e846-4bde-8489-ee894cd80d1c",
  "application": "Site reporting bot",
  "scopes": [
    { "scope": "organisation.read", "label": "Read the organisation" },
    { "scope": "tasks.manage", "label": "Create and change tasks" },
    { "scope": "tasks.read", "label": "Read tasks" }
  ],
  "realtime": {
    "namespace": "/v1",
    "how": "Connect a Socket.IO client to this host's /v1 namespace with auth: { apiKey }."
  },
  "operations": [ "…every endpoint, with a one-line summary" ]
}

You asked for two scopes and got three

Asking for a .manage scope also grants the matching .read. Tick tasks.manage and the key is created holding tasks.manage and tasks.read, you never need to ask for both.

3. Read something

Every response uses the same envelope, so one client wrapper covers all of them.

bash
curl https://gateway.octopusoperations.co.za/v1/tasks \
  -H "Authorization: Bearer $OCTOPUS_API_KEY"
Response · 200
{
  "success": true,
  "data": [
    {
      "id": "20269152-383d-4078-a6c6-4ea5a825f1d7",
      "orgId": "4bca402b-e846-4bde-8489-ee894cd80d1c",
      "projectId": "2ac11d13-9e39-4d29-ad55-c989a32b1a38",
      "title": "Inspect scaffolding on level 3",
      "status": "todo",
      "priority": "high",
      "dueDate": "2026-09-30"
    }
  ],
  "message": "Found 25 task(s).",
  "version": "v1",
  "count": 25
}

4. Change something

A task belongs to a project, is assigned to somebody, and has a due date. All three are required: a task without them cannot be chased, so Octopus refuses rather than inventing them. Get a project id from GET /v1/projects and a person from GET /v1/personnel.

Create
curl -X POST https://gateway.octopusoperations.co.za/v1/tasks \
  -H "Authorization: Bearer $OCTOPUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Inspect scaffolding on level 3",
    "projectId": "2ac11d13-9e39-4d29-ad55-c989a32b1a38",
    "assigneeId": "abff87b9-6fc2-47d1-9c24-a4e5b012d486",
    "dueDate": "2026-09-30",
    "priority": "high"
  }'

The saved record comes back with its id. Change it with a PATCH:

Update
curl -X PATCH https://gateway.octopusoperations.co.za/v1/tasks/20269152-383d-4078-a6c6-4ea5a825f1d7 \
  -H "Authorization: Bearer $OCTOPUS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "status": "in_progress" }'

5. Watch it happen

That change was just broadcast to anybody subscribed. Here is the whole round trip, including the part you get for free:

One write, end to end
Drawing…

Step 2 is the one worth remembering: authorisation happens before anything is changed, so a refused call changes nothing at all. There is no partial write to undo.

Do not poll

Every change you are allowed to see is pushed to the realtime channel and to any webhook you register. Polling costs you rate limit and still arrives later. See the realtime guide.

What next