{
  "info": {
    "name": "CanaryGuard API v1",
    "description": "REST API for the CanaryGuard canary token platform.\n\nBase URL: https://www.canaryguard.app/api/v1\n\nAuthentication: Bearer token (API key from /settings/api-keys)\n\nDocs: https://www.canaryguard.app/docs/api",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://www.canaryguard.app",
      "type": "string"
    },
    {
      "key": "api_key",
      "value": "cg_live_your_key_here",
      "type": "string",
      "description": "Replace with your actual API key from /settings/api-keys"
    },
    {
      "key": "token_id",
      "value": "",
      "type": "string",
      "description": "Auto-set after creating a token"
    },
    {
      "key": "alert_id",
      "value": "",
      "type": "string",
      "description": "Set to an alert ID for mark-reviewed requests"
    }
  ],
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{api_key}}",
        "type": "string"
      }
    ]
  },
  "item": [
    {
      "name": "Health",
      "item": [
        {
          "name": "Health Check",
          "request": {
            "auth": { "type": "noauth" },
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/health",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "health"]
            },
            "description": "Check if the API is running. No authentication required."
          },
          "response": [
            {
              "name": "200 OK",
              "status": "OK",
              "code": 200,
              "header": [{ "key": "Content-Type", "value": "application/json" }],
              "body": "{\n  \"data\": {\n    \"status\": \"ok\",\n    \"version\": \"1.0.0\"\n  }\n}"
            }
          ]
        }
      ]
    },
    {
      "name": "Tokens",
      "item": [
        {
          "name": "List Tokens",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/tokens?page=1&limit=20",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "tokens"],
              "query": [
                { "key": "page", "value": "1", "description": "Page number (default: 1)" },
                { "key": "limit", "value": "20", "description": "Results per page (max: 100)" },
                { "key": "type", "value": "http", "description": "Filter by type: http, dns, image, email, document_docx, document_pdf, qr_code, env_config", "disabled": true },
                { "key": "status", "value": "active", "description": "Filter by status: active, paused, expired, triggered", "disabled": true }
              ]
            },
            "description": "List all tokens for your organization with optional filtering and pagination."
          }
        },
        {
          "name": "Create HTTP Token",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "if (pm.response.code === 201) {",
                  "  var json = pm.response.json();",
                  "  if (json.data && json.data.id) {",
                  "    pm.collectionVariables.set('token_id', json.data.id);",
                  "    console.log('Saved token_id: ' + json.data.id);",
                  "  }",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\": \"http\",\n  \"name\": \"prod-aws-config\",\n  \"memo\": \"Planted in staging/.env\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v1/tokens",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "tokens"]
            },
            "description": "Create an HTTP/URL canary token. The callback URL triggers an alert when visited."
          }
        },
        {
          "name": "Create DNS Token",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "if (pm.response.code === 201) {",
                  "  var json = pm.response.json();",
                  "  if (json.data && json.data.id) {",
                  "    pm.collectionVariables.set('token_id', json.data.id);",
                  "  }",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\": \"dns\",\n  \"name\": \"internal-db-host\",\n  \"memo\": \"Planted in SSH config\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v1/tokens",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "tokens"]
            },
            "description": "Create a DNS canary token. Triggers alert when the hostname is resolved via dig/nslookup."
          }
        },
        {
          "name": "Create Config File (.env) Token",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "if (pm.response.code === 201) {",
                  "  var json = pm.response.json();",
                  "  if (json.data && json.data.id) {",
                  "    pm.collectionVariables.set('token_id', json.data.id);",
                  "  }",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"type\": \"env_config\",\n  \"name\": \"production-env-decoy\",\n  \"memo\": \"Planted in /var/www/app/.env.production\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v1/tokens",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "tokens"]
            },
            "description": "Create a fake .env config file token. Contains realistic API keys with an embedded tracking URL."
          }
        },
        {
          "name": "Get Token",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/tokens/{{token_id}}",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "tokens", "{{token_id}}"]
            },
            "description": "Get details of a single token by ID."
          }
        },
        {
          "name": "Delete Token",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/tokens/{{token_id}}",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "tokens", "{{token_id}}"]
            },
            "description": "Permanently delete a token and all its alerts. Returns 404 if token doesn't exist."
          }
        },
        {
          "name": "Update Token Status",
          "request": {
            "method": "PATCH",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"status\": \"paused\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v1/tokens/{{token_id}}",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "tokens", "{{token_id}}"]
            },
            "description": "Update a token's status. Set to \"active\" or \"paused\"."
          }
        },
        {
          "name": "Clone Token",
          "event": [
            {
              "listen": "test",
              "script": {
                "exec": [
                  "if (pm.response.code === 201) {",
                  "  var json = pm.response.json();",
                  "  if (json.data && json.data.id) {",
                  "    pm.collectionVariables.set('token_id', json.data.id);",
                  "    console.log('Saved cloned token_id: ' + json.data.id);",
                  "  }",
                  "}"
                ],
                "type": "text/javascript"
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"name\": \"cloned-token\",\n  \"memo\": \"Cloned from original\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v1/tokens/{{token_id}}/clone",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "tokens", "{{token_id}}", "clone"]
            },
            "description": "Clone an existing token with a new callback ID. Inherits the same type and optionally the memo from the original."
          }
        },
        {
          "name": "Batch Create Tokens",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"tokens\": [\n    {\"type\": \"http\", \"name\": \"honeypot-1\"},\n    {\"type\": \"dns\", \"name\": \"honeypot-2\", \"memo\": \"DNS decoy\"},\n    {\"type\": \"http\", \"name\": \"honeypot-3\"}\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v1/tokens/batch",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "tokens", "batch"]
            },
            "description": "Bulk create up to 50 tokens in a single request. Each item requires type and name. Partial failures are reported per-item."
          }
        },
        {
          "name": "List Token Alerts",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/tokens/{{token_id}}/alerts?page=1&limit=20",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "tokens", "{{token_id}}", "alerts"],
              "query": [
                { "key": "page", "value": "1", "description": "Page number (default: 1)" },
                { "key": "limit", "value": "20", "description": "Results per page (max: 100)" },
                { "key": "after", "value": "2026-01-01", "description": "Only alerts after this date (ISO 8601)", "disabled": true },
                { "key": "before", "value": "2026-12-31", "description": "Only alerts before this date (ISO 8601)", "disabled": true }
              ]
            },
            "description": "List alerts for a specific token. Supports pagination and date range filtering."
          }
        }
      ]
    },
    {
      "name": "Alerts",
      "item": [
        {
          "name": "List Alerts",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/alerts?page=1&limit=20",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "alerts"],
              "query": [
                { "key": "page", "value": "1", "description": "Page number" },
                { "key": "limit", "value": "20", "description": "Results per page" },
                { "key": "token_id", "value": "", "description": "Filter by token ID", "disabled": true },
                { "key": "after", "value": "2026-01-01", "description": "Only alerts after this date (ISO 8601)", "disabled": true },
                { "key": "before", "value": "2026-12-31", "description": "Only alerts before this date (ISO 8601)", "disabled": true }
              ]
            },
            "description": "List all alerts for your organization. Each alert includes source IP, geolocation, user agent, and timestamp."
          }
        },
        {
          "name": "Mark Alert Reviewed",
          "request": {
            "method": "POST",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/alerts/{{alert_id}}/reviewed",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "alerts", "{{alert_id}}", "reviewed"]
            },
            "description": "Mark an alert as reviewed. Useful for triaging alerts and tracking which have been investigated."
          }
        }
      ]
    },
    {
      "name": "Billing",
      "item": [
        {
          "name": "Get Billing Info",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/billing",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "billing"]
            },
            "description": "Get the current plan, token usage, credits balance, and custom domain status for your account."
          }
        }
      ]
    },
    {
      "name": "Stats",
      "item": [
        {
          "name": "Get Statistics",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/api/v1/stats",
              "host": ["{{base_url}}"],
              "path": ["api", "v1", "stats"]
            },
            "description": "Get aggregated statistics including total tokens, active tokens, total alerts, alerts today, and top 5 triggered tokens."
          }
        }
      ]
    }
  ]
}
