{
  "info": {
    "_postman_id": "9f2c1d64-0a3b-4e57-b8c2-6d51e7a90f14",
    "name": "Nubo Public API",
    "description": "Read-only API for pulling your Nubo projects, usage and conversation metadata into your own systems.\n\n## Setup\n\n1. Create a key on the Developer page in the Nubo portal.\n2. Open this collection's **Variables** tab and paste it into `apiKey`.\n3. Send any request — authentication is inherited from the collection.\n\nSet `projectId` and `sessionId` from the responses to **List projects** and **List sessions** to make the single-item requests work.\n\nEvery request ships with saved example responses, so you can read the shapes without a key — and point Postman's mock server at this collection if you want to build against it before wiring up the real thing.\n\nFull reference: https://www.nubo-chat.com/docs/api",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "apikey",
    "apikey": [
      {
        "key": "key",
        "value": "X-API-Key",
        "type": "string"
      },
      {
        "key": "value",
        "value": "{{apiKey}}",
        "type": "string"
      },
      {
        "key": "in",
        "value": "header",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://api.nubo-chat.com",
      "type": "string",
      "description": "Base URL of the Nubo Public API."
    },
    {
      "key": "apiKey",
      "value": "nubo_replace_with_your_key",
      "type": "string",
      "description": "Your API key from the Nubo portal's Developer page. Shown once, at creation."
    },
    {
      "key": "projectId",
      "value": "8f14e45f-ceea-467a-9ae4-2c1e2f0f1a3b",
      "type": "string",
      "description": "A project id from GET /v1/projects."
    },
    {
      "key": "sessionId",
      "value": "sess_01J9YQ2M7K4T8XN3P5RB6VW0AZ",
      "type": "string",
      "description": "A session id from GET /v1/sessions."
    }
  ],
  "item": [
    {
      "name": "Projects",
      "description": "The chatbots your workspace owns.",
      "item": [
        {
          "name": "List projects",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/projects",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "projects"
              ],
              "query": [
                {
                  "key": "projectId",
                  "value": "8f14e45f-ceea-467a-9ae4-2c1e2f0f1a3b",
                  "description": "Optional. Restrict to one project. Omit to span the whole workspace.",
                  "disabled": true
                }
              ]
            },
            "description": "Every project in the workspace that owns this key.\n\nPass `projectId` to narrow to one. The workspace's original project has an id equal to the workspace id — a historical artefact; never treat the two as interchangeable."
          },
          "response": [
            {
              "name": "200 — two projects",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "[\n  {\n    \"id\": \"8f14e45f-ceea-467a-9ae4-2c1e2f0f1a3b\",\n    \"name\": \"Support Bot\",\n    \"isActive\": true,\n    \"createdAt\": \"2026-03-11T09:22:41Z\",\n    \"isDefault\": true\n  },\n  {\n    \"id\": \"c2b7d914-5f30-4a1e-9d62-7be0e4c1a558\",\n    \"name\": \"Docs Assistant\",\n    \"isActive\": true,\n    \"createdAt\": \"2026-05-02T14:05:09Z\",\n    \"isDefault\": false\n  }\n]"
            },
            {
              "name": "401 — key missing or invalid",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "Unauthorized",
              "code": 401,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"missing_api_key\",\n    \"message\": \"This endpoint requires an API key. Send it on the X-API-Key header.\",\n    \"traceId\": \"0HN7A2QK9V1M4:00000001\"\n  }\n}"
            },
            {
              "name": "429 — rate limited",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "Too Many Requests",
              "code": 429,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                },
                {
                  "key": "Retry-After",
                  "value": "7"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"rate_limited\",\n    \"message\": \"Rate limit exceeded (60 requests per minute). Retry in 7s.\",\n    \"traceId\": \"0HN7A2QK9V1M4:00000009\"\n  }\n}"
            }
          ]
        },
        {
          "name": "Get project",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/projects/{{projectId}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "projects",
                "{{projectId}}"
              ]
            },
            "description": "A single project by id. Returns 404 if the id is unknown or not in your workspace."
          },
          "response": [
            {
              "name": "200 — one project",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"id\": \"8f14e45f-ceea-467a-9ae4-2c1e2f0f1a3b\",\n  \"name\": \"Support Bot\",\n  \"isActive\": true,\n  \"createdAt\": \"2026-03-11T09:22:41Z\",\n  \"isDefault\": true\n}"
            },
            {
              "name": "404 — unknown project",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"project_not_found\",\n    \"message\": \"No project with that id exists for this API key.\",\n    \"traceId\": \"0HN7A2QK9V1M4:00000004\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Usage",
      "description": "Aggregated chat usage. All three accept an optional projectId.",
      "item": [
        {
          "name": "Usage summary",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/usage?days=30",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "usage"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "Trailing window in days, 1–365. Defaults to 30.",
                  "disabled": false
                },
                {
                  "key": "projectId",
                  "value": "8f14e45f-ceea-467a-9ae4-2c1e2f0f1a3b",
                  "description": "Optional. Restrict to one project. Omit to span the whole workspace.",
                  "disabled": true
                }
              ]
            },
            "description": "Headline totals over a trailing window."
          },
          "response": [
            {
              "name": "200 — 30 day summary",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"rangeDays\": 30,\n  \"totalConversations\": 412,\n  \"totalMessages\": 1187,\n  \"totalTokens\": 2043911,\n  \"promptTokens\": 1402388,\n  \"completionTokens\": 641523,\n  \"avgResponseMs\": 1840,\n  \"rerankingRate\": 68.4,\n  \"toolCalls\": 233\n}"
            }
          ]
        },
        {
          "name": "Usage series",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/usage/series?days=30",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "usage",
                "series"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "Trailing window in days, 1–365. Defaults to 30.",
                  "disabled": false
                },
                {
                  "key": "projectId",
                  "value": "8f14e45f-ceea-467a-9ae4-2c1e2f0f1a3b",
                  "description": "Optional. Restrict to one project. Omit to span the whole workspace.",
                  "disabled": true
                }
              ]
            },
            "description": "One point per UTC day. Days with no activity are absent rather than zero-filled — fill gaps client-side rather than assuming a contiguous run."
          },
          "response": [
            {
              "name": "200 — daily points",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "[\n  {\n    \"date\": \"2026-08-06T00:00:00Z\",\n    \"messages\": 41,\n    \"conversations\": 15,\n    \"tokens\": 71204\n  },\n  {\n    \"date\": \"2026-08-07T00:00:00Z\",\n    \"messages\": 58,\n    \"conversations\": 22,\n    \"tokens\": 99871\n  },\n  {\n    \"date\": \"2026-08-09T00:00:00Z\",\n    \"messages\": 33,\n    \"conversations\": 12,\n    \"tokens\": 58440\n  }\n]"
            }
          ]
        },
        {
          "name": "Usage by model",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/usage/models?days=30",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "usage",
                "models"
              ],
              "query": [
                {
                  "key": "days",
                  "value": "30",
                  "description": "Trailing window in days, 1–365. Defaults to 30.",
                  "disabled": false
                },
                {
                  "key": "projectId",
                  "value": "8f14e45f-ceea-467a-9ae4-2c1e2f0f1a3b",
                  "description": "Optional. Restrict to one project. Omit to span the whole workspace.",
                  "disabled": true
                }
              ]
            },
            "description": "Usage grouped by the model that served each reply, busiest first."
          },
          "response": [
            {
              "name": "200 — model breakdown",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "[\n  {\n    \"modelName\": \"claude-sonnet-4\",\n    \"provider\": \"anthropic\",\n    \"messages\": 803,\n    \"tokens\": 1402388\n  },\n  {\n    \"modelName\": \"gpt-4o-mini\",\n    \"provider\": \"openai\",\n    \"messages\": 384,\n    \"tokens\": 641523\n  }\n]"
            }
          ]
        }
      ]
    },
    {
      "name": "Sessions",
      "description": "Conversations, reconstructed from recorded turns. Metadata only — Nubo does not persist message text, so transcripts are never returned.",
      "item": [
        {
          "name": "List sessions",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/sessions?page=1&pageSize=25",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "sessions"
              ],
              "query": [
                {
                  "key": "from",
                  "value": "2026-08-10T09:00:00Z",
                  "description": "Lower bound on activity, UTC, inclusive.",
                  "disabled": true
                },
                {
                  "key": "to",
                  "value": "2026-08-10T10:00:00Z",
                  "description": "Upper bound on activity, UTC, inclusive.",
                  "disabled": true
                },
                {
                  "key": "page",
                  "value": "1",
                  "description": "1-based page number.",
                  "disabled": false
                },
                {
                  "key": "pageSize",
                  "value": "25",
                  "description": "Rows per page, max 100.",
                  "disabled": false
                },
                {
                  "key": "projectId",
                  "value": "8f14e45f-ceea-467a-9ae4-2c1e2f0f1a3b",
                  "description": "Optional. Restrict to one project. Omit to span the whole workspace.",
                  "disabled": true
                }
              ]
            },
            "description": "Paged list, most recently active first.\n\n**Polling:** new activity pushes older rows down, so walking pages on a live list can skip rows. Pin both ends with `from` and `to` and page inside that closed window."
          },
          "response": [
            {
              "name": "200 — first page",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"items\": [\n    {\n      \"sessionId\": \"sess_01J9YQ2M7K4T8XN3P5RB6VW0AZ\",\n      \"startedAt\": \"2026-08-10T09:14:02Z\",\n      \"lastActivityAt\": \"2026-08-10T09:21:47Z\",\n      \"messages\": 6,\n      \"totalTokens\": 9871,\n      \"avgResponseMs\": 1720,\n      \"toolCalls\": 2,\n      \"rerankingRate\": 66.7,\n      \"models\": [\n        \"claude-sonnet-4\"\n      ]\n    }\n  ],\n  \"total\": 47,\n  \"page\": 1,\n  \"pageSize\": 25\n}"
            }
          ]
        },
        {
          "name": "Get session",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/sessions/{{sessionId}}",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "sessions",
                "{{sessionId}}"
              ],
              "query": [
                {
                  "key": "projectId",
                  "value": "8f14e45f-ceea-467a-9ae4-2c1e2f0f1a3b",
                  "description": "Optional. Restrict to one project. Omit to span the whole workspace.",
                  "disabled": true
                }
              ]
            },
            "description": "One conversation's totals plus its per-turn metadata, oldest turn first."
          },
          "response": [
            {
              "name": "200 — session detail",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"sessionId\": \"sess_01J9YQ2M7K4T8XN3P5RB6VW0AZ\",\n  \"startedAt\": \"2026-08-10T09:14:02Z\",\n  \"lastActivityAt\": \"2026-08-10T09:21:47Z\",\n  \"messages\": 2,\n  \"totalTokens\": 3310,\n  \"avgResponseMs\": 1755,\n  \"toolCalls\": 1,\n  \"rerankingRate\": 50.0,\n  \"models\": [\n    \"claude-sonnet-4\"\n  ],\n  \"turns\": [\n    {\n      \"timestamp\": \"2026-08-10T09:14:02Z\",\n      \"modelName\": \"claude-sonnet-4\",\n      \"provider\": \"anthropic\",\n      \"promptTokens\": 1180,\n      \"completionTokens\": 402,\n      \"totalTokens\": 1582,\n      \"durationMs\": 1610,\n      \"toolCalls\": 0,\n      \"rerankingApplied\": true\n    },\n    {\n      \"timestamp\": \"2026-08-10T09:21:47Z\",\n      \"modelName\": \"claude-sonnet-4\",\n      \"provider\": \"anthropic\",\n      \"promptTokens\": 1290,\n      \"completionTokens\": 438,\n      \"totalTokens\": 1728,\n      \"durationMs\": 1900,\n      \"toolCalls\": 1,\n      \"rerankingApplied\": false\n    }\n  ]\n}"
            },
            {
              "name": "404 — unknown session",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "Not Found",
              "code": 404,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"error\": {\n    \"code\": \"session_not_found\",\n    \"message\": \"No session with that id exists for this API key.\",\n    \"traceId\": \"0HN7A2QK9V1M4:00000006\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Account",
      "description": "Workspace-level information. Neither endpoint takes projectId.",
      "item": [
        {
          "name": "Balance",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/balance",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "balance"
              ]
            },
            "description": "Replies included, used and remaining in the current period.\n\n**Read `periodStart` and `periodEnd` from the response rather than computing them.** `periodBasis` is `calendar_month` today and becomes `subscription_period` when real billing periods land, at which point those dates stop falling on the 1st."
          },
          "response": [
            {
              "name": "200 — mid-period",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"planKey\": \"pro\",\n  \"included\": 10000,\n  \"used\": 3421,\n  \"remaining\": 6579,\n  \"periodStart\": \"2026-08-01T00:00:00Z\",\n  \"periodEnd\": \"2026-09-01T00:00:00Z\",\n  \"periodBasis\": \"calendar_month\"\n}"
            }
          ]
        },
        {
          "name": "Plan",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/plan",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "plan"
              ]
            },
            "description": "The plan assigned to this key's workspace and what it entitles you to. Entitlements only — no pricing or billing data."
          },
          "response": [
            {
              "name": "200 — pro plan",
              "originalRequest": {
                "method": "GET",
                "header": [],
                "url": {
                  "raw": "{{baseUrl}}"
                }
              },
              "status": "OK",
              "code": 200,
              "_postman_previewlanguage": "json",
              "header": [
                {
                  "key": "Content-Type",
                  "value": "application/json"
                }
              ],
              "cookie": [],
              "body": "{\n  \"planKey\": \"pro\",\n  \"name\": \"Pro\",\n  \"description\": \"For teams running production assistants.\",\n  \"entitlements\": {\n    \"schemaVersion\": 1,\n    \"replyAllowance\": {\n      \"included\": 10000,\n      \"period\": \"month\",\n      \"overage\": \"block\"\n    },\n    \"rateLimits\": {\n      \"requestsPerMinute\": 60,\n      \"maxConcurrent\": 8\n    },\n    \"models\": {\n      \"allowed\": [\n        \"*\"\n      ],\n      \"autoSelect\": true\n    },\n    \"features\": {\n      \"reranking\": true,\n      \"mcpTools\": true,\n      \"maxToolInvocations\": 8,\n      \"removeBranding\": true\n    },\n    \"knowledge\": {\n      \"maxSources\": 200\n    },\n    \"projects\": {\n      \"max\": 5\n    }\n  }\n}"
            }
          ]
        }
      ]
    }
  ]
}
