{"openapi":"3.1.0","info":{"title":"OpenLawn API","version":"1.0.0","description":"Asynchronous U.S. lawn measurements, saved results, workspace properties, and signed webhooks. Estimates are not legal surveys.","contact":{"email":"support@joinclicki.com","url":"https://openlawn.ai/docs"}},"servers":[{"url":"https://api.openlawn.ai/v1"},{"url":"https://openlawn.ai/v1","description":"Same API, alternate hostname"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Workspace-scoped ol_live_ API key. Create one in Settings → API connections."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]},"request_id":{"type":"string","format":"uuid"}},"required":["error","request_id"]},"Job":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"address":{"type":"string"},"status":{"type":"string","enum":["queued","running","completed","failed","canceled"]},"phase":{"type":["string","null"]},"measurement_id":{"type":["string","null"],"format":"uuid"},"created_at":{"type":["string","null"],"format":"date-time"},"started_at":{"type":["string","null"],"format":"date-time"},"finished_at":{"type":["string","null"],"format":"date-time"}},"required":["id","status"]},"AcceptedJob":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"reused":{"type":"boolean"},"idempotency_key":{"type":"string"}},"required":["id"]},"Measurement":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"address":{"type":"string"},"latitude":{"type":"number"},"longitude":{"type":"number"},"turf_sqft":{"type":"number"},"parcel_turf_sqft":{"type":["number","null"]},"verge_sqft":{"type":["number","null"]},"confidence":{"type":["number","null"]},"processing_ms":{"type":["number","null"]},"model":{"type":["string","null"]},"boundary_source":{"type":["string","null"]},"manual_edited":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":["string","null"],"format":"date-time"},"geometry":{"type":"object","properties":{"coordinate_system":{"const":"normalized_image"},"range":{"type":"array","items":{"type":"number"}},"actions":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Paint/erase polygon actions in normalized image coordinates, not GeoJSON."},"boundary":{"type":"array","items":{}},"imagery":{"type":["object","null"],"properties":{"zoom":{"type":"number"}}}},"required":[]},"inferred_maintained_sqft":{"type":"number"},"snapshot_url":{"type":["string","null"],"format":"uri"},"snapshot_expires_in_seconds":{"type":["integer","null"]}},"required":[]},"Property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"address":{"type":"string"},"measurement_count":{"type":"integer"},"latest_measurement_id":{"type":"string","format":"uuid"},"created_at":{"type":["string","null"],"format":"date-time"}},"required":[]},"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"active":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time"},"disabled_at":{"type":["string","null"],"format":"date-time"},"signing_secret":{"type":"string","description":"Returned only when registering the receiver."}},"required":[]},"Delivery":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"event_id":{"type":"string"},"status":{"type":"string","enum":["pending","delivering","delivered","failed"]},"attempts":{"type":"integer"},"last_http_status":{"type":["integer","null"]},"last_error":{"type":["string","null"]},"created_at":{"type":["string","null"],"format":"date-time"},"delivered_at":{"type":["string","null"],"format":"date-time"}},"required":[]},"Account":{"type":"object","properties":{"workspace":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":[]},"credits":{"type":"object","additionalProperties":true,"description":"Key creator’s current credit balance and reservations."},"credit_owner":{"const":"key_creator"},"rate_limit_per_minute":{"const":120}},"required":[]}}},"paths":{"/account":{"get":{"operationId":"get_account","tags":["Account"],"summary":"Workspace identity and the key creator’s credit balance.","description":"Required scope: account:read.","security":[{"bearerAuth":[]}],"x-required-scope":"account:read","parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Account"},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/measurement-jobs":{"get":{"operationId":"get_measurement_jobs","tags":["Measurement jobs"],"summary":"List background measurement jobs.","description":"Required scope: measurements:read.","security":[{"bearerAuth":[]}],"x-required-scope":"measurements:read","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque next_cursor from the previous page."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Job"}},"next_cursor":{"type":["string","null"]},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"post_measurement_jobs","tags":["Measurement jobs"],"summary":"Queue one address. Requires an Idempotency-Key header.","description":"Required scope: measurements:write. Live requests can consume credits. Keep the same idempotency key when retrying.","security":[{"bearerAuth":[]}],"x-required-scope":"measurements:write","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{8,128}$","example":"crm-property-1042-v1"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"address":{"type":"string","minLength":3,"maxLength":500,"description":"Complete U.S. property street address.","example":"5915 Castle Brook Avenue Southeast, Kentwood, MI 49508"}},"required":["address"]}}}},"responses":{"202":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/AcceptedJob"},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/measurement-jobs/batch":{"post":{"operationId":"post_measurement_jobs_batch","tags":["Measurement jobs"],"summary":"Queue up to 25 addresses with an idempotency_key per item.","description":"Required scope: measurements:write. Live requests can consume credits. Keep the same idempotency key when retrying.","security":[{"bearerAuth":[]}],"x-required-scope":"measurements:write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"jobs":{"type":"array","minItems":1,"maxItems":25,"items":{"type":"object","properties":{"address":{"type":"string","minLength":3,"maxLength":500,"description":"Complete U.S. property street address.","example":"5915 Castle Brook Avenue Southeast, Kentwood, MI 49508"},"idempotency_key":{"type":"string","pattern":"^[A-Za-z0-9_-]{8,128}$","example":"crm-property-1042-v1"}},"required":["address","idempotency_key"]}}},"required":["jobs"]}}}},"responses":{"202":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/AcceptedJob"},{"type":"object","properties":{"idempotency_key":{"type":"string","pattern":"^[A-Za-z0-9_-]{8,128}$","example":"crm-property-1042-v1"},"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":[]}},"required":["idempotency_key","error"]}]}},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/measurement-jobs/{id}":{"get":{"operationId":"get_measurement_jobs_ById","tags":["Measurement jobs"],"summary":"Read a job’s phase, status, and resulting measurement ID.","description":"Required scope: measurements:read.","security":[{"bearerAuth":[]}],"x-required-scope":"measurements:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Use the ID returned by a previous request. Demo fixture IDs do not identify live records."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Job"},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"delete_measurement_jobs_ById","tags":["Measurement jobs"],"summary":"Cancel a non-terminal job created by this key’s user.","description":"Required scope: measurements:write.","security":[{"bearerAuth":[]}],"x-required-scope":"measurements:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Use the ID returned by a previous request. Demo fixture IDs do not identify live records."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"canceled":{"type":"boolean"},"active":{"type":"boolean"}},"required":[]},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/measurements":{"get":{"operationId":"get_measurements","tags":["Measurements"],"summary":"List saved lawn estimates in this workspace.","description":"Required scope: measurements:read.","security":[{"bearerAuth":[]}],"x-required-scope":"measurements:read","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque next_cursor from the previous page."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Measurement"}},"next_cursor":{"type":["string","null"]},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/measurements/{id}":{"get":{"operationId":"get_measurements_ById","tags":["Measurements"],"summary":"Get geometry, area totals, and a five-minute signed snapshot URL.","description":"Required scope: measurements:read.","security":[{"bearerAuth":[]}],"x-required-scope":"measurements:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Use the ID returned by a previous request. Demo fixture IDs do not identify live records."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Measurement"},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/properties":{"get":{"operationId":"get_properties","tags":["Properties"],"summary":"List properties grouped by normalized saved address.","description":"Required scope: properties:read.","security":[{"bearerAuth":[]}],"x-required-scope":"properties:read","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque next_cursor from the previous page."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Property"}},"next_cursor":{"type":["string","null"]},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/properties/{id}":{"get":{"operationId":"get_properties_ById","tags":["Properties"],"summary":"Get a property and its latest measurement ID.","description":"Required scope: properties:read.","security":[{"bearerAuth":[]}],"x-required-scope":"properties:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Use the ID returned by a previous request. Demo fixture IDs do not identify live records."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Property"},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks":{"get":{"operationId":"get_webhooks","tags":["Webhooks"],"summary":"List webhook receivers without their signing secrets.","description":"Required scope: webhooks:read.","security":[{"bearerAuth":[]}],"x-required-scope":"webhooks:read","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque next_cursor from the previous page."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}},"next_cursor":{"type":["string","null"]},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"post_webhooks","tags":["Webhooks"],"summary":"Register a receiver; the signing secret is returned only once.","description":"Required scope: webhooks:write.","security":[{"bearerAuth":[]}],"x-required-scope":"webhooks:write","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","maxLength":2048,"description":"Approved HTTPS receiver. Zapier and Make supported; custom domains require approval."}},"required":["url"]}}}},"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Webhook"},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{id}":{"delete":{"operationId":"delete_webhooks_ById","tags":["Webhooks"],"summary":"Disable a receiver and stop future delivery attempts.","description":"Required scope: webhooks:write.","security":[{"bearerAuth":[]}],"x-required-scope":"webhooks:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Use the ID returned by a previous request. Demo fixture IDs do not identify live records."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"canceled":{"type":"boolean"},"active":{"type":"boolean"}},"required":[]},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{id}/test":{"post":{"operationId":"post_webhooks_ById_test","tags":["Webhooks"],"summary":"Queue a webhook.test event without running a measurement.","description":"Required scope: webhooks:write.","security":[{"bearerAuth":[]}],"x-required-scope":"webhooks:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Use the ID returned by a previous request. Demo fixture IDs do not identify live records."}],"responses":{"202":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"event_id":{"type":"string"},"status":{"type":"string"}},"required":[]},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{id}/deliveries":{"get":{"operationId":"get_webhooks_ById_deliveries","tags":["Webhooks"],"summary":"List delivery status and attempts for this receiver.","description":"Required scope: webhooks:read.","security":[{"bearerAuth":[]}],"x-required-scope":"webhooks:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"},"description":"Use the ID returned by a previous request. Demo fixture IDs do not identify live records."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque next_cursor from the previous page."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Delivery"}},"next_cursor":{"type":["string","null"]},"request_id":{"type":"string","format":"uuid"}},"required":["data","request_id"]}}}},"400":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"405":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Request error; see error.code. Retry 429 after the Retry-After header.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}