{
  "openapi": "3.1.0",
  "info": {
    "title": "Pilotspan Catalog API",
    "version": "1.0.0",
    "summary": "Public, keyless catalog of Pilotspan company facts and demo-lead intake.",
    "description": "Pilotspan is a home health management platform and healthcare CRM with HIPAA-aligned electronic health records, scheduling, billing, payroll, communications, and workforce tools for home health agencies. This public API is read-mostly, requires no authentication, and never exposes agency PHI. Breaking changes require a new /api/vN path. Deprecated operations receive Deprecation and Sunset headers at least 90 days before removal.",
    "termsOfService": "https://pilotspan.com/privacy",
    "contact": {
      "name": "Pilotspan developer support",
      "email": "help@pilotspan.com",
      "url": "https://pilotspan.com/developers"
    },
    "license": {
      "name": "Pilotspan public catalog terms",
      "url": "https://pilotspan.com/privacy"
    }
  },
  "servers": [
    {
      "url": "https://pilotspan.com",
      "description": "Production sandbox"
    }
  ],
  "tags": [
    {
      "name": "Catalog",
      "description": "Reviewed public marketing facts."
    },
    {
      "name": "Leads",
      "description": "Demo and contact intake."
    }
  ],
  "paths": {
    "/api/v1/health": {
      "get": {
        "operationId": "getHealth",
        "tags": [
          "Catalog"
        ],
        "summary": "Service health",
        "description": "Returns liveness, the public catalog version, and a UTC clock so agents can confirm the sandbox is reachable before other calls.",
        "security": [],
        "responses": {
          "200": {
            "description": "Catalog is reachable.",
            "headers": {
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF RateLimit policy."
              },
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "Remaining quota and reset."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Rate limit exceeded",
                  "status": 429,
                  "detail": "Rate limit exceeded",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/company": {
      "get": {
        "operationId": "getCompany",
        "tags": [
          "Catalog"
        ],
        "summary": "Organization profile",
        "description": "Returns the public Pilotspan organization, office address, phone, email, and social profile URLs used for citations.",
        "security": [],
        "responses": {
          "200": {
            "description": "Organization profile",
            "headers": {
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF RateLimit policy."
              },
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "Remaining quota and reset."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Company"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Rate limit exceeded",
                  "status": 429,
                  "detail": "Rate limit exceeded",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/features": {
      "get": {
        "operationId": "listFeatures",
        "tags": [
          "Catalog"
        ],
        "summary": "List product features",
        "description": "Returns the reviewed public feature catalog. Results are a complete collection; no pagination is required because the list is bounded.",
        "security": [],
        "responses": {
          "200": {
            "description": "Feature collection",
            "headers": {
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF RateLimit policy."
              },
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "Remaining quota and reset."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeatureList"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Rate limit exceeded",
                  "status": 429,
                  "detail": "Rate limit exceeded",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/services": {
      "get": {
        "operationId": "listServices",
        "tags": [
          "Catalog"
        ],
        "summary": "List agency services",
        "description": "Returns consulting, support, management, and marketing services described on the public website.",
        "security": [],
        "responses": {
          "200": {
            "description": "Service collection",
            "headers": {
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF RateLimit policy."
              },
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "Remaining quota and reset."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceList"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Rate limit exceeded",
                  "status": 429,
                  "detail": "Rate limit exceeded",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/faqs": {
      "get": {
        "operationId": "listFaqs",
        "tags": [
          "Catalog"
        ],
        "summary": "List public FAQs",
        "description": "Returns frequently asked questions that agents may cite when explaining Pilotspan to a prospective agency.",
        "security": [],
        "responses": {
          "200": {
            "description": "FAQ collection",
            "headers": {
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF RateLimit policy."
              },
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "Remaining quota and reset."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FaqList"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Rate limit exceeded",
                  "status": 429,
                  "detail": "Rate limit exceeded",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pages": {
      "get": {
        "operationId": "listPages",
        "tags": [
          "Catalog"
        ],
        "summary": "List public pages",
        "description": "Cursor-paginated index of public marketing pages. Pass the next_cursor from one response as cursor on the next request.",
        "security": [],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Page size from 1 to 50. Default 20.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Opaque cursor from a previous next_cursor value.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page index",
            "headers": {
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF RateLimit policy."
              },
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "Remaining quota and reset."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PageList"
                }
              }
            }
          },
          "400": {
            "description": "Invalid pagination",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Invalid pagination",
                  "status": 400,
                  "detail": "Invalid pagination",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Rate limit exceeded",
                  "status": 429,
                  "detail": "Rate limit exceeded",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/pages/{slug}": {
      "get": {
        "operationId": "getPage",
        "tags": [
          "Catalog"
        ],
        "summary": "Get one public page",
        "description": "Returns the title, canonical URL, and summary for one public marketing page.",
        "security": [],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "description": "Page slug such as about, contact, or features.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Page summary",
            "headers": {
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF RateLimit policy."
              },
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "Remaining quota and reset."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Page"
                }
              }
            }
          },
          "404": {
            "description": "Page not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Page not found",
                  "status": 404,
                  "detail": "Page not found",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Rate limit exceeded",
                  "status": 429,
                  "detail": "Rate limit exceeded",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/leads": {
      "post": {
        "operationId": "createLead",
        "tags": [
          "Leads"
        ],
        "summary": "Submit a demo or contact lead",
        "description": "Creates a public marketing lead. Retry safely by sending the same Idempotency-Key. Do not include protected health information. Large or long-running prep work is exposed as a 202 job.",
        "security": [],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Client-chosen key that makes retries return the original lead instead of creating a duplicate.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 128
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeadRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Lead accepted immediately",
            "headers": {
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF RateLimit policy."
              },
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "Remaining quota and reset."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Lead"
                }
              }
            }
          },
          "202": {
            "description": "Lead accepted for asynchronous prep",
            "headers": {
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF RateLimit policy."
              },
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "Remaining quota and reset."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              },
              "Location": {
                "schema": {
                  "type": "string",
                  "format": "uri"
                },
                "description": "Job status URL"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "400": {
            "description": "Invalid lead",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Invalid lead",
                  "status": 400,
                  "detail": "Invalid lead",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Rate limit exceeded",
                  "status": 429,
                  "detail": "Rate limit exceeded",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/jobs/{id}": {
      "get": {
        "operationId": "getJob",
        "tags": [
          "Leads"
        ],
        "summary": "Poll an asynchronous job",
        "description": "Returns status for a 202 lead-prep job. Poll this URL from the Location header until status is succeeded or failed.",
        "security": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Job identifier from a 202 response.",
            "schema": {
              "type": "string",
              "minLength": 8,
              "maxLength": 64
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Job status",
            "headers": {
              "RateLimit-Policy": {
                "schema": {
                  "type": "string"
                },
                "description": "IETF RateLimit policy."
              },
              "RateLimit": {
                "schema": {
                  "type": "string"
                },
                "description": "Remaining quota and reset."
              },
              "RateLimit-Limit": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Remaining": {
                "schema": {
                  "type": "integer"
                }
              },
              "RateLimit-Reset": {
                "schema": {
                  "type": "integer"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "404": {
            "description": "Job not found",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Job not found",
                  "status": 404,
                  "detail": "Job not found",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://pilotspan.com/docs#errors",
                  "title": "Rate limit exceeded",
                  "status": 429,
                  "detail": "Rate limit exceeded",
                  "code": "example_error",
                  "resolution": "See https://pilotspan.com/docs for the recovery path."
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ProblemDetails": {
        "type": "object",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "code",
          "resolution"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "resolution": {
            "type": "string"
          },
          "instance": {
            "type": "string"
          }
        }
      },
      "Health": {
        "type": "object",
        "required": [
          "ok",
          "service",
          "version",
          "now"
        ],
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "service": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "now": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PostalAddress": {
        "type": "object",
        "required": [
          "streetAddress",
          "addressLocality",
          "addressRegion",
          "postalCode",
          "addressCountry"
        ],
        "properties": {
          "streetAddress": {
            "type": "string"
          },
          "addressLocality": {
            "type": "string"
          },
          "addressRegion": {
            "type": "string"
          },
          "postalCode": {
            "type": "string"
          },
          "addressCountry": {
            "type": "string"
          }
        }
      },
      "Company": {
        "type": "object",
        "required": [
          "name",
          "url",
          "email",
          "telephone",
          "description",
          "address"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "telephone": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "address": {
            "$ref": "#/components/schemas/PostalAddress"
          },
          "sameAs": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            }
          }
        }
      },
      "Feature": {
        "type": "object",
        "required": [
          "id",
          "name",
          "summary"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          }
        }
      },
      "FeatureList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Feature"
            }
          }
        }
      },
      "Service": {
        "type": "object",
        "required": [
          "id",
          "name",
          "summary"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "summary": {
            "type": "string"
          }
        }
      },
      "ServiceList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Service"
            }
          }
        }
      },
      "Faq": {
        "type": "object",
        "required": [
          "question",
          "answer"
        ],
        "properties": {
          "question": {
            "type": "string"
          },
          "answer": {
            "type": "string"
          }
        }
      },
      "FaqList": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Faq"
            }
          }
        }
      },
      "Page": {
        "type": "object",
        "required": [
          "slug",
          "title",
          "url"
        ],
        "properties": {
          "slug": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "summary": {
            "type": "string"
          }
        }
      },
      "PageList": {
        "type": "object",
        "required": [
          "items",
          "next_cursor"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Page"
            }
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "LeadRequest": {
        "type": "object",
        "required": [
          "name",
          "email",
          "company"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "company": {
            "type": "string",
            "minLength": 1,
            "maxLength": 160
          },
          "phone": {
            "type": "string",
            "maxLength": 40
          },
          "message": {
            "type": "string",
            "maxLength": 2000
          }
        }
      },
      "Lead": {
        "type": "object",
        "required": [
          "id",
          "status",
          "created_at"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "accepted"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Job": {
        "type": "object",
        "required": [
          "id",
          "status",
          "poll_url"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "running",
              "succeeded",
              "failed"
            ]
          },
          "poll_url": {
            "type": "string",
            "format": "uri"
          },
          "result_url": {
            "type": "string",
            "format": "uri"
          }
        }
      }
    }
  },
  "x-rate-limit-policy": "120;w=60",
  "x-api-lifecycle": "Stable v1. Breaking changes require /api/v2. Deprecation uses Deprecation and Sunset headers with at least 90 days notice."
}
