{
  "info": {
    "_postman_id": "d1a2b3c4-e5f6-7890-abcd-ef1234567890",
    "name": "DispoTag API",
    "description": "High-performance backend API for package tracking with disposable BLE beacon tags.\n\n## Authentication\n\nThe API uses three authentication methods depending on the endpoint:\n\n- **Dashboard API** (`/v1/*`): WorkOS JWT token in `Authorization: Bearer <token>` header\n- **Beacon API** (`/v1/beacon/*`): API key in `X-API-Key` header\n- **Hubble Webhook** (`/v1/hubble/webhook`): Shared secret in `X-HUBBLE-TOKEN` header\n\n## Rate Limits\n\n- Beacon endpoints: 1000 requests/minute per API key\n- Dashboard endpoints: 100 requests/minute per user\n\n## Tag State Machine\n\n```\nAWAITING_FIRST_PING -> AT_ORIGIN -> IN_TRANSIT -> APPROACHING -> DELIVERED -> DELIVERY_VERIFICATION -> COMPLETED\n                                       |\n                              DISPUTED_IN_TRANSIT -> COMPLETED\n```",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "base_url",
      "value": "http://localhost:8080",
      "type": "string"
    },
    {
      "key": "api_key",
      "value": "",
      "type": "string"
    },
    {
      "key": "jwt_token",
      "value": "",
      "type": "string"
    },
    {
      "key": "hubble_token",
      "value": "",
      "type": "string"
    },
    {
      "key": "tag_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "alert_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "dispute_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "org_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "invite_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "invite_token",
      "value": "",
      "type": "string"
    },
    {
      "key": "device_id",
      "value": "",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Health",
      "description": "Health check endpoints for load balancers and monitoring. No authentication required.",
      "item": [
        {
          "name": "Health check",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/health",
              "host": ["{{base_url}}"],
              "path": ["health"]
            },
            "description": "Basic liveness check. Returns 200 if server is running."
          },
          "response": []
        },
        {
          "name": "Readiness check",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/ready",
              "host": ["{{base_url}}"],
              "path": ["ready"]
            },
            "description": "Verifies all dependencies (database, Redis) are accessible."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Beacon Ingestion",
      "description": "High-volume beacon ingestion from SDKs. Uses API key authentication via X-API-Key header.",
      "item": [
        {
          "name": "Submit beacon ping",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-API-Key",
                "value": "{{api_key}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"ble_identifier\": \"AA:BB:CC:DD:EE:FF\",\n  \"lat\": 34.052235,\n  \"lng\": -118.243683,\n  \"rssi\": -65,\n  \"timestamp\": \"2026-02-19T12:00:00Z\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/beacon/ping",
              "host": ["{{base_url}}"],
              "path": ["v1", "beacon", "ping"]
            },
            "description": "Submit a single location ping from SDK."
          },
          "response": []
        },
        {
          "name": "Submit batch pings",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-API-Key",
                "value": "{{api_key}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"pings\": [\n    {\n      \"ble_identifier\": \"AA:BB:CC:DD:EE:FF\",\n      \"lat\": 34.052235,\n      \"lng\": -118.243683,\n      \"rssi\": -65,\n      \"timestamp\": \"2026-02-19T12:00:00Z\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/beacon/batch",
              "host": ["{{base_url}}"],
              "path": ["v1", "beacon", "batch"]
            },
            "description": "Submit multiple location pings in a single request."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Auth",
      "description": "Authentication endpoints (WorkOS integration). Uses Bearer JWT authentication.",
      "item": [
        {
          "name": "Get current user",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/auth/me",
              "host": ["{{base_url}}"],
              "path": ["v1", "auth", "me"]
            },
            "description": "Returns the authenticated user's profile information."
          },
          "response": []
        },
        {
          "name": "Logout",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/auth/logout",
              "host": ["{{base_url}}"],
              "path": ["v1", "auth", "logout"]
            },
            "description": "Invalidates the current session."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Tags",
      "description": "BLE beacon tag management. Uses Bearer JWT authentication.",
      "item": [
        {
          "name": "List tags",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/tags?page=1&limit=50",
              "host": ["{{base_url}}"],
              "path": ["v1", "tags"],
              "query": [
                {
                  "key": "page",
                  "value": "1",
                  "description": "Page number (1-indexed)"
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "Items per page (max 100)"
                },
                {
                  "key": "state",
                  "value": "",
                  "description": "Filter by tag state (e.g. in_transit, delivered)",
                  "disabled": true
                },
                {
                  "key": "search",
                  "value": "",
                  "description": "Search by BLE identifier, order ID, or recipient",
                  "disabled": true
                },
                {
                  "key": "order_id",
                  "value": "",
                  "description": "Filter by exact order ID",
                  "disabled": true
                }
              ]
            },
            "description": "Returns a paginated list of tags for the organization."
          },
          "response": []
        },
        {
          "name": "Create tag",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"ble_identifier\": \"DT:TEST:00:00:00:01\",\n  \"order_id\": \"ORD-1234\",\n  \"recipient_name\": \"Jane Doe\",\n  \"recipient_email\": \"jane@example.com\",\n  \"destination_lat\": 40.7128,\n  \"destination_lng\": -74.0060,\n  \"destination_address\": \"456 Main St, New York, NY\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/tags",
              "host": ["{{base_url}}"],
              "path": ["v1", "tags"]
            },
            "description": "Creates a new BLE beacon tag for tracking."
          },
          "response": []
        },
        {
          "name": "Get tag",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/tags/{{tag_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "tags", "{{tag_id}}"]
            },
            "description": "Returns details for a specific tag."
          },
          "response": []
        },
        {
          "name": "Update tag",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"recipient_name\": \"Updated Name\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/tags/{{tag_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "tags", "{{tag_id}}"]
            },
            "description": "Updates tag information (recipient, destination, metadata)."
          },
          "response": []
        },
        {
          "name": "Delete tag",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/tags/{{tag_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "tags", "{{tag_id}}"]
            },
            "description": "Soft-deletes a tag. Only allowed for tags in AWAITING_FIRST_PING state."
          },
          "response": []
        },
        {
          "name": "Get tag journey",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/tags/{{tag_id}}/journey",
              "host": ["{{base_url}}"],
              "path": ["v1", "tags", "{{tag_id}}", "journey"]
            },
            "description": "Returns the location history for a tag."
          },
          "response": []
        },
        {
          "name": "Get evidence package",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/tags/{{tag_id}}/evidence",
              "host": ["{{base_url}}"],
              "path": ["v1", "tags", "{{tag_id}}", "evidence"]
            },
            "description": "Returns proof-of-delivery evidence for dispute resolution."
          },
          "response": []
        },
        {
          "name": "Refresh carrier tracking",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/tags/{{tag_id}}/tracking",
              "host": ["{{base_url}}"],
              "path": ["v1", "tags", "{{tag_id}}", "tracking"]
            },
            "description": "Fetches the latest tracking info from the carrier API (USPS, UPS, or FedEx) for a tag. The tag must have `carrier` and `tracking_number` set."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Alerts",
      "description": "Alert and notification management. Uses Bearer JWT authentication.",
      "item": [
        {
          "name": "List alerts",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/alerts?page=1&limit=50",
              "host": ["{{base_url}}"],
              "path": ["v1", "alerts"],
              "query": [
                {
                  "key": "page",
                  "value": "1",
                  "description": "Page number (1-indexed)"
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "Items per page"
                },
                {
                  "key": "unread_only",
                  "value": "false",
                  "description": "Filter to unread alerts only",
                  "disabled": true
                }
              ]
            },
            "description": "Returns alerts for the organization."
          },
          "response": []
        },
        {
          "name": "Mark alert as read",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/alerts/{{alert_id}}/read",
              "host": ["{{base_url}}"],
              "path": ["v1", "alerts", "{{alert_id}}", "read"]
            },
            "description": "Mark a specific alert as read."
          },
          "response": []
        },
        {
          "name": "Mark all alerts as read",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/alerts/read-all",
              "host": ["{{base_url}}"],
              "path": ["v1", "alerts", "read-all"]
            },
            "description": "Mark all alerts as read for the organization."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Disputes",
      "description": "Delivery dispute resolution. Uses Bearer JWT authentication.",
      "item": [
        {
          "name": "List disputes",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/disputes?page=1&limit=50",
              "host": ["{{base_url}}"],
              "path": ["v1", "disputes"],
              "query": [
                {
                  "key": "page",
                  "value": "1",
                  "description": "Page number (1-indexed)"
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "Items per page"
                },
                {
                  "key": "status",
                  "value": "",
                  "description": "Filter by dispute status",
                  "disabled": true
                }
              ]
            },
            "description": "Returns delivery disputes for the organization."
          },
          "response": []
        },
        {
          "name": "Get dispute details",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/disputes/{{dispute_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "disputes", "{{dispute_id}}"]
            },
            "description": "Returns details for a specific dispute."
          },
          "response": []
        },
        {
          "name": "Resolve dispute",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"resolution\": \"delivered\",\n  \"notes\": \"Confirmed with customer\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/disputes/{{dispute_id}}/resolve",
              "host": ["{{base_url}}"],
              "path": ["v1", "disputes", "{{dispute_id}}", "resolve"]
            },
            "description": "Resolve a delivery dispute with a resolution and notes."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Analytics",
      "description": "Dashboard metrics and statistics. Uses Bearer JWT authentication.",
      "item": [
        {
          "name": "Dashboard metrics",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/analytics/dashboard",
              "host": ["{{base_url}}"],
              "path": ["v1", "analytics", "dashboard"]
            },
            "description": "Returns high-level metrics for the dashboard."
          },
          "response": []
        },
        {
          "name": "Delivery statistics",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/analytics/delivery",
              "host": ["{{base_url}}"],
              "path": ["v1", "analytics", "delivery"],
              "query": [
                {
                  "key": "period",
                  "value": "week",
                  "description": "Time period: day, week, month, quarter",
                  "disabled": true
                }
              ]
            },
            "description": "Returns delivery performance statistics."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Signup",
      "description": "Self-service signup and onboarding flow. POST /start is unauthenticated; all other endpoints require Bearer JWT.",
      "item": [
        {
          "name": "Start signup",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"newuser@example.com\",\n  \"password\": \"SecurePass123!\",\n  \"first_name\": \"John\",\n  \"last_name\": \"Doe\",\n  \"company_name\": \"Acme Inc\",\n  \"plan_tier\": \"solo\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/signup/start",
              "host": ["{{base_url}}"],
              "path": ["v1", "signup", "start"]
            },
            "description": "Begin a new organization signup. Creates a pending organization and initial admin user. No authentication required."
          },
          "response": []
        },
        {
          "name": "Submit business info",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"ein\": \"12-3456789\",\n  \"company_type\": \"llc\",\n  \"industry\": \"logistics\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/signup/business-info",
              "host": ["{{base_url}}"],
              "path": ["v1", "signup", "business-info"]
            },
            "description": "Submit legal name, EIN, and business details during signup."
          },
          "response": []
        },
        {
          "name": "Submit contacts",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"contacts\": [\n    {\n      \"name\": \"John Doe\",\n      \"email\": \"john@example.com\",\n      \"phone\": \"+1234567890\",\n      \"role\": \"primary\"\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/signup/contacts",
              "host": ["{{base_url}}"],
              "path": ["v1", "signup", "contacts"]
            },
            "description": "Submit primary and billing contact information."
          },
          "response": []
        },
        {
          "name": "Add address",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"line1\": \"123 Main St\",\n  \"city\": \"Los Angeles\",\n  \"state\": \"CA\",\n  \"zip\": \"90001\",\n  \"country\": \"US\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/signup/address",
              "host": ["{{base_url}}"],
              "path": ["v1", "signup", "address"]
            },
            "description": "Add corporate, billing, or shipping address."
          },
          "response": []
        },
        {
          "name": "Complete signup",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{}"
            },
            "url": {
              "raw": "{{base_url}}/v1/signup/complete",
              "host": ["{{base_url}}"],
              "path": ["v1", "signup", "complete"]
            },
            "description": "Finalize the signup process. Transitions org to active status."
          },
          "response": []
        },
        {
          "name": "Get signup status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/signup/status",
              "host": ["{{base_url}}"],
              "path": ["v1", "signup", "status"]
            },
            "description": "Check the current progress of the signup flow."
          },
          "response": []
        },
        {
          "name": "Create DocuSign envelope",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/signup/docusign/create",
              "host": ["{{base_url}}"],
              "path": ["v1", "signup", "docusign", "create"]
            },
            "description": "Create a DocuSign signing envelope for MSA/ToS/SLA (Starter+ tiers)."
          },
          "response": []
        },
        {
          "name": "DocuSign webhook",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"event\": \"envelope-completed\",\n  \"data\": {}\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/signup/docusign/webhook",
              "host": ["{{base_url}}"],
              "path": ["v1", "signup", "docusign", "webhook"]
            },
            "description": "Receives DocuSign Connect events for envelope status changes. Authenticated via DocuSign signature."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Billing",
      "description": "Stripe billing portal and payment management. Uses Bearer JWT authentication.",
      "item": [
        {
          "name": "Check upgrade eligibility",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/billing/upgrade/eligibility",
              "host": ["{{base_url}}"],
              "path": ["v1", "billing", "upgrade", "eligibility"]
            },
            "description": "Returns which tiers the organization can upgrade to."
          },
          "response": []
        },
        {
          "name": "Preview upgrade",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"target_tier\": \"starter\",\n  \"committed_monthly_volume\": 25000\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/billing/upgrade/preview",
              "host": ["{{base_url}}"],
              "path": ["v1", "billing", "upgrade", "preview"]
            },
            "description": "Get pricing comparison for a potential tier upgrade."
          },
          "response": []
        },
        {
          "name": "Initiate upgrade",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"target_tier\": \"starter\",\n  \"committed_monthly_volume\": 25000\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/billing/upgrade",
              "host": ["{{base_url}}"],
              "path": ["v1", "billing", "upgrade"]
            },
            "description": "Start a tier upgrade. Solo->Starter+ requires DocuSign; Starter+->higher is direct."
          },
          "response": []
        },
        {
          "name": "Complete upgrade",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"payment_method_id\": \"pm_xxx\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/billing/upgrade/complete",
              "host": ["{{base_url}}"],
              "path": ["v1", "billing", "upgrade", "complete"]
            },
            "description": "Finalize the upgrade after DocuSign signing and payment. Attaches payment method if provided, creates or updates Stripe subscription."
          },
          "response": []
        },
        {
          "name": "Cancel upgrade",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/billing/upgrade",
              "host": ["{{base_url}}"],
              "path": ["v1", "billing", "upgrade"]
            },
            "description": "Cancel an in-progress tier upgrade."
          },
          "response": []
        },
        {
          "name": "Get billing portal URL",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/billing/portal",
              "host": ["{{base_url}}"],
              "path": ["v1", "billing", "portal"]
            },
            "description": "Creates a Stripe billing portal session. The returned URL allows the customer to manage payment methods, view invoices, and update their subscription."
          },
          "response": []
        },
        {
          "name": "Create setup intent",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/billing/setup-intent",
              "host": ["{{base_url}}"],
              "path": ["v1", "billing", "setup-intent"]
            },
            "description": "Creates a Stripe SetupIntent for collecting payment details via Stripe Elements. Returns a client_secret for the frontend to confirm card setup."
          },
          "response": []
        },
        {
          "name": "Cancel subscription",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/billing/cancel",
              "host": ["{{base_url}}"],
              "path": ["v1", "billing", "cancel"]
            },
            "description": "Cancel the current subscription. Solo tier: allowed anytime. Starter+ tiers: blocked during 2-year commitment period."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Admin",
      "description": "DispoTag staff admin portal. Uses Bearer JWT authentication (must be staff user).",
      "item": [
        {
          "name": "Admin dashboard",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/admin/dashboard",
              "host": ["{{base_url}}"],
              "path": ["v1", "admin", "dashboard"]
            },
            "description": "Overview stats: org counts by status, user totals, tier breakdown."
          },
          "response": []
        },
        {
          "name": "List organizations",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/admin/organizations?page=1&limit=50",
              "host": ["{{base_url}}"],
              "path": ["v1", "admin", "organizations"],
              "query": [
                {
                  "key": "page",
                  "value": "1",
                  "description": "Page number (1-indexed)"
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "Items per page"
                },
                {
                  "key": "status",
                  "value": "",
                  "description": "Filter by organization status",
                  "disabled": true
                },
                {
                  "key": "plan_tier",
                  "value": "",
                  "description": "Filter by plan tier",
                  "disabled": true
                },
                {
                  "key": "search",
                  "value": "",
                  "description": "Search by company name or email",
                  "disabled": true
                }
              ]
            },
            "description": "Paginated list with filtering by status, tier, and search."
          },
          "response": []
        },
        {
          "name": "Create organization",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"company_name\": \"New Corp\",\n  \"contact_email\": \"admin@newcorp.com\",\n  \"plan_tier\": \"starter\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/admin/organizations",
              "host": ["{{base_url}}"],
              "path": ["v1", "admin", "organizations"]
            },
            "description": "Admin-created customer organization. Requires DISPOTAG_ADMIN role."
          },
          "response": []
        },
        {
          "name": "Get organization details",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/admin/organizations/{{org_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "admin", "organizations", "{{org_id}}"]
            },
            "description": "Full organization details including all fields."
          },
          "response": []
        },
        {
          "name": "Update organization",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"status\": \"active\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/admin/organizations/{{org_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "admin", "organizations", "{{org_id}}"]
            },
            "description": "Update organization fields. Status/tier/billing changes require DISPOTAG_ADMIN."
          },
          "response": []
        },
        {
          "name": "Approve Net 30 terms",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/admin/organizations/{{org_id}}/approve-net30",
              "host": ["{{base_url}}"],
              "path": ["v1", "admin", "organizations", "{{org_id}}", "approve-net30"]
            },
            "description": "Approve Net 30 payment terms for an organization. Requires DISPOTAG_ADMIN."
          },
          "response": []
        },
        {
          "name": "Start impersonation",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/admin/organizations/{{org_id}}/impersonate",
              "host": ["{{base_url}}"],
              "path": ["v1", "admin", "organizations", "{{org_id}}", "impersonate"]
            },
            "description": "Start impersonating a customer organization. Creates a 30-minute session."
          },
          "response": []
        },
        {
          "name": "End impersonation",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/admin/impersonate",
              "host": ["{{base_url}}"],
              "path": ["v1", "admin", "impersonate"]
            },
            "description": "End the active impersonation session."
          },
          "response": []
        },
        {
          "name": "Impersonation status",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/admin/impersonate/status",
              "host": ["{{base_url}}"],
              "path": ["v1", "admin", "impersonate", "status"]
            },
            "description": "Get the current impersonation session status."
          },
          "response": []
        },
        {
          "name": "List audit logs",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/admin/audit-logs?page=1&limit=50",
              "host": ["{{base_url}}"],
              "path": ["v1", "admin", "audit-logs"],
              "query": [
                {
                  "key": "page",
                  "value": "1",
                  "description": "Page number (1-indexed)"
                },
                {
                  "key": "limit",
                  "value": "50",
                  "description": "Items per page"
                },
                {
                  "key": "organization_id",
                  "value": "",
                  "description": "Filter by organization UUID",
                  "disabled": true
                },
                {
                  "key": "user_id",
                  "value": "",
                  "description": "Filter by user UUID",
                  "disabled": true
                },
                {
                  "key": "action",
                  "value": "",
                  "description": "Filter by action type",
                  "disabled": true
                }
              ]
            },
            "description": "Paginated audit log viewer with filtering."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Users & Invites",
      "description": "User invite management. Uses Bearer JWT authentication.",
      "item": [
        {
          "name": "Create invite",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"newuser@company.com\",\n  \"role\": \"manager\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/users/invite",
              "host": ["{{base_url}}"],
              "path": ["v1", "users", "invite"]
            },
            "description": "Send an invite to a new user. Enforces user limits per plan tier."
          },
          "response": []
        },
        {
          "name": "List invites",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/users/invites",
              "host": ["{{base_url}}"],
              "path": ["v1", "users", "invites"]
            },
            "description": "List pending invites for the current organization."
          },
          "response": []
        },
        {
          "name": "Cancel invite",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/users/invites/{{invite_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "users", "invites", "{{invite_id}}"]
            },
            "description": "Cancel a pending invite."
          },
          "response": []
        },
        {
          "name": "Accept invite",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"first_name\": \"New\",\n  \"last_name\": \"User\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/users/invites/{{invite_token}}/accept",
              "host": ["{{base_url}}"],
              "path": ["v1", "users", "invites", "{{invite_token}}", "accept"]
            },
            "description": "Accept an invite using the token, creating the user account."
          },
          "response": []
        }
      ]
    },
    {
      "name": "SSO & Directory Sync",
      "description": "SSO and Directory Sync configuration. Uses Bearer JWT authentication.",
      "item": [
        {
          "name": "Get SSO config",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/settings/sso",
              "host": ["{{base_url}}"],
              "path": ["v1", "settings", "sso"]
            },
            "description": "Get SSO and directory sync configuration for the current organization."
          },
          "response": []
        },
        {
          "name": "Configure SSO",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"provider\": \"okta\",\n  \"connection_id\": \"conn_xxx\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/settings/sso",
              "host": ["{{base_url}}"],
              "path": ["v1", "settings", "sso"]
            },
            "description": "Link a WorkOS SSO connection. Only Growth, Scale, Enterprise tiers."
          },
          "response": []
        },
        {
          "name": "Disable SSO",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/settings/sso",
              "host": ["{{base_url}}"],
              "path": ["v1", "settings", "sso"]
            },
            "description": "Remove the SSO connection. Requires admin role."
          },
          "response": []
        },
        {
          "name": "Configure directory sync",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"directory_id\": \"dir_xxx\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/settings/directory",
              "host": ["{{base_url}}"],
              "path": ["v1", "settings", "directory"]
            },
            "description": "Link a WorkOS directory for automatic user provisioning. Growth+ tiers only."
          },
          "response": []
        },
        {
          "name": "Disable directory sync",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/settings/directory",
              "host": ["{{base_url}}"],
              "path": ["v1", "settings", "directory"]
            },
            "description": "Remove the directory connection. Existing users remain."
          },
          "response": []
        },
        {
          "name": "List directory users",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/settings/directory/users",
              "host": ["{{base_url}}"],
              "path": ["v1", "settings", "directory", "users"]
            },
            "description": "List users provisioned via directory sync."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Webhooks",
      "description": "Incoming webhooks from third-party services. Authenticated via service-specific signatures.",
      "item": [
        {
          "name": "Stripe webhook",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "Stripe-Signature",
                "value": "t=1234567890,v1=signature_here",
                "type": "text",
                "description": "Stripe webhook signature header (t=timestamp,v1=signature)"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"id\": \"evt_test_123\",\n  \"type\": \"invoice.paid\",\n  \"data\": {\n    \"object\": {}\n  }\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/webhooks/stripe",
              "host": ["{{base_url}}"],
              "path": ["v1", "webhooks", "stripe"]
            },
            "description": "Receives events from Stripe (invoice.paid, invoice.payment_failed, customer.subscription.deleted, customer.subscription.updated). Validates the webhook signature using HMAC-SHA256."
          },
          "response": []
        },
        {
          "name": "WorkOS webhook",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              },
              {
                "key": "WorkOS-Signature",
                "value": "t=1234567890,v1=signature_here",
                "type": "text",
                "description": "WorkOS webhook signature header"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"event\": \"dsync.user.created\",\n  \"data\": {}\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/webhooks/workos",
              "host": ["{{base_url}}"],
              "path": ["v1", "webhooks", "workos"]
            },
            "description": "Receives WorkOS directory sync events (user created/updated/deleted)."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Hubble",
      "description": "Hubble Network satellite integration. Mixed authentication: webhook uses X-HUBBLE-TOKEN, device endpoints use Bearer JWT.",
      "item": [
        {
          "name": "Hubble webhook",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "X-HUBBLE-TOKEN",
                "value": "{{hubble_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"device_id\": \"hubble-device-001\",\n  \"lat\": 34.052235,\n  \"lng\": -118.243683,\n  \"timestamp\": \"2026-02-19T12:00:00Z\",\n  \"payload\": {}\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/hubble/webhook",
              "host": ["{{base_url}}"],
              "path": ["v1", "hubble", "webhook"]
            },
            "description": "Receives satellite location data from Hubble Network."
          },
          "response": []
        },
        {
          "name": "Register Hubble device",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              },
              {
                "key": "Content-Type",
                "value": "application/json",
                "type": "text"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"device_name\": \"my-tag-001\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/hubble/devices",
              "host": ["{{base_url}}"],
              "path": ["v1", "hubble", "devices"]
            },
            "description": "Registers a new device with Hubble Network."
          },
          "response": []
        },
        {
          "name": "List Hubble devices",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/hubble/devices",
              "host": ["{{base_url}}"],
              "path": ["v1", "hubble", "devices"]
            },
            "description": "Lists devices registered with Hubble Network."
          },
          "response": []
        },
        {
          "name": "Get Hubble device",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/hubble/devices/{{device_id}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "hubble", "devices", "{{device_id}}"]
            },
            "description": "Get details for a specific Hubble device."
          },
          "response": []
        },
        {
          "name": "Get Hubble packets",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{jwt_token}}",
                "type": "text"
              }
            ],
            "url": {
              "raw": "{{base_url}}/v1/hubble/packets?limit=100",
              "host": ["{{base_url}}"],
              "path": ["v1", "hubble", "packets"],
              "query": [
                {
                  "key": "limit",
                  "value": "100",
                  "description": "Maximum number of packets to return"
                },
                {
                  "key": "device_id",
                  "value": "",
                  "description": "Filter by device ID",
                  "disabled": true
                },
                {
                  "key": "start",
                  "value": "",
                  "description": "Start datetime (ISO 8601)",
                  "disabled": true
                },
                {
                  "key": "end",
                  "value": "",
                  "description": "End datetime (ISO 8601)",
                  "disabled": true
                }
              ]
            },
            "description": "Retrieves location packets from Hubble (admin/debug)."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Public Tracking",
      "description": "Unauthenticated public tracking endpoints for shareable tracking pages. Rate limited to 60 req/min per IP.",
      "item": [
        {
          "name": "Get shipment tracking (short URL)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/public/tracking/shipment/{{tracking_number}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "public", "tracking", "shipment", "{{tracking_number}}"]
            },
            "description": "Get tracking data for a shipment by tracking number. This is the preferred short URL format. The frontend renders this at /shipment/{trackingNumber}."
          },
          "response": []
        },
        {
          "name": "Get shipment tracking (legacy URL)",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/public/tracking/shipment/{{carrier_name}}/{{tracking_number}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "public", "tracking", "shipment", "{{carrier_name}}", "{{tracking_number}}"]
            },
            "description": "Get tracking data for a shipment by carrier name and tracking number. Legacy two-segment URL — still works but prefer the short URL format above."
          },
          "response": []
        },
        {
          "name": "Get tag tracking",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/public/tracking/tag/{{tag_serial}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "public", "tracking", "tag", "{{tag_serial}}"]
            },
            "description": "Get tracking data for a single tag by its BLE serial number. The frontend renders this at /tag/{serial}."
          },
          "response": []
        },
        {
          "name": "Get order tracking",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{base_url}}/v1/public/tracking/order/{{shop_slug}}/{{order_number}}",
              "host": ["{{base_url}}"],
              "path": ["v1", "public", "tracking", "order", "{{shop_slug}}", "{{order_number}}"]
            },
            "description": "Get tracking data for a Shopify order by shop slug and order number."
          },
          "response": []
        },
        {
          "name": "Subscribe to tag notifications",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone\": \"+15551234567\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/public/tracking/tag/{{tag_serial}}/subscribe",
              "host": ["{{base_url}}"],
              "path": ["v1", "public", "tracking", "tag", "{{tag_serial}}", "subscribe"]
            },
            "description": "Subscribe a phone number to SMS delivery notifications for a tag."
          },
          "response": []
        },
        {
          "name": "Subscribe to shipment notifications",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone\": \"+15551234567\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/v1/public/tracking/shipment/{{tracking_number}}/subscribe",
              "host": ["{{base_url}}"],
              "path": ["v1", "public", "tracking", "shipment", "{{tracking_number}}", "subscribe"]
            },
            "description": "Subscribe a phone number to SMS delivery notifications for all tags in a shipment."
          },
          "response": []
        }
      ]
    }
  ]
}