{
  "openapi": "3.0.0",
  "paths": {
    "/reseller/catalog": {
      "get": {
        "description": "Browse all service offers available to your reseller team. Visibility is based on provider settings (all resellers, preferred resellers, or selected resellers). Supports filtering by category, price range, ZIP code, and search terms. Results are sorted by relevance!",
        "operationId": "ResellerCatalogController_findAll",
        "parameters": [
          {
            "name": "category",
            "required": false,
            "in": "query",
            "description": "Filter by service category",
            "schema": {
              "example": "internet",
              "type": "string",
              "enum": [
                "internet",
                "electricity",
                "other"
              ]
            }
          },
          {
            "name": "minPrice",
            "required": false,
            "in": "query",
            "description": "Minimum monthly price",
            "schema": {
              "example": 0,
              "type": "number"
            }
          },
          {
            "name": "maxPrice",
            "required": false,
            "in": "query",
            "description": "Maximum monthly price",
            "schema": {
              "example": 100,
              "type": "number"
            }
          },
          {
            "name": "zipCode",
            "required": false,
            "in": "query",
            "description": "ZIP code to check availability",
            "schema": {
              "example": "94102",
              "type": "string"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "Search term (searches name, description, marketing headline)",
            "schema": {
              "example": "fiber internet",
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of available offers"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Browse available offers",
        "tags": [
          "reseller-catalog"
        ]
      }
    },
    "/reseller/catalog/{id}": {
      "get": {
        "description": "Retrieve detailed information about a specific offer in the catalog. You can only view offers that are available to your reseller team.",
        "operationId": "ResellerCatalogController_findOne",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Offer details"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Offer not found or not available to your team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Get offer details",
        "tags": [
          "reseller-catalog"
        ]
      }
    },
    "/reseller/availability": {
      "post": {
        "description": "Given a service address, returns every offer your reseller team can sell at that location. Coverage is evaluated against each offer’s availability rules — postal codes and active market areas (including state-wide and city-level coverage) — and provider visibility settings (all resellers, preferred resellers, or selected resellers). This is the same availability logic used by shareable checkout links, exposed as a dedicated address-driven endpoint. Results are returned both as a flat list and grouped by category for checkout UIs.",
        "operationId": "ResellerAvailabilityController_findAvailable",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CheckAvailabilityDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Offers available at the given address"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Find available offers for an address",
        "tags": [
          "reseller-availability"
        ]
      }
    },
    "/reseller/orders": {
      "post": {
        "description": "Create a new order for one or more service offers. Each offer will be sent to its respective provider for fulfillment. You can only order offers that are available to your reseller team.",
        "operationId": "ResellerOrdersController_create",
        "parameters": [
          {
            "name": "idempotency-key",
            "required": true,
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "Client-generated key for this checkout attempt. A repeat request with the same key (e.g. a network retry or double-click) returns the original order instead of creating a duplicate.",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOrderDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Order successfully created"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "One or more offers are not available to your team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Place a new order",
        "tags": [
          "reseller-orders"
        ]
      },
      "get": {
        "description": "Retrieve all orders placed by your reseller team. Includes order items and their fulfillment status.",
        "operationId": "ResellerOrdersController_findAll",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List of orders"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "List your orders",
        "tags": [
          "reseller-orders"
        ]
      }
    },
    "/reseller/orders/{id}": {
      "get": {
        "description": "Retrieve detailed information about a specific order, including all items and their fulfillment status.",
        "operationId": "ResellerOrdersController_findOne",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Order details"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Order not found or does not belong to your team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Get order details",
        "tags": [
          "reseller-orders"
        ]
      }
    },
    "/reseller/orders/{id}/cancel": {
      "patch": {
        "description": "Cancel a pending or submitted order. Orders can only be cancelled if they have not been accepted by providers.",
        "operationId": "ResellerOrdersController_cancel",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Order successfully cancelled"
          },
          "400": {
            "description": "Order cannot be cancelled in its current status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Order not found or does not belong to your team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Cancel an order",
        "tags": [
          "reseller-orders"
        ]
      }
    },
    "/reseller/links": {
      "post": {
        "description": "Generate a shareable link for tenants to order services at a specific address. The link can be shared via email or SMS. Tenants can use the link to browse available offers and place orders without needing to create an account.",
        "operationId": "ResellerLinksController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLinkDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Link successfully created"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Create a shareable link",
        "tags": [
          "reseller-links"
        ]
      },
      "get": {
        "description": "Retrieve all shareable links created by your reseller team. Includes view and order counts for analytics.",
        "operationId": "ResellerLinksController_findAll",
        "parameters": [],
        "responses": {
          "200": {
            "description": "List of links"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "List all shareable links",
        "tags": [
          "reseller-links"
        ]
      }
    },
    "/reseller/links/{id}": {
      "get": {
        "description": "Retrieve detailed information about a specific link, including recent orders placed via the link.",
        "operationId": "ResellerLinksController_findOne",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Link details"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Link not found or does not belong to your team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Get link details",
        "tags": [
          "reseller-links"
        ]
      },
      "patch": {
        "description": "Update link properties such as property name, move-in date, or status. Set status to \"inactive\" to disable a link without deleting it.",
        "operationId": "ResellerLinksController_update",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLinkDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Link successfully updated"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Link not found or does not belong to your team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Update a link",
        "tags": [
          "reseller-links"
        ]
      },
      "delete": {
        "description": "Permanently delete a shareable link. Orders placed via this link will be preserved.",
        "operationId": "ResellerLinksController_remove",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Link successfully deleted"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Link not found or does not belong to your team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Delete a link",
        "tags": [
          "reseller-links"
        ]
      }
    },
    "/reseller/customers": {
      "get": {
        "description": "Returns this reseller team's customers (people who have placed an order) and leads (people added manually, by API import, or by event). Filter via the kind query param.",
        "operationId": "ResellerCustomersController_findAll",
        "parameters": [
          {
            "name": "kind",
            "required": false,
            "in": "query",
            "schema": {
              "enum": [
                "lead",
                "customer"
              ],
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of customers"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "List customers and leads",
        "tags": [
          "reseller-customers"
        ]
      },
      "post": {
        "description": "Create a new lead or customer record. Resellers use this to track contacts from off-platform sources before they place an order.",
        "operationId": "ResellerCustomersController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCustomerDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Customer created"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "A record for this person already exists in your list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Add a customer or lead manually",
        "tags": [
          "reseller-customers"
        ]
      }
    },
    "/reseller/customers/{customerId}": {
      "get": {
        "operationId": "ResellerCustomersController_findOne",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Customer detail"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Customer not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Get customer detail (with this reseller's orders)",
        "tags": [
          "reseller-customers"
        ]
      },
      "patch": {
        "description": "Update reseller-private fields. To update the underlying contact info (name, email, address) the contact themselves must place a new order, since those fields are shared across all teams that know this person.",
        "operationId": "ResellerCustomersController_update",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCustomerDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Customer updated"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Customer not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Update customer notes / tags / status / kind",
        "tags": [
          "reseller-customers"
        ]
      },
      "delete": {
        "description": "Removes the link between this reseller and the customer. The shared Customer record itself is preserved so other teams' views are unaffected.",
        "operationId": "ResellerCustomersController_remove",
        "parameters": [
          {
            "name": "customerId",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Customer removed"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Customer not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Remove customer from this reseller's list",
        "tags": [
          "reseller-customers"
        ]
      }
    },
    "/reseller/webhooks": {
      "post": {
        "description": "Register an HTTPS endpoint to receive signed order-event deliveries for orders your team placed. The response includes the signing secret — it is shown only this once.",
        "operationId": "ResellerWebhooksController_create",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWebhookDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The webhook, including its signing secret"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Register a webhook",
        "tags": [
          "reseller-webhooks"
        ]
      },
      "get": {
        "description": "Secrets are masked — the full value is only ever returned at creation.",
        "operationId": "ResellerWebhooksController_findAll",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Your webhooks, newest first"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "List your registered webhooks",
        "tags": [
          "reseller-webhooks"
        ]
      }
    },
    "/reseller/webhooks/{id}": {
      "get": {
        "operationId": "ResellerWebhooksController_findOne",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The webhook, without its signing secret"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Webhook not found or does not belong to your team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Get a webhook by id",
        "tags": [
          "reseller-webhooks"
        ]
      },
      "patch": {
        "operationId": "ResellerWebhooksController_update",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWebhookDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated webhook"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Webhook not found or does not belong to your team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Update a webhook (url, subscribed events, or active state)",
        "tags": [
          "reseller-webhooks"
        ]
      },
      "delete": {
        "operationId": "ResellerWebhooksController_remove",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Webhook deleted"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Webhook not found or does not belong to your team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "Delete a webhook",
        "tags": [
          "reseller-webhooks"
        ]
      }
    },
    "/reseller/webhooks/{id}/deliveries": {
      "get": {
        "description": "The 50 most recent attempts, newest first. Every attempt is logged whether it succeeded or failed — start here when a delivery appears to be missing.",
        "operationId": "ResellerWebhooksController_listDeliveries",
        "parameters": [
          {
            "name": "id",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Recent delivery attempts, newest first"
          },
          "401": {
            "description": "Missing, malformed, or revoked `x-api-key` header.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Valid API key, but your team's role does not grant access to this endpoint.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Webhook not found or does not belong to your team",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error. Safe to retry idempotent requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "api-key": []
          }
        ],
        "summary": "List recent delivery attempts for a webhook",
        "tags": [
          "reseller-webhooks"
        ]
      }
    }
  },
  "info": {
    "title": "OfferGrid API",
    "description": "**Reseller API** - Browse service catalog and place orders on behalf of customers.\n\nAs a reseller, you can:\n- Browse available service offerings from providers\n- Filter offers by category, price, location, and search terms\n- View detailed offer information including pricing and features\n- Place orders for customers (single or multi-provider orders)\n- Track order status and fulfillment progress\n- Cancel pending orders\n- Register webhooks to receive order events as they happen",
    "version": "1.0",
    "contact": {}
  },
  "tags": [
    {
      "name": "reseller-catalog",
      "description": "Reseller: Browse available service offerings"
    },
    {
      "name": "reseller-availability",
      "description": "Reseller: Find offers available at a service address"
    },
    {
      "name": "reseller-orders",
      "description": "Reseller: Place and manage orders"
    },
    {
      "name": "reseller-customers",
      "description": "Reseller: Manage customers and leads"
    },
    {
      "name": "reseller-links",
      "description": "Reseller: Manage shareable customer links"
    },
    {
      "name": "reseller-webhooks",
      "description": "Reseller: Receive order events for the orders you placed"
    }
  ],
  "servers": [
    {
      "url": "https://api.offergrid.io",
      "description": "Production"
    }
  ],
  "components": {
    "securitySchemes": {
      "api-key": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Team API key for authentication. Your team role (provider/reseller/hybrid) determines which endpoints you can access."
      }
    },
    "schemas": {
      "CreateOfferDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Public-facing name of the offer",
            "example": "High-Speed Internet 1000 Mbps"
          },
          "internalName": {
            "type": "string",
            "description": "Internal name for tracking (not shown to customers)",
            "example": "HSI-1000-Q4-2024"
          },
          "category": {
            "type": "string",
            "description": "Service category",
            "enum": [
              "internet",
              "electricity",
              "other"
            ],
            "example": "internet"
          },
          "status": {
            "type": "string",
            "description": "Current status of the offer",
            "enum": [
              "draft",
              "active",
              "inactive",
              "archived"
            ],
            "example": "draft",
            "default": "draft"
          },
          "sku": {
            "type": "string",
            "description": "Stock Keeping Unit (SKU) - must be unique",
            "example": "INT-1000-001"
          },
          "externalId": {
            "type": "string",
            "description": "External system identifier",
            "example": "ext-12345"
          },
          "externalProductKey": {
            "type": "string",
            "description": "Identifier of this offer's product in the provider's serviceability source. When the source returns several products for an address, this selects the one whose price/plan is shown for this offer; offers sharing a market can therefore each surface their own address-level pricing. Leave unset to use the source's default (payload-level) projection.",
            "example": "FIBER-500"
          },
          "metadata": {
            "type": "object",
            "description": "Custom metadata as JSON object",
            "example": {
              "tags": [
                "fiber",
                "residential"
              ],
              "priority": 1
            }
          },
          "description": {
            "type": "string",
            "description": "Detailed description of the offer",
            "example": "Blazing fast fiber internet with unlimited data"
          },
          "internalDescription": {
            "type": "string",
            "description": "Internal notes and description",
            "example": "Q4 promotional offer for new markets"
          },
          "marketingHeadline": {
            "type": "string",
            "description": "Marketing headline",
            "example": "Get Lightning-Fast Internet Today!"
          },
          "marketingDescription": {
            "type": "string",
            "description": "Marketing description",
            "example": "Experience the future of connectivity with our fiber-optic network"
          },
          "keyFeatures": {
            "description": "Array of key features",
            "example": [
              "1000 Mbps download",
              "Unlimited data",
              "No contract"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "imageUrl": {
            "type": "string",
            "description": "URL to offer image",
            "example": "https://cdn.example.com/offers/internet-1000.jpg"
          },
          "overview": {
            "type": "string",
            "description": "Detailed overview of the offer",
            "example": "This package includes installation, router, and 24/7 support"
          },
          "brandId": {
            "type": "string",
            "description": "Id of one of your team brands (see /provider/brands) to display the offer under. Takes precedence over brandName. Send null on update to clear the brand and fall back to the provider team identity.",
            "example": "a3f1c9c2-7f42-4b6e-9a8e-2f0d5c6b1e77"
          },
          "brandName": {
            "type": "string",
            "description": "Brand display name. When set, buyer-facing surfaces show this brand's name/logo instead of the owning provider team — used to load offers under another company's identity. If your team has no brand with this name it is created; matching is case/space-insensitive within your team. Falls back to the provider team name when omitted. Ignored when brandId is set.",
            "example": "Direct Energy"
          },
          "brandImageUrl": {
            "type": "string",
            "description": "Brand logo URL. Only used to set the image when the brand is first created (or when an existing brand has no image); it never overwrites an existing brand logo.",
            "example": "https://logo.clearbit.com/directenergy.com"
          },
          "submissionUrl": {
            "type": "string",
            "description": "URL for order submission",
            "example": "https://provider.example.com/api/orders"
          },
          "submissionConfig": {
            "type": "object",
            "description": "Submission configuration including form fields",
            "example": {
              "formFields": [
                {
                  "name": "address",
                  "type": "text",
                  "required": true
                },
                {
                  "name": "phone",
                  "type": "tel",
                  "required": true
                }
              ],
              "metadata": []
            }
          },
          "electricity": {
            "type": "object",
            "description": "Structured electricity contract — the only way to set an electricity offer’s pricing, term, plan and disclosures. Folded into storage server-side. Grouped as rate / term / plan / disclosures.",
            "additionalProperties": true,
            "example": {
              "rate": {
                "type": "fixed",
                "charges": [
                  {
                    "type": "perKwh",
                    "owner": "provider",
                    "label": "Energy Charge",
                    "centsPerKwh": 12.5
                  },
                  {
                    "type": "perKwh",
                    "owner": "utility",
                    "label": "TDU Delivery",
                    "centsPerKwh": 4.2
                  }
                ]
              },
              "term": {
                "length": "months_12",
                "earlyTerminationFee": 150
              },
              "plan": {
                "renewablePercentage": 100,
                "noDeposit": true
              },
              "disclosures": {
                "puctCertNumber": "10081"
              }
            }
          },
          "internet": {
            "type": "object",
            "description": "Structured internet contract — the only way to set an internet offer’s speed, data allowance, term and disclosures. Folded into storage server-side. Grouped as speed / data / term / disclosures.",
            "additionalProperties": true,
            "example": {
              "speed": {
                "minBandwidthMbps": 100,
                "maxBandwidthMbps": 1000,
                "connectionType": "fiber"
              },
              "data": {
                "capGb": 1024
              },
              "term": {
                "length": "months_12",
                "earlyTerminationFee": 150
              },
              "disclosures": {
                "broadbandLabel": {
                  "url": "https://example.com/broadband-label.pdf",
                  "typicalDownload": 940,
                  "typicalUpload": 880,
                  "typicalLatency": 15
                },
                "networkManagementUrl": "https://example.com/network-management"
              }
            }
          },
          "pricingType": {
            "type": "string",
            "description": "Pricing type",
            "enum": [
              "fixed",
              "variable",
              "tiered",
              "custom"
            ],
            "example": "fixed"
          },
          "monthlyPrice": {
            "type": "number",
            "description": "Monthly recurring price",
            "example": 59.99,
            "minimum": 0
          },
          "marketNames": {
            "description": "Scope the offer to one or more existing markets by NAME. Each name must match an existing market on your team (create markets separately via the markets API). Mirrors the CSV bulk-upload `marketNames` column so a JSON integration and the CSV path use the same identifier. Use `marketIds` if you already have market IDs. Cannot be combined with `marketIds`.",
            "example": [
              "Texas — Oncor",
              "Texas — CenterPoint"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "marketIds": {
            "description": "Scope the offer to one or more existing markets by ID. Each id must belong to a market on your team. Prefer `marketNames` when you have the market name (matches the CSV column and is easier to author). Cannot be combined with `marketNames`.",
            "example": [
              "b1c8d1e2-..."
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "consumerEnabled": {
            "type": "boolean",
            "description": "Publish this offer to the public /shop consumer storefront. Defaults to false — nothing appears in the shop without explicit opt-in. Independent of reseller (B2B) access.",
            "example": true
          },
          "consumerMode": {
            "type": "string",
            "description": "How a consumer-enabled offer converts on the shop. `checkout`: the shopper completes the order inside Offergrid. `lead_gen`: the CTA logs a click and redirects to your own `leadGenUrl` with attribution params; Offergrid creates no order. Required (enforced at publish) when consumerEnabled is true. Send null to clear.",
            "enum": [
              "lead_gen",
              "checkout"
            ],
            "example": "lead_gen"
          },
          "leadGenUrl": {
            "type": "string",
            "description": "Partner signup URL template for `lead_gen` offers — where the shop CTA sends the shopper. Must be an https:// URL and may embed {{variable}} placeholders in query-parameter values, rendered from collected customer data at handoff. Supported variables: first_name, last_name, full_name, email, phone, street, unit, city, state, zip, esiid, start_date, action (move/switch), tdsp_duns, click_id, offer_external_id. The full template (https, allowlisted variables, placeholders only in query values) is validated when the offer is published. Send null to clear.",
            "example": "https://partner.example.com/signup?ref=offergrid&fname={{first_name}}&zip={{zip}}"
          }
        },
        "required": [
          "name"
        ],
        "title": "Create Offer Request"
      },
      "UpdateOfferDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Public-facing name of the offer",
            "example": "High-Speed Internet 1000 Mbps"
          },
          "internalName": {
            "type": "string",
            "description": "Internal name for tracking (not shown to customers)",
            "example": "HSI-1000-Q4-2024"
          },
          "category": {
            "type": "string",
            "description": "Service category",
            "enum": [
              "internet",
              "electricity",
              "other"
            ],
            "example": "internet"
          },
          "status": {
            "type": "string",
            "description": "Current status of the offer",
            "enum": [
              "draft",
              "active",
              "inactive",
              "archived"
            ],
            "example": "draft",
            "default": "draft"
          },
          "sku": {
            "type": "string",
            "description": "Stock Keeping Unit (SKU) - must be unique",
            "example": "INT-1000-001"
          },
          "externalId": {
            "type": "string",
            "description": "External system identifier",
            "example": "ext-12345"
          },
          "externalProductKey": {
            "type": "string",
            "description": "Identifier of this offer's product in the provider's serviceability source. When the source returns several products for an address, this selects the one whose price/plan is shown for this offer; offers sharing a market can therefore each surface their own address-level pricing. Leave unset to use the source's default (payload-level) projection.",
            "example": "FIBER-500"
          },
          "metadata": {
            "type": "object",
            "description": "Custom metadata as JSON object",
            "example": {
              "tags": [
                "fiber",
                "residential"
              ],
              "priority": 1
            }
          },
          "description": {
            "type": "string",
            "description": "Detailed description of the offer",
            "example": "Blazing fast fiber internet with unlimited data"
          },
          "internalDescription": {
            "type": "string",
            "description": "Internal notes and description",
            "example": "Q4 promotional offer for new markets"
          },
          "marketingHeadline": {
            "type": "string",
            "description": "Marketing headline",
            "example": "Get Lightning-Fast Internet Today!"
          },
          "marketingDescription": {
            "type": "string",
            "description": "Marketing description",
            "example": "Experience the future of connectivity with our fiber-optic network"
          },
          "keyFeatures": {
            "description": "Array of key features",
            "example": [
              "1000 Mbps download",
              "Unlimited data",
              "No contract"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "imageUrl": {
            "type": "string",
            "description": "URL to offer image",
            "example": "https://cdn.example.com/offers/internet-1000.jpg"
          },
          "overview": {
            "type": "string",
            "description": "Detailed overview of the offer",
            "example": "This package includes installation, router, and 24/7 support"
          },
          "brandId": {
            "type": "string",
            "description": "Id of one of your team brands (see /provider/brands) to display the offer under. Takes precedence over brandName. Send null on update to clear the brand and fall back to the provider team identity.",
            "example": "a3f1c9c2-7f42-4b6e-9a8e-2f0d5c6b1e77"
          },
          "brandName": {
            "type": "string",
            "description": "Brand display name. When set, buyer-facing surfaces show this brand's name/logo instead of the owning provider team — used to load offers under another company's identity. If your team has no brand with this name it is created; matching is case/space-insensitive within your team. Falls back to the provider team name when omitted. Ignored when brandId is set.",
            "example": "Direct Energy"
          },
          "brandImageUrl": {
            "type": "string",
            "description": "Brand logo URL. Only used to set the image when the brand is first created (or when an existing brand has no image); it never overwrites an existing brand logo.",
            "example": "https://logo.clearbit.com/directenergy.com"
          },
          "submissionUrl": {
            "type": "string",
            "description": "URL for order submission",
            "example": "https://provider.example.com/api/orders"
          },
          "submissionConfig": {
            "type": "object",
            "description": "Submission configuration including form fields",
            "example": {
              "formFields": [
                {
                  "name": "address",
                  "type": "text",
                  "required": true
                },
                {
                  "name": "phone",
                  "type": "tel",
                  "required": true
                }
              ],
              "metadata": []
            }
          },
          "electricity": {
            "type": "object",
            "description": "Structured electricity contract — the only way to set an electricity offer’s pricing, term, plan and disclosures. Folded into storage server-side. Grouped as rate / term / plan / disclosures.",
            "additionalProperties": true,
            "example": {
              "rate": {
                "type": "fixed",
                "charges": [
                  {
                    "type": "perKwh",
                    "owner": "provider",
                    "label": "Energy Charge",
                    "centsPerKwh": 12.5
                  },
                  {
                    "type": "perKwh",
                    "owner": "utility",
                    "label": "TDU Delivery",
                    "centsPerKwh": 4.2
                  }
                ]
              },
              "term": {
                "length": "months_12",
                "earlyTerminationFee": 150
              },
              "plan": {
                "renewablePercentage": 100,
                "noDeposit": true
              },
              "disclosures": {
                "puctCertNumber": "10081"
              }
            }
          },
          "internet": {
            "type": "object",
            "description": "Structured internet contract — the only way to set an internet offer’s speed, data allowance, term and disclosures. Folded into storage server-side. Grouped as speed / data / term / disclosures.",
            "additionalProperties": true,
            "example": {
              "speed": {
                "minBandwidthMbps": 100,
                "maxBandwidthMbps": 1000,
                "connectionType": "fiber"
              },
              "data": {
                "capGb": 1024
              },
              "term": {
                "length": "months_12",
                "earlyTerminationFee": 150
              },
              "disclosures": {
                "broadbandLabel": {
                  "url": "https://example.com/broadband-label.pdf",
                  "typicalDownload": 940,
                  "typicalUpload": 880,
                  "typicalLatency": 15
                },
                "networkManagementUrl": "https://example.com/network-management"
              }
            }
          },
          "pricingType": {
            "type": "string",
            "description": "Pricing type",
            "enum": [
              "fixed",
              "variable",
              "tiered",
              "custom"
            ],
            "example": "fixed"
          },
          "monthlyPrice": {
            "type": "number",
            "description": "Monthly recurring price",
            "example": 59.99,
            "minimum": 0
          },
          "marketNames": {
            "description": "Scope the offer to one or more existing markets by NAME. Each name must match an existing market on your team (create markets separately via the markets API). Mirrors the CSV bulk-upload `marketNames` column so a JSON integration and the CSV path use the same identifier. Use `marketIds` if you already have market IDs. Cannot be combined with `marketIds`.",
            "example": [
              "Texas — Oncor",
              "Texas — CenterPoint"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "marketIds": {
            "description": "Scope the offer to one or more existing markets by ID. Each id must belong to a market on your team. Prefer `marketNames` when you have the market name (matches the CSV column and is easier to author). Cannot be combined with `marketNames`.",
            "example": [
              "b1c8d1e2-..."
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "consumerEnabled": {
            "type": "boolean",
            "description": "Publish this offer to the public /shop consumer storefront. Defaults to false — nothing appears in the shop without explicit opt-in. Independent of reseller (B2B) access.",
            "example": true
          },
          "consumerMode": {
            "type": "string",
            "description": "How a consumer-enabled offer converts on the shop. `checkout`: the shopper completes the order inside Offergrid. `lead_gen`: the CTA logs a click and redirects to your own `leadGenUrl` with attribution params; Offergrid creates no order. Required (enforced at publish) when consumerEnabled is true. Send null to clear.",
            "enum": [
              "lead_gen",
              "checkout"
            ],
            "example": "lead_gen"
          },
          "leadGenUrl": {
            "type": "string",
            "description": "Partner signup URL template for `lead_gen` offers — where the shop CTA sends the shopper. Must be an https:// URL and may embed {{variable}} placeholders in query-parameter values, rendered from collected customer data at handoff. Supported variables: first_name, last_name, full_name, email, phone, street, unit, city, state, zip, esiid, start_date, action (move/switch), tdsp_duns, click_id, offer_external_id. The full template (https, allowlisted variables, placeholders only in query values) is validated when the offer is published. Send null to clear.",
            "example": "https://partner.example.com/signup?ref=offergrid&fname={{first_name}}&zip={{zip}}"
          }
        },
        "title": "Update Offer Request"
      },
      "BulkUploadResultDto": {
        "type": "object",
        "properties": {
          "totalRows": {
            "type": "number",
            "description": "Total rows processed"
          },
          "successCount": {
            "type": "number",
            "description": "Number of successfully created offers"
          },
          "errorCount": {
            "type": "number",
            "description": "Number of failed offers"
          },
          "createdOfferIds": {
            "description": "Created offer IDs",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "errors": {
            "description": "Detailed errors for failed rows",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "warnings": {
            "description": "Warnings for all rows",
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "totalRows",
          "successCount",
          "errorCount",
          "createdOfferIds",
          "errors"
        ],
        "title": "Bulk Upload Result"
      },
      "BulkUpdateResultDto": {
        "type": "object",
        "properties": {
          "totalRows": {
            "type": "number",
            "description": "Total rows processed"
          },
          "successCount": {
            "type": "number",
            "description": "Number of successfully updated offers"
          },
          "errorCount": {
            "type": "number",
            "description": "Number of failed rows"
          },
          "updatedOfferIds": {
            "description": "Updated offer IDs",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "errors": {
            "description": "Detailed errors for failed rows",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "warnings": {
            "description": "Warnings for all rows",
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "totalRows",
          "successCount",
          "errorCount",
          "updatedOfferIds",
          "errors"
        ],
        "title": "Bulk Update Result"
      },
      "UpdateItemStatusDto": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "submitted_to_provider",
              "accepted",
              "rejected",
              "scheduled",
              "in_progress",
              "completed",
              "active",
              "cancelled",
              "failed"
            ],
            "description": "New status for the order item",
            "example": "accepted"
          },
          "providerNotes": {
            "type": "string",
            "description": "Notes from provider about this status update",
            "example": "Installation scheduled for next Tuesday"
          },
          "scheduledFor": {
            "type": "string",
            "description": "Scheduled date/time for installation or activation (ISO 8601)",
            "example": "2025-01-15T10:00:00Z"
          },
          "metadata": {
            "type": "object",
            "description": "Additional metadata for this status update",
            "example": {
              "trackingNumber": "ABC123",
              "estimatedCompletion": "2025-01-20"
            }
          }
        },
        "required": [
          "status"
        ],
        "title": "Update Item Status Request"
      },
      "CreateMarketDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Provider-facing market name. Unique per provider team.",
            "example": "Austin Metro"
          },
          "description": {
            "type": "string",
            "description": "Optional description of the market.",
            "example": "Fiber footprint across Travis and Williamson counties."
          },
          "status": {
            "type": "string",
            "description": "Lifecycle status.",
            "enum": [
              "draft",
              "active",
              "paused",
              "archived"
            ],
            "default": "draft"
          },
          "tags": {
            "description": "Free-form tags for grouping markets.",
            "example": [
              "fiber",
              "priority"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "name"
        ],
        "title": "Create Market"
      },
      "UpdateMarketDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Provider-facing market name. Unique per provider team.",
            "example": "Austin Metro"
          },
          "description": {
            "type": "string",
            "description": "Optional description of the market.",
            "example": "Fiber footprint across Travis and Williamson counties."
          },
          "status": {
            "type": "string",
            "description": "Lifecycle status.",
            "enum": [
              "draft",
              "active",
              "paused",
              "archived"
            ],
            "default": "draft"
          },
          "tags": {
            "description": "Free-form tags for grouping markets.",
            "example": [
              "fiber",
              "priority"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "title": "Update Market"
      },
      "UpsertMarketAreaDto": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "postal",
              "admin",
              "polygon",
              "h3",
              "utility_territory",
              "serviceability"
            ]
          },
          "operation": {
            "type": "string",
            "enum": [
              "include",
              "exclude"
            ],
            "default": "include"
          },
          "label": {
            "type": "string",
            "description": "Optional display label (e.g. \"Travis County\", \"78704 cluster\")."
          },
          "postalCodes": {
            "example": [
              "78701",
              "78702"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "postalCountry": {
            "type": "string",
            "example": "US"
          },
          "adminLevel": {
            "type": "string",
            "enum": [
              "state",
              "county",
              "city",
              "census_place"
            ]
          },
          "adminCountry": {
            "type": "string",
            "example": "US"
          },
          "adminState": {
            "type": "string",
            "example": "TX"
          },
          "adminCounty": {
            "type": "string",
            "example": "Travis"
          },
          "adminCity": {
            "type": "string",
            "example": "Austin"
          },
          "adminGeoid": {
            "type": "string",
            "description": "Census GEOID for stable matching."
          },
          "geometry": {
            "type": "object",
            "description": "GeoJSON Polygon or MultiPolygon."
          },
          "h3Cells": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "h3Resolution": {
            "type": "number",
            "example": 8
          },
          "utilityCodes": {
            "description": "TDSP/TDU DUNS codes, e.g. Oncor \"1039940674000\".",
            "example": [
              "1039940674000"
            ],
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "utilityCountry": {
            "type": "string",
            "example": "US"
          },
          "sourceType": {
            "type": "string",
            "enum": [
              "fabric_upload",
              "external_api"
            ]
          },
          "sourceRef": {
            "type": "string",
            "description": "The IntegrationSource key this area resolves through. Required for serviceability areas, where it must name an active serviceability source owned by your team."
          },
          "gating": {
            "type": "boolean",
            "description": "Serviceability areas only. true = the market covers an address only when this source answers on-net; false (default) = the source enriches offer detail but never hides the offer. An unanswerable lookup never gates.",
            "default": false
          }
        },
        "required": [
          "type"
        ],
        "title": "Upsert Market Area"
      },
      "CreateWebhookDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "HTTPS endpoint that will receive signed order-event deliveries",
            "example": "https://your-system.example.com/offergrid-callback"
          },
          "events": {
            "type": "array",
            "description": "Event types this webhook subscribes to",
            "example": [
              "order.item.created",
              "order.item.status_changed"
            ],
            "items": {
              "type": "string",
              "enum": [
                "order.created",
                "order.item.created",
                "order.item.status_changed",
                "order.cancelled"
              ]
            }
          }
        },
        "required": [
          "url",
          "events"
        ],
        "title": "Create Webhook"
      },
      "UpdateWebhookDto": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "example": "https://your-system.example.com/offergrid-callback"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "order.created",
                "order.item.created",
                "order.item.status_changed",
                "order.cancelled"
              ]
            }
          },
          "isActive": {
            "type": "boolean",
            "description": "Pause/resume deliveries without deleting the webhook"
          }
        },
        "title": "Update Webhook"
      },
      "CreateBrandDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Display name buyers see on offers using this brand. Matched case-insensitively within your team — creating a name your team already uses returns a conflict.",
            "example": "Direct Energy"
          },
          "imageUrl": {
            "type": "string",
            "description": "Logo image URL shown on buyer-facing offer cards. Must serve an actual image; cards fall back to name initials when it fails to load.",
            "example": "https://cdn.example.com/logos/direct-energy.png"
          }
        },
        "required": [
          "name"
        ],
        "title": "Create Brand"
      },
      "UpdateBrandDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Display name buyers see on offers using this brand. Matched case-insensitively within your team — creating a name your team already uses returns a conflict.",
            "example": "Direct Energy"
          },
          "imageUrl": {
            "type": "string",
            "description": "Logo image URL shown on buyer-facing offer cards. Send an empty string to clear the logo (cards fall back to name initials).",
            "example": "https://cdn.example.com/logos/direct-energy.png"
          }
        },
        "title": "Update Brand"
      },
      "CreateTeamApiKeyDto": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Descriptive name for the API key"
          }
        },
        "required": [
          "name"
        ],
        "title": "Create Team Api Key"
      },
      "InviteTeamMemberDto": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "description": "Email address of the person to invite"
          }
        },
        "required": [
          "email"
        ],
        "title": "Invite Team Member"
      },
      "AddressDto": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string",
            "example": "123 Main Street"
          },
          "unit": {
            "type": "string",
            "example": "Unit 205"
          },
          "city": {
            "type": "string",
            "example": "Austin"
          },
          "state": {
            "type": "string",
            "example": "TX"
          },
          "zipCode": {
            "type": "string",
            "example": "78701"
          },
          "country": {
            "type": "string",
            "example": "US",
            "default": "US"
          }
        },
        "required": [
          "street",
          "city",
          "state",
          "zipCode",
          "country"
        ],
        "title": "Address"
      },
      "CheckAvailabilityDto": {
        "type": "object",
        "properties": {
          "address": {
            "description": "Service address to check availability for",
            "allOf": [
              {
                "$ref": "#/components/schemas/AddressDto"
              }
            ]
          },
          "category": {
            "type": "string",
            "enum": [
              "internet",
              "electricity",
              "other"
            ],
            "description": "Only return offers in this service category",
            "example": "internet"
          },
          "minPrice": {
            "type": "number",
            "description": "Minimum monthly price",
            "example": 0
          },
          "maxPrice": {
            "type": "number",
            "description": "Maximum monthly price",
            "example": 100
          }
        },
        "required": [
          "address"
        ],
        "title": "Find Available Offers Request"
      },
      "OrderItemDto": {
        "type": "object",
        "properties": {
          "offerId": {
            "type": "string",
            "description": "ID of the offer to order",
            "example": "123e4567-e89b-12d3-a456-426614174000"
          },
          "metadata": {
            "type": "object",
            "description": "Per-item metadata stored on the resulting OrderItem. For electricity offers, carry enrollment details here so the provider can fulfill the enrollment.",
            "example": {
              "enrollment": {
                "enrollmentType": "switch",
                "esid": "10443720000000000",
                "requestedStartDate": "2026-07-15"
              }
            }
          }
        },
        "required": [
          "offerId"
        ],
        "title": "Order Item"
      },
      "ServiceAddressDto": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string",
            "example": "123 Main St"
          },
          "city": {
            "type": "string",
            "example": "San Francisco"
          },
          "state": {
            "type": "string",
            "example": "CA"
          },
          "zipCode": {
            "type": "string",
            "example": "94102"
          },
          "country": {
            "type": "string",
            "example": "US"
          }
        },
        "required": [
          "street",
          "city",
          "state",
          "zipCode",
          "country"
        ],
        "title": "Service Address"
      },
      "CustomerInfoDto": {
        "type": "object",
        "properties": {
          "firstName": {
            "type": "string",
            "example": "John"
          },
          "lastName": {
            "type": "string",
            "example": "Doe"
          },
          "fullName": {
            "type": "string",
            "example": "John Doe",
            "description": "Legacy single-field name — prefer firstName + lastName. Required only when both are absent; split on the last space when used."
          },
          "email": {
            "type": "string",
            "example": "john@example.com"
          },
          "phone": {
            "type": "string",
            "example": "+1-555-123-4567"
          }
        },
        "required": [
          "email",
          "phone"
        ],
        "title": "Customer Information"
      },
      "CreateOrderDto": {
        "type": "object",
        "properties": {
          "items": {
            "description": "Array of items to order (offers)",
            "example": [
              {
                "offerId": "123e4567-e89b-12d3-a456-426614174000"
              }
            ],
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderItemDto"
            }
          },
          "serviceAddress": {
            "description": "Service address for installation",
            "allOf": [
              {
                "$ref": "#/components/schemas/ServiceAddressDto"
              }
            ]
          },
          "customerInfo": {
            "description": "Customer information",
            "allOf": [
              {
                "$ref": "#/components/schemas/CustomerInfoDto"
              }
            ]
          },
          "notes": {
            "type": "string",
            "description": "Additional notes for the order",
            "example": "Customer prefers morning installations"
          },
          "metadata": {
            "type": "object",
            "description": "Additional metadata for the order",
            "example": {
              "referralSource": "property-listing",
              "unitNumber": "4B"
            }
          }
        },
        "required": [
          "items",
          "serviceAddress",
          "customerInfo"
        ],
        "title": "Create Order Request"
      },
      "CreateLinkDto": {
        "type": "object",
        "properties": {
          "address": {
            "description": "Service address for the tenant",
            "allOf": [
              {
                "$ref": "#/components/schemas/AddressDto"
              }
            ]
          },
          "propertyName": {
            "type": "string",
            "description": "Property name or description",
            "example": "Sunset Apartments Unit 205"
          },
          "moveInDate": {
            "type": "string",
            "description": "Expected move-in date (ISO 8601)",
            "example": "2025-02-01"
          }
        },
        "required": [
          "address"
        ],
        "title": "Create Link Request"
      },
      "UpdateLinkDto": {
        "type": "object",
        "properties": {
          "propertyName": {
            "type": "string",
            "description": "Property name or description",
            "example": "Sunset Apartments Unit 205"
          },
          "moveInDate": {
            "type": "string",
            "description": "Expected move-in date (ISO 8601)",
            "example": "2025-02-01"
          },
          "status": {
            "type": "string",
            "description": "Link status",
            "enum": [
              "active",
              "inactive"
            ],
            "example": "active"
          }
        },
        "title": "Update Link Request"
      },
      "CreateCustomerDto": {
        "type": "object",
        "properties": {
          "firstName": {
            "type": "string",
            "example": "Jane"
          },
          "lastName": {
            "type": "string",
            "example": "Doe"
          },
          "fullName": {
            "type": "string",
            "example": "Jane Doe",
            "description": "Legacy single-field name — prefer firstName + lastName. Required only when both are absent; split on the last space when used."
          },
          "email": {
            "type": "string",
            "example": "jane@example.com"
          },
          "phone": {
            "type": "string",
            "example": "+1-555-123-4567"
          },
          "addressLine1": {
            "type": "string",
            "example": "123 Main St"
          },
          "addressLine2": {
            "type": "string",
            "example": "Apt 4B"
          },
          "city": {
            "type": "string",
            "example": "San Francisco"
          },
          "state": {
            "type": "string",
            "example": "CA"
          },
          "postalCode": {
            "type": "string",
            "example": "94102"
          },
          "country": {
            "type": "string",
            "example": "US"
          },
          "kind": {
            "type": "string",
            "description": "Whether to track as a lead (pre-order) or as a customer.",
            "enum": [
              "lead",
              "customer"
            ],
            "default": "lead"
          },
          "source": {
            "type": "string",
            "description": "Where this contact came from.",
            "enum": [
              "order",
              "link",
              "api_import",
              "manual",
              "event",
              "shop",
              "reseller"
            ],
            "default": "manual"
          },
          "notes": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "customFields": {
            "type": "object",
            "description": "Open-ended attributes (source URL, external IDs, etc.)",
            "example": {
              "sourceUrl": "https://example.com/listing/42"
            }
          }
        },
        "title": "Create Customer"
      },
      "UpdateCustomerDto": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "lead",
              "customer"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "churned",
              "unsubscribed"
            ]
          },
          "notes": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "title": "Update Customer"
      },
      "SelectedOfferDto": {
        "type": "object",
        "properties": {
          "offerId": {
            "type": "string",
            "description": "Offer ID to order",
            "example": "uuid-of-offer"
          }
        },
        "required": [
          "offerId"
        ],
        "title": "Selected Offer"
      },
      "CreatePublicOrderDto": {
        "type": "object",
        "properties": {
          "customerInfo": {
            "description": "Customer contact information",
            "allOf": [
              {
                "$ref": "#/components/schemas/CustomerInfoDto"
              }
            ]
          },
          "items": {
            "description": "List of offers to order (one per category)",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SelectedOfferDto"
            }
          },
          "moveInDate": {
            "type": "string",
            "description": "Move-in date (ISO 8601)",
            "example": "2025-02-01"
          },
          "notes": {
            "type": "string",
            "description": "Additional notes from the customer",
            "example": "Please contact me in the morning"
          },
          "idempotencyKey": {
            "type": "string",
            "description": "Client-generated key for this checkout attempt. A repeat submission with the same key (e.g. a network retry or double-click on Submit) returns the original order instead of creating a duplicate.",
            "example": "a1b2c3d4-checkout-attempt"
          }
        },
        "required": [
          "customerInfo",
          "items"
        ],
        "title": "Create Public Order Request"
      },
      "ShopServiceabilityDto": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string",
            "example": "123 Main St"
          },
          "unit": {
            "type": "string",
            "example": "Unit 4B"
          },
          "zip": {
            "type": "string",
            "example": "78701"
          },
          "city": {
            "type": "string",
            "example": "Austin"
          },
          "state": {
            "type": "string",
            "example": "TX"
          },
          "country": {
            "type": "string",
            "example": "US",
            "default": "US"
          },
          "category": {
            "type": "string",
            "enum": [
              "internet",
              "electricity",
              "other"
            ],
            "example": "internet"
          },
          "offerIds": {
            "description": "Restrict the check to these offer ids (the cards on screen).",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "street",
          "zip"
        ],
        "title": "Shop Serviceability"
      },
      "ShopOrderItemDto": {
        "type": "object",
        "properties": {
          "offerId": {
            "type": "string",
            "description": "ID of the consumer-enabled offer to order"
          },
          "metadata": {
            "type": "object",
            "description": "Per-item metadata stored on the resulting OrderItem — for electricity offers, carry enrollment details here (mirrors the reseller checkout wizard).",
            "example": {
              "enrollment": {
                "enrollmentType": "switch",
                "esid": "10443720000000000",
                "requestedStartDate": "2026-07-15"
              }
            }
          }
        },
        "required": [
          "offerId"
        ],
        "title": "Shop Order Item"
      },
      "ShopServiceAddressDto": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string",
            "example": "123 Main St"
          },
          "unit": {
            "type": "string",
            "example": "Unit 4B"
          },
          "city": {
            "type": "string",
            "example": "Austin"
          },
          "state": {
            "type": "string",
            "example": "TX"
          },
          "zipCode": {
            "type": "string",
            "example": "78701"
          },
          "country": {
            "type": "string",
            "example": "US",
            "default": "US"
          }
        },
        "required": [
          "street",
          "city",
          "state",
          "zipCode"
        ],
        "title": "Shop Service Address"
      },
      "ShopCustomerInfoDto": {
        "type": "object",
        "properties": {
          "firstName": {
            "type": "string",
            "example": "Jane"
          },
          "lastName": {
            "type": "string",
            "example": "Doe"
          },
          "fullName": {
            "type": "string",
            "example": "Jane Doe",
            "description": "Legacy single-field name — prefer firstName + lastName. Required only when both are absent; split on the last space when used."
          },
          "email": {
            "type": "string",
            "example": "jane@example.com"
          },
          "phone": {
            "type": "string",
            "example": "555-123-4567"
          }
        },
        "required": [
          "email",
          "phone"
        ],
        "title": "Shop Customer Info"
      },
      "CreateShopOrderDto": {
        "type": "object",
        "properties": {
          "items": {
            "description": "Offers to order — checkout-mode offers only, one per category",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ShopOrderItemDto"
            }
          },
          "serviceAddress": {
            "description": "Service address for installation",
            "allOf": [
              {
                "$ref": "#/components/schemas/ShopServiceAddressDto"
              }
            ]
          },
          "customerInfo": {
            "description": "Shopper contact information",
            "allOf": [
              {
                "$ref": "#/components/schemas/ShopCustomerInfoDto"
              }
            ]
          },
          "notes": {
            "type": "string",
            "description": "Additional notes from the shopper"
          },
          "idempotencyKey": {
            "type": "string",
            "description": "Client-generated key for this checkout attempt. A repeat submission with the same key (network retry, double-click on Submit) returns the original order instead of creating a duplicate.",
            "example": "a1b2c3d4-checkout-attempt"
          },
          "sessionId": {
            "type": "string",
            "description": "Anonymous client-generated session id, so the checkout-mode click this order completes can be tied to the same funnel as its lead_gen counterpart.",
            "example": "a1b2c3d4-shopper-session"
          }
        },
        "required": [
          "items",
          "serviceAddress",
          "customerInfo"
        ],
        "title": "Create Shop Order"
      },
      "ShopClickContactDto": {
        "type": "object",
        "properties": {
          "firstName": {
            "type": "string",
            "example": "Jane"
          },
          "lastName": {
            "type": "string",
            "example": "Doe"
          },
          "fullName": {
            "type": "string",
            "example": "Jane Doe",
            "description": "Legacy single-field name — prefer firstName + lastName. Required only when both are absent; split on the last space when used."
          },
          "email": {
            "type": "string",
            "example": "jane@example.com"
          },
          "phone": {
            "type": "string",
            "example": "555-123-4567"
          }
        },
        "required": [
          "email"
        ],
        "title": "Shop Click Contact"
      },
      "ShopClickServiceAddressDto": {
        "type": "object",
        "properties": {
          "street": {
            "type": "string",
            "example": "123 Main Street"
          },
          "unit": {
            "type": "string",
            "example": "Apt 4B"
          },
          "city": {
            "type": "string",
            "example": "Austin"
          },
          "state": {
            "type": "string",
            "example": "TX"
          },
          "zipCode": {
            "type": "string",
            "example": "78701"
          }
        },
        "required": [
          "street"
        ],
        "title": "Shop Click Service Address"
      },
      "ShopClickEnrollmentDto": {
        "type": "object",
        "properties": {
          "enrollmentType": {
            "type": "string",
            "example": "move_in",
            "description": "switch (existing meter stays on) or move_in (new occupancy)"
          },
          "esid": {
            "type": "string",
            "example": "10443720005941666"
          },
          "requestedStartDate": {
            "type": "string",
            "example": "2026-09-01"
          }
        },
        "title": "Shop Click Enrollment"
      },
      "CreateShopClickDto": {
        "type": "object",
        "properties": {
          "offerId": {
            "type": "string",
            "description": "The offer this click is for"
          },
          "zip": {
            "type": "string",
            "example": "78701"
          },
          "city": {
            "type": "string",
            "example": "Austin"
          },
          "state": {
            "type": "string",
            "example": "TX"
          },
          "sessionId": {
            "type": "string",
            "description": "Anonymous client-generated UUID grouping clicks within one shopper session",
            "example": "a1b2c3d4-shopper-session"
          },
          "referrer": {
            "type": "string",
            "example": "https://www.google.com/"
          },
          "utm": {
            "type": "object",
            "example": {
              "utm_source": "google",
              "utm_campaign": "internet-austin"
            }
          },
          "contact": {
            "description": "Optional contact capture before a lead_gen redirect — always skippable. When present, creates a provider lead (Customer + TeamCustomer).",
            "allOf": [
              {
                "$ref": "#/components/schemas/ShopClickContactDto"
              }
            ]
          },
          "serviceAddress": {
            "description": "Full service address, when the handoff was reached through the checkout wizard. Its city/state/zipCode fill in for any top-level zip/city/state left unset.",
            "allOf": [
              {
                "$ref": "#/components/schemas/ShopClickServiceAddressDto"
              }
            ]
          },
          "enrollment": {
            "description": "Optional electricity enrollment details collected before a lead_gen handoff — used to fill the offer's URL template (ESIID, start date, move vs switch) so the partner prefills its signup flow.",
            "allOf": [
              {
                "$ref": "#/components/schemas/ShopClickEnrollmentDto"
              }
            ]
          }
        },
        "required": [
          "offerId",
          "sessionId"
        ],
        "title": "Create Shop Click"
      },
      "ErrorResponse": {
        "type": "object",
        "title": "Error",
        "description": "Standard error envelope returned by every 4xx and 5xx response.",
        "required": [
          "statusCode",
          "message"
        ],
        "properties": {
          "statusCode": {
            "type": "integer",
            "description": "HTTP status code, repeated in the body.",
            "example": 404
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation of what went wrong.",
            "example": "Offer not found"
          },
          "error": {
            "type": "string",
            "description": "Short, stable name for the status code.",
            "example": "Not Found"
          }
        }
      },
      "ValidationErrorResponse": {
        "type": "object",
        "title": "Validation Error",
        "description": "Returned when request-body validation fails. `message` is an array with one entry per failed constraint.",
        "required": [
          "statusCode",
          "message"
        ],
        "properties": {
          "statusCode": {
            "type": "integer",
            "example": 400
          },
          "message": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "One human-readable message per failed constraint.",
            "example": [
              "name should not be empty",
              "category must be one of the following values: internet, electricity"
            ]
          },
          "error": {
            "type": "string",
            "example": "Bad Request"
          }
        }
      }
    }
  }
}