{
  "info": {
    "name": "Light AI API",
    "description": "Light AI public API 2026-11-01. Docs: https://docs.light-ai.app. Set LIGHT_AI_API_KEY to a lai_test_ key to start.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{LIGHT_AI_API_KEY}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://api.light-ai.app"
    },
    {
      "key": "LIGHT_AI_API_KEY",
      "value": ""
    },
    {
      "key": "organization",
      "value": ""
    },
    {
      "key": "INBOUND_SOURCE_SECRET",
      "value": ""
    }
  ],
  "item": [
    {
      "name": "Account",
      "description": "Status and the identity of the presented credential.",
      "item": [
        {
          "name": "API status",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/status",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "status"
              ]
            },
            "description": "API status\n\nUnauthenticated liveness check (no database access). `HEAD` works here and on every GET route (uptime monitors).",
            "auth": {
              "type": "noauth"
            }
          }
        },
        {
          "name": "Who am I",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/me",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "me"
              ]
            },
            "description": "Who am I\n\nThe credential's organization (or partner), effective scopes (key ∩ grant ∩ plan), entitlements, limits and API version. Doubles as an authenticated health check. Partner keys add `Light-AI-Organization` to see one connected organization."
          }
        }
      ]
    },
    {
      "name": "Leads",
      "description": "Inbound estimate requests from every channel, deduplicated into touches.",
      "item": [
        {
          "name": "Create a lead",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/leads",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "leads"
              ]
            },
            "description": "Create a lead\n\nCreates an inbound estimate request. Never loses a request: a repeat request for the same address and service on an open lead becomes a **touch** (`lead.touched`, HTTP 200), an `external_ref` your integration already sent replays the original lead (HTTP 200, `replayed: true`), and a paused organization **holds** the lead (converted on resume). \n\nWithout `leads:read` every answer is the same receipt (HTTP 202), so the response never reveals whether a person already exists. A lead without an address is stored and becomes a project when one is added.\n\nScope: leads:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"source\": \"google_lsa\",\n  \"source_detail\": \"LSA message lead\",\n  \"external_ref\": {\n    \"system\": \"google_lsa\",\n    \"namespace\": \"ads-123-456-7890\",\n    \"id\": \"8813377001\"\n  },\n  \"contact\": {\n    \"first_name\": \"Dana\",\n    \"last_name\": \"Reyes\",\n    \"email\": \"dana@example.com\",\n    \"phone\": \"+1 (512) 555-0134\"\n  },\n  \"address\": {\n    \"line1\": \"4102 Oak Hollow Dr\",\n    \"city\": \"Austin\",\n    \"region\": \"TX\",\n    \"postal_code\": \"78731\",\n    \"country\": \"US\"\n  },\n  \"service_interest\": \"christmas_lights\",\n  \"message\": \"Roofline plus the two front trees, warm white.\",\n  \"attribution\": {\n    \"utm_source\": \"google\",\n    \"utm_medium\": \"lsa\",\n    \"campaign_id\": \"2093\"\n  },\n  \"consent\": {\n    \"email\": true,\n    \"sms\": true,\n    \"marketing\": false,\n    \"text\": \"I agree to be contacted by text.\",\n    \"captured_at\": \"2026-10-12T14:03:11Z\",\n    \"method\": \"lsa_message\"\n  },\n  \"custom_fields\": {\n    \"hoa\": \"yes\"\n  },\n  \"submitted_at\": \"2026-10-12T14:03:11Z\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "List leads",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/leads",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "leads"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "sort",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "source",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "created_after",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "created_before",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "updated_since",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "updated_after",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "external_ref",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "external_ref_namespace",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "form_id",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "List leads\n\nNewest first by default. For an incremental sync use `sort=updated_asc&updated_since=…`, follow `next_cursor`, and start the next poll a few minutes before your last `updated_at` (de-duplicate by id): a late commit can carry an earlier timestamp. For a gapless change feed poll GET /v1/events?sort=sync_asc.\n\nScope: leads:read"
          }
        },
        {
          "name": "Search leads by email, phone or address",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/leads/search",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "leads",
                "search"
              ]
            },
            "description": "Search leads by email, phone or address\n\nLookups by personal data go in the request body, never the query string. Returns at most 100 matches, newest first.\n\nScope: leads:read",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"dana@example.com\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Retrieve a lead",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/leads/:lead_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "leads",
                ":lead_id"
              ],
              "variable": [
                {
                  "key": "lead_id",
                  "value": "",
                  "description": "The lead id (`lead_…`)."
                }
              ]
            },
            "description": "Retrieve a lead\n\nScope: leads:read"
          }
        },
        {
          "name": "Update a lead",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/leads/:lead_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "leads",
                ":lead_id"
              ],
              "variable": [
                {
                  "key": "lead_id",
                  "value": "",
                  "description": "The lead id (`lead_…`), or the receipt id (`rcpt_…`) your own credential's request was answered with."
                }
              ]
            },
            "description": "Update a lead\n\nChange the status (`new`, `archived`, `spam`), notes or reason, or add the street address of a lead that has none yet (no address, or only a ZIP or city): it then converts to a project and `lead.updated` reports the address. Archiving with reason `test` also archives its untouched intake project; nothing is ever deleted. Without `leads:read` only leads your own credential created can be changed, and the answer is a receipt. **Intake-only keys**: address the request by the receipt id `POST /v1/leads` answered with (`/v1/leads/rcpt_…`) to add the address later; a receipt id only takes `address` (and `source_system`) and only changes a lead your credential created. Without `leads:read` every receipt answer is the same 200 receipt (also when the request was folded into someone else's lead, which is never changed, or the lead already has its street address).\n\nScope: leads:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"status\": \"archived\",\n  \"reason\": \"test\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "List the repeat requests folded into a lead",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/leads/:lead_id/touches",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "leads",
                ":lead_id",
                "touches"
              ],
              "variable": [
                {
                  "key": "lead_id",
                  "value": "",
                  "description": "The lead id (`lead_…`)."
                }
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "List the repeat requests folded into a lead\n\nScope: leads:read"
          }
        },
        {
          "name": "Set your id for a lead",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/leads/:object_id/external_refs/:system",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "leads",
                ":object_id",
                "external_refs",
                ":system"
              ],
              "variable": [
                {
                  "key": "object_id",
                  "value": "",
                  "description": "The lead id, or the receipt id (`rcpt_…`) of your own credential's request."
                },
                {
                  "key": "system",
                  "value": "",
                  "description": "Lowercase system name, e.g. `jobber`."
                }
              ]
            },
            "description": "Set your id for a lead\n\nWrites back your CRM id. References are namespaced by integration: you can never overwrite another integration's ids.\n\nScope: leads:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"id\": \"Z2lkOi8vSm9iYmVy\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Remove your id for a lead",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/leads/:object_id/external_refs/:system",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "leads",
                ":object_id",
                "external_refs",
                ":system"
              ],
              "variable": [
                {
                  "key": "object_id",
                  "value": "",
                  "description": "The lead id, or the receipt id (`rcpt_…`) of your own credential's request."
                },
                {
                  "key": "system",
                  "value": "",
                  "description": "Lowercase system name, e.g. `jobber`."
                }
              ],
              "query": [
                {
                  "key": "namespace",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "Remove your id for a lead\n\nScope: leads:write"
          }
        }
      ]
    },
    {
      "name": "Clients",
      "description": "Customers and their properties.",
      "item": [
        {
          "name": "List clients",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/clients",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "clients"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "sort",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "created_after",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "created_before",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "updated_since",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "updated_after",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "external_ref",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "external_ref_namespace",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "List clients\n\nScope: clients:read"
          }
        },
        {
          "name": "Create or update a client",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/clients",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "clients"
              ]
            },
            "description": "Create or update a client\n\nMatches your own `external_ref` first, then the exact email, then the phone; otherwise creates the client. An `address` adds that property when it is new for the client. Without `clients:read` the answer carries the id only.\n\nScope: clients:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"first_name\": \"Dana\",\n  \"last_name\": \"Reyes\",\n  \"email\": \"dana@example.com\",\n  \"phone\": \"+15125550134\",\n  \"external_ref\": {\n    \"system\": \"hubspot\",\n    \"id\": \"contact:5501\"\n  },\n  \"source_system\": \"hubspot\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Search clients by email, phone or address",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/clients/search",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "clients",
                "search"
              ]
            },
            "description": "Search clients by email, phone or address\n\nScope: clients:read",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"email\": \"dana@example.com\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Retrieve a client",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/clients/:client_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "clients",
                ":client_id"
              ],
              "variable": [
                {
                  "key": "client_id",
                  "value": "",
                  "description": "The client id (`cli_…`)."
                }
              ]
            },
            "description": "Retrieve a client\n\nScope: clients:read"
          }
        },
        {
          "name": "Update a client",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/clients/:client_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "clients",
                ":client_id"
              ],
              "variable": [
                {
                  "key": "client_id",
                  "value": "",
                  "description": "The client id (`cli_…`)."
                }
              ]
            },
            "description": "Update a client\n\nChanges the name, email or phone. `null` (or \"\") clears a field; a null or \"\" `source_system` is absent.\n\nScope: clients:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"phone\": \"+15125550199\",\n  \"source_system\": \"jobber\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "List a client's properties",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/clients/:client_id/properties",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "clients",
                ":client_id",
                "properties"
              ],
              "variable": [
                {
                  "key": "client_id",
                  "value": "",
                  "description": "The client id (`cli_…`)."
                }
              ]
            },
            "description": "List a client's properties\n\nScope: clients:read"
          }
        },
        {
          "name": "Add a property to a client",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/clients/:client_id/properties",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "clients",
                ":client_id",
                "properties"
              ],
              "variable": [
                {
                  "key": "client_id",
                  "value": "",
                  "description": "The client id (`cli_…`)."
                }
              ]
            },
            "description": "Add a property to a client\n\nAn identical address returns the existing property. `is_primary` moves the primary flag atomically.\n\nScope: clients:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"address\": {\n    \"line1\": \"88 Lantern Way\",\n    \"city\": \"Austin\",\n    \"region\": \"TX\",\n    \"postal_code\": \"78731\"\n  },\n  \"is_primary\": false\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Set your id for a client",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/clients/:object_id/external_refs/:system",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "clients",
                ":object_id",
                "external_refs",
                ":system"
              ],
              "variable": [
                {
                  "key": "object_id",
                  "value": "",
                  "description": "The client id."
                },
                {
                  "key": "system",
                  "value": "",
                  "description": "Lowercase system name, e.g. `jobber`."
                }
              ]
            },
            "description": "Set your id for a client\n\nWrites back your CRM id. References are namespaced by integration: you can never overwrite another integration's ids.\n\nScope: clients:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"id\": \"Z2lkOi8vSm9iYmVy\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Remove your id for a client",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/clients/:object_id/external_refs/:system",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "clients",
                ":object_id",
                "external_refs",
                ":system"
              ],
              "variable": [
                {
                  "key": "object_id",
                  "value": "",
                  "description": "The client id."
                },
                {
                  "key": "system",
                  "value": "",
                  "description": "Lowercase system name, e.g. `jobber`."
                }
              ],
              "query": [
                {
                  "key": "namespace",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "Remove your id for a client\n\nScope: clients:write"
          }
        }
      ]
    },
    {
      "name": "Projects",
      "description": "Jobs in the pipeline. The project id is the stable key across quote revisions.",
      "item": [
        {
          "name": "List projects",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/projects",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "projects"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "sort",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "pipeline_stage",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "client_id",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "created_after",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "created_before",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "updated_since",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "updated_after",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "external_ref",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "external_ref_namespace",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "List projects\n\nScope: projects:read"
          }
        },
        {
          "name": "Retrieve a project",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/projects/:project_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "projects",
                ":project_id"
              ],
              "variable": [
                {
                  "key": "project_id",
                  "value": "",
                  "description": "The project id (`prj_…`)."
                }
              ]
            },
            "description": "Retrieve a project\n\nScope: projects:read"
          }
        },
        {
          "name": "Move a project to another pipeline stage",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/projects/:project_id/stage",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "projects",
                ":project_id",
                "stage"
              ],
              "variable": [
                {
                  "key": "project_id",
                  "value": "",
                  "description": "The project id (`prj_…`)."
                }
              ]
            },
            "description": "Move a project to another pipeline stage\n\nExactly the manual move a team member can make in the pipeline: a display stage, never an approval (use `mark_approved` for that). `expected_stage` protects against overwriting a newer change (409 `stale_state`).\n\nScope: projects:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"expected_stage\": \"quote_sent\",\n  \"stage\": \"closed_lost\",\n  \"reason\": \"Went with another company\",\n  \"source_system\": \"hubspot\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Pipeline stage totals",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/pipeline/stages",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "pipeline",
                "stages"
              ]
            },
            "description": "Pipeline stage totals\n\nProject count per stage, and its value with quotes:read. Archived projects are excluded.\n\nScope: projects:read"
          }
        },
        {
          "name": "Set your id for a project",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/projects/:object_id/external_refs/:system",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "projects",
                ":object_id",
                "external_refs",
                ":system"
              ],
              "variable": [
                {
                  "key": "object_id",
                  "value": "",
                  "description": "The project id."
                },
                {
                  "key": "system",
                  "value": "",
                  "description": "Lowercase system name, e.g. `jobber`."
                }
              ]
            },
            "description": "Set your id for a project\n\nWrites back your CRM id. References are namespaced by integration: you can never overwrite another integration's ids.\n\nScope: projects:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"id\": \"Z2lkOi8vSm9iYmVy\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Remove your id for a project",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/projects/:object_id/external_refs/:system",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "projects",
                ":object_id",
                "external_refs",
                ":system"
              ],
              "variable": [
                {
                  "key": "object_id",
                  "value": "",
                  "description": "The project id."
                },
                {
                  "key": "system",
                  "value": "",
                  "description": "Lowercase system name, e.g. `jobber`."
                }
              ],
              "query": [
                {
                  "key": "namespace",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "Remove your id for a project\n\nScope: projects:write"
          }
        }
      ]
    },
    {
      "name": "Quotes",
      "description": "Published quotes with line items, totals, deposit, assets and outcomes.",
      "item": [
        {
          "name": "Durable quote image link",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/a/:token",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "a",
                ":token"
              ],
              "variable": [
                {
                  "key": "token",
                  "value": "",
                  "description": "The signed link token."
                }
              ]
            },
            "description": "Durable quote image link\n\nLinks handed out with the quotes:asset_links scope. Each hit re-checks the issuing key or grant, the organization and the customer link, then redirects (302) to a 60-second signed image URL. Revoking the key or grant, disabling or rotating the customer link, or the 30-day limit stops the link. Query parameters appended by email and marketing tools (utm_*, click ids) are ignored; `HEAD` answers like GET without a body.",
            "auth": {
              "type": "noauth"
            }
          }
        },
        {
          "name": "List published quotes",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/quotes",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "quotes"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "sort",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "project_id",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "is_current",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "created_after",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "created_before",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "updated_since",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "updated_after",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "external_ref",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "external_ref_namespace",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "List published quotes\n\nDrafts are never exposed. With `status` or `is_current` a page may be short (or empty) while `has_more` is true: keep following `next_cursor`. With `quotes:asset_links`, `assets.*.url` are durable image links (as on GET /v1/quotes/{id}).\n\nScope: quotes:read"
          }
        },
        {
          "name": "Retrieve a quote",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/quotes/:quote_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "quotes",
                ":quote_id"
              ],
              "variable": [
                {
                  "key": "quote_id",
                  "value": "",
                  "description": "The quote id (`qt_…`)."
                }
              ]
            },
            "description": "Retrieve a quote\n\nWith `quotes:asset_links`, `assets.*.url` are durable links that work while the customer link is active (at most 30 days).\n\nScope: quotes:read"
          }
        },
        {
          "name": "Get signed links to a quote's images and PDF",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/quotes/:quote_id/assets",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "quotes",
                ":quote_id",
                "assets"
              ],
              "variable": [
                {
                  "key": "quote_id",
                  "value": "",
                  "description": "The quote id (`qt_…`)."
                }
              ]
            },
            "description": "Get signed links to a quote's images and PDF\n\nFresh signed URLs valid for 60 minutes. An image that no longer exists is `removed: true` with a null URL. With `quotes:asset_links`, each also has a `durable_url` you can store in a CRM.\n\nScope: quotes:read"
          }
        },
        {
          "name": "A quote's timeline (published, viewed, decided)",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/quotes/:quote_id/timeline",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "quotes",
                ":quote_id",
                "timeline"
              ],
              "variable": [
                {
                  "key": "quote_id",
                  "value": "",
                  "description": "The quote id (`qt_…`)."
                }
              ]
            },
            "description": "A quote's timeline (published, viewed, decided)\n\nViews require the organization's engagement entitlement; otherwise `engagement_available` is false.\n\nScope: quotes:read"
          }
        },
        {
          "name": "Record an approval made outside Light AI",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/quotes/:quote_id/mark_approved",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "quotes",
                ":quote_id",
                "mark_approved"
              ],
              "variable": [
                {
                  "key": "quote_id",
                  "value": "",
                  "description": "The quote id (`qt_…`)."
                }
              ]
            },
            "description": "Record an approval made outside Light AI\n\nFor a homeowner who approved in your CRM or field app (e.g. Jobber). Works on the current published revision while it is `sent`; 409 `quote_already_decided` if the homeowner already decided in Light AI and 409 `quote_not_current` for an older revision. A different selection creates the approved quote with its own id (`replaces_quote_id`). Emits `quote.approved`. Test keys run the same contract on the quotes test mode created (publish one with `POST /v1/test_helpers/leads/{lead_id}/publish_quote`); events reach test endpoints only.\n\nScope: quotes:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"approved_at\": \"2026-10-14T16:00:00Z\",\n  \"external_ref\": {\n    \"system\": \"jobber\",\n    \"id\": \"Z2lkOi8vSm9iYmVyL1F1b3RlLzE\"\n  },\n  \"signed_by\": \"Dana Reyes\",\n  \"note\": \"Approved in Jobber\",\n  \"source_system\": \"jobber\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Record a decline made outside Light AI",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/quotes/:quote_id/mark_declined",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "quotes",
                ":quote_id",
                "mark_declined"
              ],
              "variable": [
                {
                  "key": "quote_id",
                  "value": "",
                  "description": "The quote id (`qt_…`)."
                }
              ]
            },
            "description": "Record a decline made outside Light AI\n\nSame rules as mark_approved. The customer link stops accepting approvals. Emits `quote.declined` (closed-lost). Test keys run the same contract on the quotes test mode created.\n\nScope: quotes:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"reason\": \"Price\",\n  \"source_system\": \"jobber\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "The organization's line-item catalog",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/catalog",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "catalog"
              ]
            },
            "description": "The organization's line-item catalog\n\nThe templates the organization quotes from (built-in ones always included, replaced by the organization's \"My defaults\" copy when it saved one) with each line item's stable `code` (matching `line_items[].code` on quotes) and default price, resolved as the app prices a new quote. Mini lights carry `sqft_per_set`. Never costs.\n\nScope: quotes:read"
          }
        },
        {
          "name": "Set your id for a quote",
          "request": {
            "method": "PUT",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/quotes/:object_id/external_refs/:system",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "quotes",
                ":object_id",
                "external_refs",
                ":system"
              ],
              "variable": [
                {
                  "key": "object_id",
                  "value": "",
                  "description": "The quote id."
                },
                {
                  "key": "system",
                  "value": "",
                  "description": "Lowercase system name, e.g. `jobber`."
                }
              ]
            },
            "description": "Set your id for a quote\n\nWrites back your CRM id. References are namespaced by integration: you can never overwrite another integration's ids.\n\nScope: quotes:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"id\": \"Z2lkOi8vSm9iYmVy\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Remove your id for a quote",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/quotes/:object_id/external_refs/:system",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "quotes",
                ":object_id",
                "external_refs",
                ":system"
              ],
              "variable": [
                {
                  "key": "object_id",
                  "value": "",
                  "description": "The quote id."
                },
                {
                  "key": "system",
                  "value": "",
                  "description": "Lowercase system name, e.g. `jobber`."
                }
              ],
              "query": [
                {
                  "key": "namespace",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "Remove your id for a quote\n\nScope: quotes:write"
          }
        }
      ]
    },
    {
      "name": "Mockups",
      "description": "Lighting mockups generated with Light AI Gen 3.0 (`light-ai-gen-3.0`), exactly as in the app: 5 credits per image from the contractor's own credits (402 `insufficient_credits` with the credits required and a top-up link when short, plus the balance for organization keys only; a failed image is refunded), results saved to the project's mockup history. Generation is asynchronous: create returns 202 with a `mgen_…` operation; poll GET /v1/mockup_generations/{id} or subscribe to mockup.completed / mockup.failed. Test keys simulate a generation (a sample image; no credits).",
      "item": [
        {
          "name": "Create a photo upload",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/projects/:project_id/photo_uploads",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "projects",
                ":project_id",
                "photo_uploads"
              ],
              "variable": [
                {
                  "key": "project_id",
                  "value": "",
                  "description": "The project id (`prj_…`)."
                }
              ]
            },
            "description": "Create a photo upload\n\nA single-use slot for a front photo larger than a JSON body allows (up to 10 MB, JPEG, PNG or WebP): PUT the bytes to `upload_url` with their Content-Type within 2 hours, then name the upload in a generation (`source.type` `photo_upload`). At most 20 open slots and 100 slots a day per organization (429 `photo_uploads_daily`). Uploaded originals are working copies: deleted once used or a few hours after an unused slot expires; the generated mockups stay in the project. Test keys get a simulated slot (no upload URL).\n\nScope: mockups:write"
          }
        },
        {
          "name": "Generate mockups",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/projects/:project_id/mockups",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "projects",
                ":project_id",
                "mockups"
              ],
              "variable": [
                {
                  "key": "project_id",
                  "value": "",
                  "description": "The project id (`prj_…`)."
                }
              ]
            },
            "description": "Generate mockups\n\nStarts a Light AI Gen 3.0 generation of 1–4 lighting mockups for the project, exactly as the app generates them: from the project's front view and its measured guide lines (default), or from a front photo (`photo_url`, fetched once, or `photo_upload`). Costs 5 credits per image from the contractor's own credits, reserved now: 402 `insufficient_credits` (with `required` and `top_up_url`, plus `balance` for an organization key only: a partner key never sees the contractor's balance) when short, and nothing is charged; a partner key also needs the grant's `mockups:write` and stays within the spend cap the contractor set (402 `partner_spend_cap_reached`). Failed images are refunded. Answers 202 with the generation; poll GET /v1/mockup_generations/{id} or subscribe to mockup.completed and mockup.failed. Idempotency-Key is required: a retry with the same key never charges again. At most 3 generations per organization run at once (429 `rate_limited`, `mockup_concurrency`). Finished images join the project as one editor mockup card (named from its light colors in the app, for example Warm White or Candy Cane, unless the contractor renames it). A card generated from a front photo (`photo_url` or `photo_upload`) is not tied to one of the project's front views: the photo is a working copy, removed a few hours after the generation finishes, so the contractor chooses a front view with a photo for that card before generating more from it in the app. Test keys simulate a finished generation with a sample image (no credits).\n\nScope: mockups:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"images\": 2,\n  \"style_preset\": \"classic_warm_white\",\n  \"ambiance\": {\n    \"snow\": true\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Retrieve a mockup generation",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/mockup_generations/:mockup_generation_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "mockup_generations",
                ":mockup_generation_id"
              ],
              "variable": [
                {
                  "key": "mockup_generation_id",
                  "value": "",
                  "description": "The generation id (`mgen_…`)."
                }
              ]
            },
            "description": "Retrieve a mockup generation\n\nThe generation with each image's status. Succeeded images carry a signed URL (WebP, valid for one hour: read it again for a fresh one) and their `mockup_id` in the project's mockup history.\n\nScope: mockups:read"
          }
        }
      ]
    },
    {
      "name": "Website forms",
      "description": "Website request forms installed on contractors' sites (Pro). Every submission is a lead with source `website_widget`, `form`, `form_answers`, `mockup_status`, `preview_looks` and `assets`; `lead.mockup_ready` fires when its optional instant preview finishes (one AI mockup per request at 5 credits from the contractor's credits, capped per form each month; the form hides the preview when credits or caps run out).",
      "item": [
        {
          "name": "List website request forms",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/forms",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "forms"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "List website request forms\n\nNewest first. Website request forms are live configuration: test keys always get an empty list.\n\nScope: forms:read"
          }
        },
        {
          "name": "Retrieve a website request form",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/forms/:form_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "forms",
                ":form_id"
              ],
              "variable": [
                {
                  "key": "form_id",
                  "value": "",
                  "description": "The form id (`form_…`)."
                }
              ]
            },
            "description": "Retrieve a website request form\n\nStatus, install snippets, allowed websites, fields, consent, questions and instant preview settings with this month's use.\n\nScope: forms:read"
          }
        },
        {
          "name": "Update a website request form",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/forms/:form_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "forms",
                ":form_id"
              ],
              "variable": [
                {
                  "key": "form_id",
                  "value": "",
                  "description": "The form id (`form_…`)."
                }
              ]
            },
            "description": "Update a website request form\n\nPause or resume, rename, edit the wording, replace the allowed websites, or change the instant preview (on/off; one image per request at 5 credits, `images_per_lead` 1 or 2 is accepted for compatibility and stored as 1; monthly credit cap 5–5000; turning previews on without a cap sets 250). `expected_updated_at` is required (409 `stale_state` when the form changed). Changing the websites or turning previews on sends the account owners a notice and appears in Developers → Activity. Pro only; test keys are refused. Needs `forms:write`, which is never part of a preset.\n\nScope: forms:write",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"expected_updated_at\": \"2026-10-14T15:02:11.120Z\",\n  \"status\": \"paused\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        }
      ]
    },
    {
      "name": "Events",
      "description": "Everything that happened, for polling (sync_asc) or debugging.",
      "item": [
        {
          "name": "List events",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/events",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "events"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "sort",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "type",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "types",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "created_after",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "grant_id",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "List events\n\nEvents of the last 30 days your scopes can read. `events:read` or one of `leads:read`, `clients:read`, `projects:read` or `quotes:read` works: the feed holds only the event types those scopes can read (lead events need `leads:read`, quote events `quotes:read`, and so on). Polling integrations should use `sort=sync_asc`: store `next_cursor` and pass it back as `cursor`; every event appears exactly once (no gaps, even for slow transactions). A partner key without Light-AI-Organization lists events of every connected organization under one cursor, each with its `grant`.\n\nScope: events:read"
          }
        },
        {
          "name": "Retrieve an event",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/events/:event_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "events",
                ":event_id"
              ],
              "variable": [
                {
                  "key": "event_id",
                  "value": "",
                  "description": "The event id (`evt_…`)."
                }
              ]
            },
            "description": "Retrieve an event\n\nThe object inside an event is rendered now (leads and clients show their current state; quote revisions never change). events:read or one of leads:read, clients:read, projects:read or quotes:read works, as for List events.\n\nScope: events:read"
          }
        }
      ]
    },
    {
      "name": "Webhooks",
      "description": "Signed (Standard Webhooks) event delivery with retries, logs and replay. Delivery is at-least-once: the same event can arrive more than once (a retry after a timeout, a replay), always with the same webhook-id, so de-duplicate on webhook-id. Order is not guaranteed: a retried event can arrive after a later one, so compare data.object.updated_at (and data.stage_change.sequence for project.stage_changed) with what you stored and skip older ones. data.object is the object as it is when the delivery is sent: upsert by its id rather than assuming an earlier event arrived first.",
      "item": [
        {
          "name": "List your webhook endpoints",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook_endpoints",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook_endpoints"
              ]
            },
            "description": "List your webhook endpoints\n\nOnly endpoints your own credential created through the API (dashboard endpoints are managed in Settings → Developers).\n\nScope: webhooks:manage"
          }
        },
        {
          "name": "Subscribe a webhook endpoint",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook_endpoints",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook_endpoints"
              ]
            },
            "description": "Subscribe a webhook endpoint\n\nREST-hook compatible (Zapier, Make, n8n). Returns the signing secret once (`secret`). Subscribing the same URL and events again returns the same endpoint with a freshly rotated secret (HTTP 200); the previous secret keeps working for 24 hours. A re-subscribe also applies the static_header (e.g. a rotated n8n credential), exclude_own_origin and description it sends; fields it omits keep their stored values. The organization's owners are notified of every endpoint created through the API. Partner keys create an endpoint for one connected organization (send `Light-AI-Organization`); a partner-wide endpoint (every connected organization, with per-organization lanes and optional grant filters) is created by the partner owner in Settings → Developers with a second factor, never with a key, so a leaked key can never open a channel to every contractor at once. While the organization has disabled one of your endpoints to a receiver (status_reason `disabled_by_organization`), creating another to that receiver answers 409 stale_state.\n\nScope: webhooks:manage",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"url\": \"https://hooks.example.com/light-ai\",\n  \"events\": [\n    \"lead.created\",\n    \"quote.approved\"\n  ],\n  \"description\": \"n8n workflow\",\n  \"static_header\": {\n    \"name\": \"X-N8N-Auth\",\n    \"value\": \"a-long-random-value\"\n  },\n  \"exclude_own_origin\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Retrieve a webhook endpoint",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook_endpoints/:endpoint_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook_endpoints",
                ":endpoint_id"
              ],
              "variable": [
                {
                  "key": "endpoint_id",
                  "value": "",
                  "description": "The endpoint id (`we_…`)."
                }
              ]
            },
            "description": "Retrieve a webhook endpoint\n\nScope: webhooks:manage"
          }
        },
        {
          "name": "Update a webhook endpoint",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook_endpoints/:endpoint_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook_endpoints",
                ":endpoint_id"
              ],
              "variable": [
                {
                  "key": "endpoint_id",
                  "value": "",
                  "description": "The endpoint id (`we_…`)."
                }
              ]
            },
            "description": "Update a webhook endpoint\n\nChange the URL, events, description, static header, loop prevention or status. Scopes never grow. An endpoint stopped by a revocation or suspension can be disabled but not re-enabled here (an owner re-affirms it in Settings → Developers). One the organization disabled (status_reason `disabled_by_organization`) can be disabled or edited but not enabled or re-pointed, and no other endpoint can be pointed at its receiver (409 stale_state). A static header never moves to a new URL: a request that changes url on an endpoint with a static header must send static_header again (or null), else 422.\n\nScope: webhooks:manage",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"events\": [\n    \"lead.created\",\n    \"lead.touched\",\n    \"quote.approved\",\n    \"quote.declined\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Unsubscribe (delete) a webhook endpoint",
          "request": {
            "method": "DELETE",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook_endpoints/:endpoint_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook_endpoints",
                ":endpoint_id"
              ],
              "variable": [
                {
                  "key": "endpoint_id",
                  "value": "",
                  "description": "The endpoint id (`we_…`)."
                }
              ]
            },
            "description": "Unsubscribe (delete) a webhook endpoint\n\nPending deliveries are dropped with it. An endpoint the organization disabled (status_reason `disabled_by_organization`) cannot be deleted here (409 stale_state): it stands for their decision until they enable or remove it in Settings → Developers.\n\nScope: webhooks:manage"
          }
        },
        {
          "name": "Rotate the signing secret",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook_endpoints/:endpoint_id/rotate_secret",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook_endpoints",
                ":endpoint_id",
                "rotate_secret"
              ],
              "variable": [
                {
                  "key": "endpoint_id",
                  "value": "",
                  "description": "The endpoint id (`we_…`)."
                }
              ]
            },
            "description": "Rotate the signing secret\n\nReturns the new secret once. For 24 hours deliveries carry signatures for both secrets.\n\nScope: webhooks:manage",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Send a test event",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook_endpoints/:endpoint_id/test",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook_endpoints",
                ":endpoint_id",
                "test"
              ],
              "variable": [
                {
                  "key": "endpoint_id",
                  "value": "",
                  "description": "The endpoint id (`we_…`)."
                }
              ]
            },
            "description": "Send a test event\n\nQueues one `ping` event to this endpoint (at most 30 test sends per hour per organization). In test mode each ping is also one of the organization's 500 test deliveries a day: past that it is refused (429 rate_limited, limit_scope `test_deliveries`, Retry-After until midnight UTC), never answered without a delivery. An endpoint that cannot receive it answers 409 stale_state.\n\nScope: webhooks:manage",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "List an endpoint's deliveries",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook_endpoints/:endpoint_id/deliveries",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook_endpoints",
                ":endpoint_id",
                "deliveries"
              ],
              "variable": [
                {
                  "key": "endpoint_id",
                  "value": "",
                  "description": "The endpoint id (`we_…`)."
                }
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "List an endpoint's deliveries\n\nDeliveries of the last 30 days with their attempts (status, latency, error class, a short response excerpt).\n\nScope: webhooks:manage"
          }
        },
        {
          "name": "Replay events to an endpoint",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook_endpoints/:endpoint_id/replay",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook_endpoints",
                ":endpoint_id",
                "replay"
              ],
              "variable": [
                {
                  "key": "endpoint_id",
                  "value": "",
                  "description": "The endpoint id (`we_…`)."
                }
              ]
            },
            "description": "Replay events to an endpoint\n\nRe-queues events of a time range (at most 30 days back, at most 5000 events). By default only events not yet delivered successfully, including events missed while the endpoint was disabled. Replays reuse the original `webhook-id`. Test-mode replays count toward the organization's 500 test deliveries a day: a replay that would pass it queues nothing and answers 429 (Retry-After until midnight UTC).\n\nScope: webhooks:manage",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"created_after\": \"2026-10-10T00:00:00Z\",\n  \"types\": [\n    \"lead.created\"\n  ],\n  \"only_failed\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Retry one delivery now",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/webhook_deliveries/:delivery_id/retry",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "webhook_deliveries",
                ":delivery_id",
                "retry"
              ],
              "variable": [
                {
                  "key": "delivery_id",
                  "value": "",
                  "description": "The delivery id (`whd_…`)."
                }
              ]
            },
            "description": "Retry one delivery now\n\nRe-queues this delivery's event to its endpoint, reusing its `webhook-id` (a logged `ping` too, to re-verify the receiver). A test-mode retry counts toward the organization's 500 test deliveries a day (429 past it).\n\nScope: webhooks:manage",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        }
      ]
    },
    {
      "name": "Inbound",
      "description": "Receivers for lead sources that cannot call the API with a key.",
      "item": [
        {
          "name": "Receive a lead (inbound source, header secret)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-Light-AI-Source-Secret",
                "value": "{{INBOUND_SOURCE_SECRET}}"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/inbound/:source_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "inbound",
                ":source_id"
              ],
              "variable": [
                {
                  "key": "source_id",
                  "value": "",
                  "description": "The inbound source id (`src_…`)."
                }
              ]
            },
            "description": "Receive a lead (inbound source, header secret)\n\nFor HighLevel workflows, Zapier, Make, n8n, Sweep&Go and form tools. Authenticate with `Authorization: Bearer lai_whin_…` or `X-Light-AI-Source-Secret`. The body is either the POST /v1/leads shape or any JSON your source's field map understands. Always receipt-only. Per-source limits: 60/min and the daily limit. Only the contact can refuse a lead (a name, and an email or a phone): a country name is normalized (`United States` → `US`), and an address or other optional part that cannot be used is left out (its raw value kept in `custom_fields.inbound_*`) instead of losing the lead.",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"contact\": {\n    \"first_name\": \"Dana\",\n    \"last_name\": \"Reyes\",\n    \"email\": \"dana@example.com\",\n    \"phone\": \"+1 (512) 555-0134\"\n  },\n  \"address\": {\n    \"line1\": \"4102 Oak Hollow Dr\",\n    \"city\": \"Austin\",\n    \"region\": \"TX\",\n    \"postal_code\": \"78731\"\n  },\n  \"service_interest\": \"christmas_lights\",\n  \"message\": \"Roofline, warm white.\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Receive a lead (inbound source, secret in the URL)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/inbound/:source_id/:token",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "inbound",
                ":source_id",
                ":token"
              ],
              "variable": [
                {
                  "key": "source_id",
                  "value": "",
                  "description": "The inbound source id (`src_…`)."
                },
                {
                  "key": "token",
                  "value": "",
                  "description": "The source's URL token (`lai_whu_…`)."
                }
              ]
            },
            "description": "Receive a lead (inbound source, secret in the URL)\n\nFor senders that cannot set headers. The URL itself is the credential: keep it private and rotate it if it leaks.",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"contact\": {\n    \"first_name\": \"Dana\",\n    \"last_name\": \"Reyes\",\n    \"email\": \"dana@example.com\",\n    \"phone\": \"+1 (512) 555-0134\"\n  },\n  \"address\": {\n    \"line1\": \"4102 Oak Hollow Dr\",\n    \"city\": \"Austin\",\n    \"region\": \"TX\",\n    \"postal_code\": \"78731\"\n  },\n  \"service_interest\": \"christmas_lights\",\n  \"message\": \"Roofline, warm white.\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Google Ads lead form webhook",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/inbound/google-ads/:source_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "inbound",
                "google-ads",
                ":source_id"
              ],
              "variable": [
                {
                  "key": "source_id",
                  "value": "",
                  "description": "The inbound source id (`src_…`)."
                }
              ]
            },
            "description": "Google Ads lead form webhook\n\nPaste this URL and the source key into the lead form's webhook settings. Answers follow Google's retry rules: 200 on success, 400 for a bad key or malformed lead (not retried), 503 when Google should retry (never 429). `is_test` leads (Google's \"Send test data\") run in test mode.",
            "auth": {
              "type": "noauth"
            },
            "body": {
              "mode": "raw",
              "raw": "{\n  \"lead_id\": \"TeSter-123-ABCDEFGHIJKLMNOPQRSTUVWXYZ\",\n  \"user_column_data\": [\n    {\n      \"column_id\": \"FIRST_NAME\",\n      \"string_value\": \"Dana\"\n    },\n    {\n      \"column_id\": \"LAST_NAME\",\n      \"string_value\": \"Reyes\"\n    },\n    {\n      \"column_id\": \"EMAIL\",\n      \"string_value\": \"dana@example.com\"\n    },\n    {\n      \"column_id\": \"PHONE_NUMBER\",\n      \"string_value\": \"+15125550134\"\n    },\n    {\n      \"column_id\": \"POSTAL_CODE\",\n      \"string_value\": \"78731\"\n    }\n  ],\n  \"google_key\": \"lai_whin_…\",\n  \"is_test\": true\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        }
      ]
    },
    {
      "name": "Partners",
      "description": "Integrators serving many contractors through consented grants.",
      "item": [
        {
          "name": "List the organizations connected to your partner account",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/grants",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "grants"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "status",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "List the organizations connected to your partner account\n\nEach grant is one contractor's consent. Send `Light-AI-Organization: org_…` with a grant's organization id to act for it."
          }
        },
        {
          "name": "Set your reference and metadata for a connected organization",
          "request": {
            "method": "PATCH",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/grants/:grant_id",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "grants",
                ":grant_id"
              ],
              "variable": [
                {
                  "key": "grant_id",
                  "value": "",
                  "description": "The grant id (`grant_…`)."
                }
              ]
            },
            "description": "Set your reference and metadata for a connected organization\n\n`external_reference` (e.g. a HighLevel locationId) is echoed in every event of that organization, for routing.",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"external_reference\": \"ghl-location-AbC123\",\n  \"metadata\": {\n    \"region\": \"TX\"\n  }\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Confirm the organization an unbound connect link reached",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/grants/:grant_id/confirm",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "grants",
                ":grant_id",
                "confirm"
              ],
              "variable": [
                {
                  "key": "grant_id",
                  "value": "",
                  "description": "The grant id (`grant_…`)."
                }
              ]
            },
            "description": "Confirm the organization an unbound connect link reached\n\nA link without a bound organization activates only after you confirm the organization name the owner approved with (shown on the pending grant). Live keys only, holding every scope the grant asks for.",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Decline a pending grant (wrong organization)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/grants/:grant_id/decline",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "grants",
                ":grant_id",
                "decline"
              ],
              "variable": [
                {
                  "key": "grant_id",
                  "value": "",
                  "description": "The grant id (`grant_…`)."
                }
              ]
            },
            "description": "Decline a pending grant (wrong organization)",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "List your connect links",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/connect_links",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "connect_links"
              ],
              "query": [
                {
                  "key": "limit",
                  "value": "",
                  "disabled": true
                },
                {
                  "key": "cursor",
                  "value": "",
                  "disabled": true
                }
              ]
            },
            "description": "List your connect links"
          }
        },
        {
          "name": "Create a connect link",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/connect_links",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "connect_links"
              ]
            },
            "description": "Create a connect link\n\nA single-use link (7 days at most) a contractor's owner opens to approve your access. The owner signs in (or signs up), sees your verified legal name, domain and every scope, and approves. Never email API keys: send connect links. The `url` is returned only here (and on an Idempotency-Key replay).",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"scopes\": [\n    \"leads:read\",\n    \"leads:write\",\n    \"clients:read\",\n    \"projects:read\",\n    \"quotes:read\",\n    \"quotes:write\",\n    \"webhooks:manage\"\n  ],\n  \"client_label\": \"Bright Nights Lighting\",\n  \"external_reference\": \"ghl-location-AbC123\",\n  \"redirect_uri\": \"https://app.acme-automations.com/light-ai/connected\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        },
        {
          "name": "Revoke an unused connect link",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/partner/connect_links/:connect_link_id/revoke",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "partner",
                "connect_links",
                ":connect_link_id",
                "revoke"
              ],
              "variable": [
                {
                  "key": "connect_link_id",
                  "value": "",
                  "description": "The link id (`cl_…`)."
                }
              ]
            },
            "description": "Revoke an unused connect link",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        }
      ]
    },
    {
      "name": "Test mode",
      "description": "Simulations available to test keys only.",
      "item": [
        {
          "name": "Simulate a quote lifecycle step for a test lead",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Light-AI-Organization",
                "value": "{{organization}}",
                "disabled": true,
                "description": "Partner keys: the connected organization."
              },
              {
                "key": "Idempotency-Key",
                "value": "{{$guid}}"
              },
              {
                "key": "Content-Type",
                "value": "application/json"
              }
            ],
            "url": {
              "raw": "{{baseUrl}}/v1/test_helpers/leads/:lead_id/:action",
              "host": [
                "{{baseUrl}}"
              ],
              "path": [
                "v1",
                "test_helpers",
                "leads",
                ":lead_id",
                ":action"
              ],
              "variable": [
                {
                  "key": "lead_id",
                  "value": "",
                  "description": "A test lead id (`lead_…`)."
                },
                {
                  "key": "action",
                  "value": "",
                  "description": "The step to simulate."
                }
              ]
            },
            "description": "Simulate a quote lifecycle step for a test lead\n\nTest keys only. `publish_quote` publishes a test quote for a lead your test key created (optionally from your own quote-website-v1 `document`); `view_quote`, `click_external_link`, `approve_quote` and `decline_quote` then emit the same events a real homeowner would cause, to your test endpoints only.",
            "body": {
              "mode": "raw",
              "raw": "{}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          }
        }
      ]
    }
  ]
}
