{"openapi":"3.1.0","info":{"title":"MAIA API","description":"API for MAIA application (migrated from Firebase)","version":"0.1.0"},"paths":{"/":{"get":{"summary":"Root","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootResponse"}}}}}}},"/_ah/ready":{"get":{"summary":"Ready","operationId":"ready__ah_ready_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReadyResponse"}}}}}}},"/api/v1/auth/login":{"post":{"tags":["auth"],"summary":"Local Login","description":"Return a local mock token when Firebase auth is disabled.","operationId":"local_login_api_v1_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocalLoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocalTokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/me":{"get":{"tags":["auth"],"summary":"Get Current User Info","description":"Returns information about the currently authenticated user.\n\nRequires a valid Firebase ID token in the Authorization header.\nIncludes auto-linking for users created in DB who log in via Google SSO.\n\nExempt from the terms gate: this is how the client learns it must prompt\nfor acceptance, so gating it would leave the client unable to render the\nprompt that clears the gate.","operationId":"get_current_user_info_api_v1_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfile"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/auth/check":{"get":{"tags":["auth"],"summary":"Check Authentication","description":"Checks if the user is authenticated and returns user info if they are.\n\nDoes not require authentication - returns null if no valid token is provided.\nFalls back to email lookup if Firebase UID doesn't match database ID.\nWhen found via email fallback, updates the user's database ID to match the new\nFirebase-derived ID to prevent future mismatches.","operationId":"check_authentication_api_v1_auth_check_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/UserProfile"},{"type":"null"}],"title":"Response Check Authentication Api V1 Auth Check Get"}}}}}}},"/api/v1/auth/user-exists":{"get":{"tags":["auth"],"summary":"Check User Exists","description":"Checks if a user with the given email exists in the database.\n\nA self-serve account with no users row yet (waitlisted, or a setup that\nfailed before creating one) still counts as existing: its Firebase\nidentity is real, and blocking it here would strand the person before the\nsign-in that routes them back to their setup state.\n\nRate Limited: 10 requests per minute per IP address.\n\nSecurity considerations:\n- Rate limiting prevents automated user enumeration attacks\n- Consistent response timing mitigates timing-based attacks\n- All requests are logged for security monitoring\n\nDoes not require authentication - public endpoint for login flow validation.","operationId":"check_user_exists_api_v1_auth_user_exists_get","parameters":[{"name":"email","in":"query","required":true,"schema":{"type":"string","title":"Email"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserExistsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/password-reset-email":{"post":{"tags":["auth"],"summary":"Request Password Reset Email","description":"Send a password reset email through MAIA's branded transactional channel.\n\nRate Limited: 5 requests per minute per IP address.\n\nDoes not require authentication — public endpoint for the forgot-password\nflow. Always returns 202 regardless of whether the email maps to an\naccount: the lookup and send happen in a background task after the\nresponse, so account existence leaks through neither status, body, nor\ntiming.","operationId":"request_password_reset_email_api_v1_auth_password_reset_email_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PasswordResetEmailRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/setup-token/inspect":{"post":{"tags":["auth"],"summary":"Inspect Setup Token","description":"Report what an account-setup token is worth, without consuming it.\n\nRate Limited: 20 requests per minute per IP address — headroom for a mail\ngateway's link scanner plus the recipient's own page loads.\n\nDoes not require authentication; the token is the credential. Reading a\ntoken must never consume it: Microsoft Defender Safe Links fetches every\nURL in inbound mail before delivering it, so a consume-on-read token is\nspent by a scanner before the recipient ever opens the message.","operationId":"inspect_setup_token_api_v1_auth_setup_token_inspect_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupTokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupTokenStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/setup-token/redeem":{"post":{"tags":["auth"],"summary":"Redeem Setup Token","description":"Consume an account-setup token and set the account's password.\n\nRate Limited: 5 requests per minute per IP address.\n\nDoes not require authentication — the token is the credential. Each failure\nmode gets its own status so the page can tell the user what to do next;\nnone of them names the account, so a guessed token reveals nothing. The\nstatus table lives with the exceptions rather than as a ladder here, so a\nnew refusal cannot reach the client as an unmapped 500.","operationId":"redeem_setup_token_api_v1_auth_setup_token_redeem_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupTokenRedeemRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/signup":{"post":{"tags":["auth"],"summary":"Start Signup","description":"Route a freshly authenticated identity that has no MAIA account.\n\nRate Limited: 5 requests per minute per IP address.\n\nAuthenticated, but exempt from the terms gate — an account this new has\naccepted nothing, and the gate would refuse the very request that creates\nthe account it would gate. Suspension is still enforced.\n\nA POST rather than a side effect on the profile read: this creates an\naccount and sends mail, which a GET must never do.","operationId":"start_signup_api_v1_auth_signup_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/auth/verify-email":{"post":{"tags":["auth"],"summary":"Verify Email","description":"Redeem a signup verification link and continue into admission.\n\nRate Limited: 5 requests per minute per IP address.\n\nDoes not require authentication — the link is the credential, matching the\naccount-setup redeem path. Each refusal gets its own status so the page can\ntell the user what to do next; none of them names an account.","operationId":"verify_email_api_v1_auth_verify_email_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailVerificationRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/signup/availability":{"get":{"tags":["auth"],"summary":"Get Signup Availability","description":"Whether public self-serve signup is currently open.\n\nRate Limited: 30 requests per minute per IP address.\n\nUnauthenticated pre-flight for the signup page, so a closed surface shows\nits closed screen BEFORE the form can mint a Firebase identity the POST\nwould then refuse. Advisory only: the toggle-gated POST routes remain the\nauthoritative gate, and the closed state already leaks through their 404s,\nso this read reveals nothing new.","operationId":"get_signup_availability_api_v1_auth_signup_availability_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupAvailabilityResponse"}}}}}}},"/api/v1/auth/signup/status":{"get":{"tags":["auth"],"summary":"Get Signup Status","description":"Where the caller's own self-serve setup stands.\n\nDeliberately NOT gated on the public signup toggle: an operator switching\nthe surface off must not strand people mid-setup, and this read creates\nnothing, mails nothing, and answers only about the caller's own address —\nso keeping it alive leaks nothing the account's existence hasn't already\ncommitted to. The write paths stay behind the toggle.\n\n``paused`` is derived from the live pause flag rather than stored, so a\nwaitlisted person always sees the current admission posture.\n\nNo account row exists until the verification link is redeemed, so a bare\n404 there would tell a mid-verification return \"you never signed up\"\nwhile their link is still live — an outstanding link reports\n``verification_pending`` instead, and only a truly unknown address 404s.","operationId":"get_signup_status_api_v1_auth_signup_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupStatusResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/auth/signup/profile":{"post":{"tags":["auth"],"summary":"Submit Signup Profile","description":"Store the caller's questionnaire answers on their own account.\n\nRate Limited: 10 requests per minute per IP address.\n\nDeliberately NOT gated on the public signup toggle, for the same reason as\nthe status read beside it: the form shows on the status page mid-setup, and\nan operator switching the surface off must not turn a submit that was on\nscreen into a vanished route. The write annotates the caller's own\nexisting account and creates nothing, so it does not belong to the\nservice's toggle-gated entry points — which is also why it writes through\nthe repository directly rather than growing a service method the derived\nentry-point sweeps would rightly demand a gate on.","operationId":"submit_signup_profile_api_v1_auth_signup_profile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignupProfileRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/auth/session":{"post":{"tags":["auth"],"summary":"Mint Session","description":"Mint an HttpOnly session cookie from the caller's Firebase JWT.\n\nThe client calls this whenever Firebase auth state changes. The cookie\nreplaces the `?token=<jwt>` query param on tile URLs (MAIA-1715) — Mapbox\ncaches URLs but always picks up cookies fresh from the jar, so the\n\"tile-URL goes stale during long idle\" bug class is eliminated.\n\nExempt from the terms gate because the cookie is tiles' only auth channel\n(Mapbox cannot send custom headers) and the mint is driven by Firebase\nauth-state changes, which do not re-fire on acceptance. A user who accepted\nwhile the mint was blocked would otherwise have a broken map until their\nnext sign-in. Every endpoint the cookie unlocks is itself gated.","operationId":"mint_session_api_v1_auth_session_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Mint Session Api V1 Auth Session Post"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/auth/sign-out":{"post":{"tags":["auth"],"summary":"Sign Out","description":"Clear the MAIA session cookie. Unauthenticated — clients should be able\nto clear their cookie even if they no longer have a valid session.","operationId":"sign_out_api_v1_auth_sign_out_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Sign Out Api V1 Auth Sign Out Post"}}}}}}},"/api/v1/auth/profile":{"put":{"tags":["auth"],"summary":"Update User Profile","description":"Update the current user's profile information.\nRequires authentication.","operationId":"update_user_profile_api_v1_auth_profile_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserProfileUpdateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/terms/accept":{"post":{"tags":["terms"],"summary":"Accept Terms","description":"Record the caller's acceptance of the currently published terms.\n\nDeliberately outside the terms gate — a gated accept endpoint would\ndeadlock the flow it exists to complete.","operationId":"accept_terms_api_v1_terms_accept_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TermsAcceptanceRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TermsAcceptanceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/limits":{"get":{"tags":["enrichment"],"summary":"Get Enrichment Limits","description":"Per-batch limits for column-wide bulk enrichment.\n\nReturns the canonical server values backing the column-header Enrich\nsubmenu's clamps and confirm gates. The FE should fetch these once and\ncache; never carry its own copy of these constants.","operationId":"get_enrichment_limits_api_v1_enrichment_limits_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentLimitsResponse"}}}}}}},"/api/v1/enrichment/all":{"get":{"tags":["enrichment"],"summary":"Get All Enrichments","description":"Get all custom enrichments.\nRequires authentication. Allows read access to owned or example projects.\n\nArgs:\n    request: The request object containing project_id (pre-validated)\n    enrichment_service: Service for handling enrichment operations\n\nReturns:\n    List of all enrichments","operationId":"get_all_enrichments_api_v1_enrichment_all_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentListResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/create":{"post":{"tags":["enrichment"],"summary":"Create Enrichment","description":"Create a new enrichment with default values. Requires layer ownership.\n\nArgs:\n    request: The request object containing layer_id (pre-validated)\n    enrichment_service: Service for handling enrichment operations\n\nReturns:\n    Dictionary containing enrichment data","operationId":"create_enrichment_api_v1_enrichment_create_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEnrichmentRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/enrich_async/status_batch":{"post":{"tags":["enrichment"],"summary":"Get Enrichment Status Batch","description":"Get the status of multiple enrichment workflows.","operationId":"get_enrichment_status_batch_api_v1_enrichment_enrich_async_status_batch_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentStatusBatchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentStatusListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/enrich_async/{enrichment_id}/preflight":{"post":{"tags":["enrichment"],"summary":"Preflight Enrich Row Async","operationId":"preflight_enrich_row_async_api_v1_enrichment_enrich_async__enrichment_id__preflight_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichRowRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentAdmissionPreflightResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enrichment/enrich_async/{enrichment_id}":{"post":{"tags":["enrichment"],"summary":"Enrich Row Async","description":"Enrich rows in the dataset asynchronously.\n\nSupports two selection modes (exactly one per request, enforced by\n``EnrichRowRequest`` validator):\n\n- ``feature_ids`` — explicit ids; legacy path, unchanged.\n- ``selection`` — filter spec + fingerprint + expected count. The\n  server validates the fingerprint (400 on mismatch), recomputes the\n  live count (409 on drift), and resolves the matching ids\n  server-side before enqueueing — no wire-payload of large id\n  arrays.","operationId":"enrich_row_async_api_v1_enrichment_enrich_async__enrichment_id__post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichRowRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentBatchStartResponse"}}}},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentDispatchConflictResponse"}}},"description":"Conflict"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enrichment/{enrichment_id}":{"put":{"tags":["enrichment"],"summary":"Update Enrichment","description":"Update an enrichment. Requires ownership of the project containing the enrichment.\n\nThe mortgage entitlement check fetches the user profile lazily — only a\nretarget onto the mortgage tool pays the profile DB round-trip.\n\nArgs:\n    enrichment_id: The ID of the enrichment to update (pre-validated)\n    request: The request object containing updated fields\n    enrichment_service: Service for handling enrichment operations\n\nReturns:\n    Dictionary containing enrichment data","operationId":"update_enrichment_api_v1_enrichment__enrichment_id__put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEnrichmentRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentResponse"}}}},"409":{"description":"The update needs approval before stored rows are re-enriched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentUpdateConflictResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/delete":{"post":{"tags":["enrichment"],"summary":"Delete Enrichment","description":"Delete an enrichment. Requires ownership of the project containing the enrichment.\n\nArgs:\n    request: The request object containing enrichment_id and project_id (pre-validated)\n    enrichment_service: Service for handling enrichment operations\n\nReturns:\n    Dict with success status and message","operationId":"delete_enrichment_api_v1_enrichment_delete_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentDelete"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentDeleteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/workflow/status/{workflow_id}":{"get":{"tags":["enrichment"],"summary":"Get Enrichment Status","description":"Get the status of a single enrichment workflow.","operationId":"get_enrichment_status_api_v1_enrichment_workflow_status__workflow_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workflow_id","in":"path","required":true,"schema":{"type":"string","title":"Workflow Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enrichment/agent_workflow/status/{workflow_id}":{"get":{"tags":["enrichment"],"summary":"Get Enrichment Agent Task Status","description":"Get the status of an enrichment agent (creation/update) workflow.","operationId":"get_enrichment_agent_task_status_api_v1_enrichment_agent_workflow_status__workflow_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workflow_id","in":"path","required":true,"schema":{"type":"string","title":"Workflow Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentAgentStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enrichment/all_user":{"get":{"tags":["enrichment"],"summary":"Get All User Enrichments","description":"Get all enrichments.\nRequires authentication.","operationId":"get_all_user_enrichments_api_v1_enrichment_all_user_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllUserEnrichmentsResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/add_to_layer":{"post":{"tags":["enrichment"],"summary":"Add Enrichment To Layer","description":"Add an enrichment to a layer. Requires ownership of the project containing the layer.\n\nArgs:\n    request: The request object containing enrichment_id and layer_id (pre-validated)\n    enrichment_service: Service for handling enrichment operations\n\nReturns:\n    message with success status","operationId":"add_enrichment_to_layer_api_v1_enrichment_add_to_layer_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEnrichmentToLayerRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddEnrichmentToLayerResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/delete_from_library":{"post":{"tags":["enrichment"],"summary":"Delete Enrichment From Library","description":"Delete an enrichment.\nRequires authentication.\n\nArgs:\n    request: The request object containing enrichment_id\n    enrichment_service: Service for handling enrichment operations\n\nReturns:\n    Dict with success status and message","operationId":"delete_enrichment_from_library_api_v1_enrichment_delete_from_library_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentDeleteFromLibraryRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentDeleteFromLibraryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/credits":{"get":{"tags":["enrichment"],"summary":"Get Enrichment Credits","description":"Get the number of enrichments credits available for this user.","operationId":"get_enrichment_credits_api_v1_enrichment_credits_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentCreditsResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/in-flight/{project_id}":{"get":{"tags":["enrichment"],"summary":"Get In Flight Tasks","description":"Get all in-flight enrichment workflows for a project.\n\nQueries DBOS workflow status filtered to non-terminal row-enrichment\nworkflows and aggregates per-field for the polling UI.","operationId":"get_in_flight_tasks_api_v1_enrichment_in_flight__project_id__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InFlightTasksResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/in-flight":{"get":{"tags":["enrichment"],"summary":"Get All In Flight Tasks","description":"Get all in-flight enrichment workflows across the user's projects.","operationId":"get_all_in_flight_tasks_api_v1_enrichment_in_flight_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AllInFlightTasksResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/cancel/bulk":{"post":{"tags":["enrichment"],"summary":"Cancel Enrichment Workflows Bulk","description":"Bulk-cancel in-flight DBOS enrichment workflows.\n\nBest-effort + idempotent, matching the single-cancel contract. Returns\n204 unconditionally — workflows the caller doesn't own, workflows\nwithout a reservation row, and workflows already in a terminal state\nare silently skipped. The FE's column-level cancel sends every\nworkflow_id it tracked and relies on polling to converge each one to\nREVOKED.","operationId":"cancel_enrichment_workflows_bulk_api_v1_enrichment_cancel_bulk_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkCancelEnrichmentRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/enrichment/cancel/{workflow_id}":{"post":{"tags":["enrichment"],"summary":"Cancel Enrichment Workflow","description":"Cancel an in-flight DBOS enrichment workflow + refund any unsettled credits [MAIA-1468].\n\nReturns 204 on success (idempotent on terminal states). 404 if the\nworkflow has no reservation row (Celery-routed enrichment or unknown ID)\nor if the user doesn't own the workspace it belongs to. Cross-workspace\naccess is 404 not 403 to avoid leaking workflow existence.\n\nThe ``_current_user`` Depends enforces authn; workspace authz is resolved\ninside the service via the request-scoped ``UserService`` (already bound\nto the current user via DI).","operationId":"cancel_enrichment_workflow_api_v1_enrichment_cancel__workflow_id__post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workflow_id","in":"path","required":true,"schema":{"type":"string","title":"Workflow Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/project/all":{"get":{"tags":["project"],"summary":"Get All Projects","description":"Get all projects for the authenticated user.\n\nArgs:\n    project_service: Project service for business logic\n    user_profile: Current user's profile (for workspace role and can_edit)\n\nReturns:\n    List of projects visible to the user with can_edit computed per project","operationId":"get_all_projects_api_v1_project_all_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectListResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/sandbox":{"post":{"tags":["project"],"summary":"Create Sandbox Project","description":"Create a single-click county sandbox project pre-loaded with the\ncounty's boundary layer.\n\nTwo-phase: this handler runs phase 1 (validate FIPS, insert PENDING\nproject row, return ``project_id``) synchronously and enqueues phase 2\n(Neon name resolve, CREATE MATERIALIZED VIEW, register boundary layer,\nflip status to READY) on the Celery `sandbox_boundary` queue. Celery is\nused instead of FastAPI ``BackgroundTasks`` so a Cloud Run instance\nrestart between response and task completion can't strand the project\nin ``PENDING`` — the broker persists the job until a worker acks.\n\nWorkspace RBAC: rejects FIPS codes not in the user's available\ngeographies (403). FIPS not loaded into the workspace's\n``workspace_counties`` table is a 404 before any project row is\ninserted. Failures inside the background task mark the project\n``status=FAILED`` (visible on the project page); the task itself retries\nwith exponential backoff before reaching that state.","operationId":"create_sandbox_project_api_v1_project_sandbox_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxProjectRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxProjectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/sandbox/from-feature":{"post":{"tags":["project"],"summary":"Create Sandbox Project From Feature","description":"Create a sandbox project from a confirmed resolved feature (address entry).\n\nThe create-flow inversion: unlike ``POST /sandbox`` (county picked first),\nthe county scope is *derived* from the matched feature before the project's\nRLS role is provisioned. Two-phase — this handler derives scope, inserts the\nPENDING project + role synchronously, and enqueues the async layer seed;\n``status`` flips to ``ready`` and the layer arrives via SSE.\n\nNo ``available_geographies`` 403: the matched feature is in-coverage by\nconstruction (the resolver only searched this workspace's loaded sandbox).\nUnknown ``feature_id`` → 404; a county somehow not loaded → 404 before any\nproject row is inserted; a matched feature whose ``_county_fips`` is\nNULL/malformed (a sandbox data-integrity fault, not a caller error) → 422.","operationId":"create_sandbox_project_from_feature_api_v1_project_sandbox_from_feature_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressCreateFlowRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressProjectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/sandbox/from-upload":{"post":{"tags":["project"],"summary":"Submit Import Job For New Project","description":"Start a background import as a NEW project (Door 1, async).\n\nReturns as soon as the project row and the job exist, so the client can\nnavigate straight to a project that reads as not-yet-ready while the import\nruns. The county is derived here, from a sample — a sandbox project cannot be\ncreated without one, so sampling is what lets the project exist before the\nresolve does.\n\nSeparate from ``/sandbox/from-features`` rather than a branch inside it: that\nroute's ``upload`` field means \"here are the matches I already resolved\", and\nquietly re-pointing it at background execution would strand a browser tab\nopen across the deploy.","operationId":"submit_import_job_for_new_project_api_v1_project_sandbox_from_upload_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportSubmitRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportSubmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/sandbox/from-features":{"post":{"tags":["project"],"summary":"Create Sandbox Project From Features","description":"Create one sandbox project from several confirmed features (Door 1).\n\nThe multi-feature twin of ``/sandbox/from-feature``: derives one shared county\nfrom every feature's marker before inserting the project, then enqueues a single\nseed for all of them. Unknown ``feature_id`` → 404; a NULL/malformed marker →\n422; features spanning more than one county → 422 (a project is scoped to one\ncounty under RLS, so the paste must be split). ``status`` flips to ``ready`` and\nthe layers arrive via SSE.\n\n``features`` is the paste flow. ``upload`` is the file-import flow, whose row\nvalues come from the server's held inspect result rather than this request.","operationId":"create_sandbox_project_from_features_api_v1_project_sandbox_from_features_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressBatchCreateFlowRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressProjectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/address/resolve":{"post":{"tags":["project"],"summary":"Resolve Address","description":"Resolve free text to ranked, label-hydrated candidates for address entry.\n\nPre-project: bounded to ``request.county_fips`` when the caller picked a\ncounty first, otherwise across every county the caller's workspace has\nloaded (the sandbox partition is the access control either way). A read\nfailure surfaces as 503 rather than the raw error, which can carry a\nsandbox connection URI.","operationId":"resolve_address_api_v1_project_address_resolve_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressResolveRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressResolveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/address/resolve-many":{"post":{"tags":["project"],"summary":"Resolve Addresses Batch For Project","description":"Project-scoped batch resolve for both in-project surfaces — the import\ndialog (Door 2) and chat paste.\n\nThe county scope is the project's canonical ``county_fips`` (derived\nserver-side, never client-supplied), so a paste can't resolve outside the\nproject's county; a project with no county scope is a 404. Resolution runs\nagainst the project's sandbox — internal misses and address candidates that name\nanother street fall through to the forward geocoder (it resolves points against a\nproject) instead of classifying as ``not_in_dataset`` like the pre-project batch\nmust.","operationId":"resolve_addresses_batch_for_project_api_v1_project__project_id__address_resolve_many_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectAddressResolveManyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressResolveManyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/address/resolve-many":{"post":{"tags":["project"],"summary":"Resolve Addresses Batch","description":"Resolve a pasted handful of addresses in one batch for the paste review list.\n\nOne typed outcome per input row in input order (matched / ambiguous /\nnot_in_dataset / empty_input), county-bounded like the single resolve. Candidate\nlabels for every row are hydrated in a single read, then re-split per row. A read\nfailure surfaces as 503 rather than the raw error (which can carry a sandbox URI).","operationId":"resolve_addresses_batch_api_v1_project_address_resolve_many_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressResolveManyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressResolveManyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/address/feature-geometry":{"get":{"tags":["project"],"summary":"Get Address Feature Geometry","description":"Drawable geometry + bbox for one resolved candidate, pre-project.\n\n404 covers both a malformed/unknown ``feature_id`` and a row with null\ngeometry — either way there is nothing to draw. Read failures map to 503,\nmirroring ``/address/resolve``.","operationId":"get_address_feature_geometry_api_v1_project_address_feature_geometry_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"source_table","in":"query","required":true,"schema":{"$ref":"#/components/schemas/SourceTable"}},{"name":"feature_id","in":"query","required":true,"schema":{"type":"string","title":"Feature Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressFeatureGeometryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/project/sandbox/warm-county":{"post":{"tags":["project"],"summary":"Warm County Boundary","description":"Pre-warm the boundary MV for a county without creating a project.\n\nCalled from the picker the moment a user soft-selects a county, so\nthe Neon roundtrip (TIGER GEOID lookup + CREATE MATERIALIZED VIEW +\nindex) overlaps with prompt composition instead of blocking the\nsubsequent project-create. Idempotent — the MV is workspace-scoped\nand deterministically named by ``county_fips``; concurrent warms are\nserialized inside ``ensure_county_boundary_mv`` by an advisory lock\nand the second caller fast-paths on the existing MV.\n\nWorkspace RBAC mirrors ``create_sandbox_project``: FIPS not in the\nuser's available geographies → 403, FIPS not loaded into the\nworkspace's ``workspace_counties`` table → 404, FIPS not present in\nthe workspace's ``tiger_county`` table → 404. No project row is\ncreated on any path — the warm flow is read-only at the app-DB level.","operationId":"warm_county_boundary_api_v1_project_sandbox_warm_county_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxWarmCountyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SandboxWarmCountyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}":{"get":{"tags":["project"],"summary":"Get Project","description":"Get a single project by ID.\n\nRequires read access (ownership, workspace membership, example, or admin\nview/write mode). Admin view mode forces can_edit=False; admin write mode\nforces can_edit=True. Both force is_owner=False.","operationId":"get_project_api_v1_project__project_id__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"put":{"tags":["project"],"summary":"Update Project","description":"Update a project's basic information (name and/or description).\n\nArgs:\n    project_id: UUID of the project (validated to be owned by current user)\n    project_data: Project update parameters containing optional name/description\n    project_service: Project service for business logic\n\nReturns:\n    Response with success status, message, and updated project data\n\nRaises:\n    HTTPException: 404 if project not found or user doesn't own it\n    ValueError: If no fields to update are provided","operationId":"update_project_api_v1_project__project_id__put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectUpdateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"delete":{"tags":["project"],"summary":"Delete Project","description":"Delete a project.\n\nArgs:\n    project_id: UUID of the project (validated to be owned by current user)\n    project_service: Project service for business logic\n\nReturns:\n    Dict with success status and message\n\nRaises:\n    HTTPException: 404 if project not found or user doesn't own it","operationId":"delete_project_api_v1_project__project_id__delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectDeleteResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/default-view":{"put":{"tags":["project"],"summary":"Set Project Default View","description":"Set (or clear) the project's durable default view.\n\nThe default view is the view anonymous share-link visitors and first-time\nviewers land on when the URL carries no explicit ``?view=``. Settable by any\neditor (validated by the dependency).\n\nRaises:\n    HTTPException: 404 if project not found or the caller can't write it,\n        400 if ``view_id`` isn't one of the project's views.","operationId":"set_project_default_view_api_v1_project__project_id__default_view_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetDefaultViewRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectUpdateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/views/reorder":{"patch":{"tags":["project"],"summary":"Reorder Views","description":"Reorder a project's views to match the supplied id order.\n\nDeclared *before* the ``/{view_id}`` PATCH route: FastAPI matches routes in\ndeclaration order, so the literal ``reorder`` segment must register first or\n``{view_id}`` would capture it (``view_id=\"reorder\"``).\n\nArgs:\n    project_id: UUID of the project (validated to be owned by current user)\n    request: The full ordered list of view ids\n    view_service: View service for business logic\n\nReturns:\n    Response with success status and the views in their new order\n\nRaises:\n    HTTPException: 404 if project not found or user doesn't own it,\n        400 if ``view_ids`` isn't a permutation of the project's views.","operationId":"reorder_views_api_v1_project__project_id__views_reorder_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViewsReorderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViewsReorderResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/views/{view_id}":{"patch":{"tags":["project"],"summary":"Update View","description":"Update a single view with partial data and atomic ownership validation.\n\nArgs:\n    project_id: UUID of the project (validated to be owned by current user)\n    view_id: String ID of the view to update\n    request: Request containing the partial view update data\n    view_service: View service for business logic\n\nReturns:\n    Response with success status and updated view data\n\nRaises:\n    HTTPException: 404 if project/view not found or user doesn't own it,\n        409 if ``expected_version`` is stale (the view changed concurrently).","operationId":"update_view_api_v1_project__project_id__views__view_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"view_id","in":"path","required":true,"schema":{"type":"string","title":"View Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViewUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViewUpdateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["project"],"summary":"Delete View","description":"Delete a view from a project.\n\nArgs:\n    project_id: UUID of the project (validated to be owned by current user)\n    view_id: String ID of the view to delete\n    view_service: View service for business logic\n\nReturns:\n    Response with success status and message\n\nRaises:\n    HTTPException: 404 if project/view not found or user doesn't own it","operationId":"delete_view_api_v1_project__project_id__views__view_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"view_id","in":"path","required":true,"schema":{"type":"string","title":"View Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViewDeleteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/project/{project_id}/views":{"get":{"tags":["project"],"summary":"Get Views","description":"Get all views for a project.\n\nArgs:\n    project_id: UUID of the project (validated for read access - owned or example)\n    view_service: View service for business logic\n\nReturns:\n    Response containing list of views\n\nRaises:\n    HTTPException: 404 if project not found or user doesn't have access","operationId":"get_views_api_v1_project__project_id__views_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViewsGetResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"post":{"tags":["project"],"summary":"Create View","description":"Create a new view for a project.\n\nArgs:\n    project_id: UUID of the project (validated to be owned by current user)\n    request: Request containing the view to create\n    view_service: View service for business logic\n\nReturns:\n    Response with success status and created view data\n\nRaises:\n    HTTPException: 404 if project not found or user doesn't own it","operationId":"create_view_api_v1_project__project_id__views_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViewCreateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViewCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/chats":{"get":{"tags":["project"],"summary":"Get Project Chat","description":"Get the chat for a specific project.\n\nArgs:\n    project_id: The ID of the project to get chat for (validated for read access).\n    agent_service: The AgentService instance (dependency).\n    user_repo: User repository for resolving sender display names.\n    project_repo: Project repository for checking project visibility.\n    user_profile: Current user's profile for internal status check.\n\nReturns:\n    The chat history for the project, or None if no chat exists.\n\nRaises:\n    HTTPException: 400 for validation errors.\n    HTTPException: 404 if project not found or user doesn't have access.\n    HTTPException: 500 for unexpected errors.","operationId":"get_project_chat_api_v1_project__project_id__chats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatHistoryResponseSchema"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/chats/status":{"get":{"tags":["project"],"summary":"Get Project Chat Run Status","description":"Get the authoritative chat-run state for an authenticated project read.","operationId":"get_project_chat_run_status_api_v1_project__project_id__chats_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ActiveChatRunStatus"},{"$ref":"#/components/schemas/IdleChatRunStatus"},{"$ref":"#/components/schemas/UnknownChatRunStatus"}],"title":"Response Get Project Chat Run Status Api V1 Project  Project Id  Chats Status Get","discriminator":{"propertyName":"status","mapping":{"active":"#/components/schemas/ActiveChatRunStatus","idle":"#/components/schemas/IdleChatRunStatus","unknown":"#/components/schemas/UnknownChatRunStatus"}}}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/chats/answer":{"post":{"tags":["project"],"summary":"Record Interactive Answer","description":"Persist a feature-bound interactive-question pick that skipped the chat turn.\n\nA resolved-address pick adds its layer directly (deterministic CRUD, no agent\nturn), so its answer never rode a ``prior_answer`` onto ``/chat/stream``. This\nrecords it against the owning question so a reload renders the card answered.\nNo agent run is started. A pick whose question isn't in the persisted history\n(a paste-injected card) records nothing and returns ``recorded=False``.","operationId":"record_interactive_answer_api_v1_project__project_id__chats_answer_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InteractiveQuestionAnswer"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordInteractiveAnswerResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/chats/note":{"post":{"tags":["project"],"summary":"Append Chat Note","description":"Persist a deterministic action summary into the project's chat history.\n\nBulk paste-adds run off the agent turn, so the outcome (\"Added 4 addresses\nto Parcel features\") would otherwise leave no durable trace in the chat.\nThe note is appended as a synthetic assistant message; no agent run starts.","operationId":"append_chat_note_api_v1_project__project_id__chats_note_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatNoteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatNoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/share":{"get":{"tags":["project"],"summary":"Get Share Info","description":"Get share link info for a project.\n\nReturns one of three states:\n- Never shared: is_shared=False, share=None\n- Previously shared (revoked): is_shared=False, share={is_active: False, ...}\n- Currently shared: is_shared=True, share={is_active: True, ...}\n\nAlso includes workspace context (name, member count, project visibility)\nfor the share dialog. Requires write access to the project.\n\nArgs:\n    project_id: UUID of the project (validated for write access)\n    user_profile: Current user's profile (for workspace_id)\n    share_service: ProjectShareService for share link operations\n\nReturns:\n    Share info with is_shared flag, optional share details, and workspace context","operationId":"get_share_info_api_v1_project__project_id__share_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareInfoResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"post":{"tags":["project"],"summary":"Generate Share Link","description":"Generate a share link for a project (idempotent).\n\nIf an active share link already exists, returns it. Otherwise creates\na new one with a unique token. Requires write access to the project.\n\nArgs:\n    project_id: UUID of the project (validated for write access)\n    share_service: ProjectShareService for share link operations\n\nReturns:\n    Share link details including full URL, token, and status","operationId":"generate_share_link_api_v1_project__project_id__share_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ShareLinkCreateRequest"},{"type":"null"}],"title":"Request"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareLinkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"delete":{"tags":["project"],"summary":"Revoke Share Link","description":"Revoke the active share link for a project.\n\nPermanently invalidates the current share token. Re-enabling sharing\nwill generate a new token (old links stay dead). Requires write access to the project.\n\nArgs:\n    project_id: UUID of the project (validated for write access)\n    share_service: ProjectShareService for share link operations\n\nReturns:\n    Success confirmation\n\nRaises:\n    HTTPException: 404 if no active share link exists","operationId":"revoke_share_link_api_v1_project__project_id__share_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareRevokeResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/share/viewers":{"get":{"tags":["project"],"summary":"Get Share Viewers","operationId":"get_share_viewers_api_v1_project__project_id__share_viewers_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareViewerPageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/project/{project_id}/share/viewers.csv":{"get":{"tags":["project"],"summary":"Export Share Viewers","operationId":"export_share_viewers_api_v1_project__project_id__share_viewers_csv_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/lock":{"get":{"tags":["project-lock"],"summary":"Get Lock Status","description":"Get current lock status (who holds it, if anyone). Read access only.","operationId":"get_lock_status_api_v1_project__project_id__lock_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectLockStatus"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"post":{"tags":["project-lock"],"summary":"Acquire Lock","description":"Acquire the project editing lock. Refreshes TTL if already held by caller.","operationId":"acquire_lock_api_v1_project__project_id__lock_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectLockStatus"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"delete":{"tags":["project-lock"],"summary":"Release Lock","description":"Release the project editing lock. Only the holder can release.","operationId":"release_lock_api_v1_project__project_id__lock_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Response Release Lock Api V1 Project  Project Id  Lock Delete"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/project/{project_id}/lock/heartbeat":{"post":{"tags":["project-lock"],"summary":"Lock Heartbeat","description":"Refresh the lock TTL. Call every ~30s while holding the lock.","operationId":"lock_heartbeat_api_v1_project__project_id__lock_heartbeat_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectLockStatus"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/layer/{project_id}":{"get":{"tags":["layer"],"summary":"Get Project Layers","description":"Get all layers for a specific project.\n\nArgs:\n    project_id: The ID of the project to get layers for (validated for read access)\n    layer_service: Service for handling layer operations","operationId":"get_project_layers_api_v1_layer__project_id__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/LayerModel"},"type":"array","title":"Response Get Project Layers Api V1 Layer  Project Id  Get"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/layer/{project_id}/upload":{"post":{"tags":["layer"],"summary":"Upload Layer","description":"Upload a CSV or GeoJSON file as a generic sandbox layer.\n\n``ignore_geometry`` is the table-route override: parsed geometries are\ndropped so a geometry-bearing file lands as a plain table.","operationId":"upload_layer_api_v1_layer__project_id__upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_layer_api_v1_layer__project_id__upload_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayerUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/layer/{layer_id}":{"put":{"tags":["layer"],"summary":"Update Layer","description":"Update a layer with the provided data.\n\nArgs:\n    request: Layer update request containing layer ID and fields to update\n    layer_service: Service for handling layer operations\n    enrichment_service: Service for handling enrichment operations\n\nReturns:\n    Response containing success message and updated layer\n\nRaises:\n    HTTPException: If layer not found or no fields provided for update","operationId":"update_layer_api_v1_layer__layer_id__put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayerUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayerUpdateResponse"}}}},"409":{"description":"An enrichment update needs approval before stored rows are re-enriched.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentUpdateConflictResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"delete":{"tags":["layer"],"summary":"Delete Layer","description":"Soft delete a layer.\n\nArgs:\n    request: Layer delete request containing layer ID and project ID\n    layer_service: Service for handling layer operations\n\nReturns:\n    Response containing success message\n\nRaises:\n    HTTPException: If layer not found","operationId":"delete_layer_api_v1_layer__layer_id__delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayerDeleteResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/import/inspect":{"post":{"tags":["import"],"summary":"Inspect Import","description":"Parse an upload once, server-side, and classify it for the detection card.\n\nPre-project (Door 1): no county fence — geometry files get a county\nbreakdown so the client can pre-select a dominant county for confirmation.\n``include_rows`` is the manual-override escape hatch: the user chose the\naddress route on a file detection didn't classify as address-bearing.","operationId":"inspect_import_api_v1_import_inspect_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_inspect_import_api_v1_import_inspect_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportInspectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/import/{project_id}/inspect":{"post":{"tags":["import"],"summary":"Inspect Import For Project","description":"Door 2 inspect: same parse + detection, fenced against the project's county.\n\nGeometry files additionally report how many features fall inside vs outside\n``projects.county_fips`` so the dialog can preview the out-of-scope bucket\nbefore commit.","operationId":"inspect_import_for_project_api_v1_import__project_id__inspect_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_inspect_import_for_project_api_v1_import__project_id__inspect_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportInspectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/import/{project_id}/submit":{"post":{"tags":["import"],"summary":"Submit Import Job For Project","description":"Start a background import into an EXISTING project (Door 2, async).\n\nReturns as soon as the job is durably enqueued so the browser does not own\nthe minutes-long address-resolution wait.","operationId":"submit_import_job_for_project_api_v1_import__project_id__submit_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportSubmitRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportSubmitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/import/jobs/in-flight":{"get":{"tags":["import"],"summary":"List In Flight Import Jobs","description":"The caller's running imports — the safety net under the SSE progress feed.\n\nPolled on a slow cadence only while something is in flight, mirroring the\nenrichment equivalent, because the publish path swallows its own failures.\nNever selects ``working_set``: that column is tens of KB per row and\ninlining it here would detoast every job on every poll.\n\nReclaims stranded rows first. This read is where \"still working\" is\nbelieved, so it is also where a run nobody is working on has to stop being\nbelieved — a lazy fallback at the consumer rather than a sweep, since the\npoll only runs while a client thinks something is in flight.","operationId":"list_in_flight_import_jobs_api_v1_import_jobs_in_flight_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportJobsResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/import/jobs/{job_id}":{"get":{"tags":["import"],"summary":"Get Import Job","description":"One import's durable progress — what a reopened dialog reads.\n\nScoped to the submitting user rather than to the project: the job row is the\nrecord of *this user's* run, and a 404 on someone else's job leaks nothing\nabout whether it exists.","operationId":"get_import_job_api_v1_import_jobs__job_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportJobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/import/jobs/{job_id}/cancel":{"post":{"tags":["import"],"summary":"Cancel Import Job","description":"Ask a running import to stop at its next chunk boundary.\n\nCooperative, never a DBOS hard cancel: the workflow observes the flag and\nfalls through to its normal finalize, so the rows that already resolved are\nstill committed. A hard cancel would skip that finalize entirely.\n\n409 when the job already moved — a lost claim is an answer, not a retry.","operationId":"cancel_import_job_api_v1_import_jobs__job_id__cancel_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportJobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/chat/feedback":{"post":{"tags":["chat"],"summary":"Submit Chat Feedback","description":"Receives and processes feedback for a specific chat message via the ChatService.\n\nArgs:\n    request: The feedback request data.\n    chat_service: The ChatService instance (dependency).\n\nReturns:\n    A confirmation response.\n\nRaises:\n    HTTPException: 400 if saving feedback fails (e.g., invalid data).\n    HTTPException: 500 for unexpected errors.","operationId":"submit_chat_feedback_api_v1_chat_feedback_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFeedbackRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFeedbackResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/chat/models":{"get":{"tags":["chat"],"summary":"List Picker Models","description":"Curated model-picker options for the chat composer dropdown.\n\nServed from the backend registry so the client list cannot drift from the\nkeys ``ChatRequest.selected_model`` validates against. 404s when the\nworkspace's model-picker toggle is off — off means the surface is absent.","operationId":"list_picker_models_api_v1_chat_models_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatModelsResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/chat/{project_id}/attachment":{"post":{"tags":["chat"],"summary":"Upload Chat Attachment","description":"Store one PDF for this project's chat and return its reference.\n\nReturns 404 rather than 403 when the workspace's chat PDF attachment toggle\nis off: off means the API surface is absent, not forbidden.","operationId":"upload_chat_attachment_api_v1_chat__project_id__attachment_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_chat_attachment_api_v1_chat__project_id__attachment_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatAttachmentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/chat/stream":{"post":{"tags":["chat"],"summary":"Chat Main Agent","description":"Receives and processes a streaming chat request via the AgentService.\n\nThis endpoint streams the agent's response in real-time using Server-Sent Events.\n\nArgs:\n    request: The chat request data containing message and project_id (pre-validated).\n    agent_service: The AgentService instance (dependency).\n\nReturns:\n    StreamingResponse with Server-Sent Events containing streaming chat data.\n\nRaises:\n    HTTPException: 400 for validation errors.\n    HTTPException: 404 if project not found or user doesn't own it.\n    HTTPException: 500 for unexpected errors.","operationId":"chat_main_agent_api_v1_chat_stream_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/chat/stream/resume":{"post":{"tags":["chat"],"summary":"Resume Chat Main Agent","description":"Re-attach to a project's in-flight chat run after a mid-stream refresh.\n\nRead-only second reader: tails the existing workflow's durable stream\n(``read_stream`` replays from offset 0 → the full ordered sequence: the\nuser-message echo, every delta so far, then the terminal) WITHOUT starting\na run or claiming a slot. If no run is live the generator yields nothing; the\nFE then sees no terminal and falls back to reloading persisted history (the\nempty replay is the signal that the run finished and released its slot before\nthis reattach).","operationId":"resume_chat_main_agent_api_v1_chat_stream_resume_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatResumeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/chat/chat/interrupt":{"post":{"tags":["chat"],"summary":"Interrupt Chat","description":"Stop an in-flight chat run via the cooperative interrupt flag.\n\nStopping resolves the chat's ``active_workflow_id`` (liveness from the DBOS\nstatus row) and raises the single cooperative stop signal. The workflow\nobserves it at its next node boundary and finalizes normally — persisting\nthe sanitized partial turn, stamping last-edit, capturing the trace, and\nemitting the ``interrupted`` terminal — while in-flight tools observe the\nsame flag at their checkpoints and bail BEFORE committing DB side-effects.\nNo hard DBOS cancel is issued here: a hard cancel skips finalization and is\nonly seen at the next step boundary (tools would commit after Stop); it\nsurvives solely as the run monitor's escalation backstop for wedged runs.\n\nArgs:\n    request: The interrupt request containing project_id and reason (pre-validated).\n\nReturns:\n    ChatInterruptResponse with ``was_active`` True iff a live run was signalled.\n\nRaises:\n    HTTPException: 400 for an invalid project id; 500 for unexpected errors.","operationId":"interrupt_chat_api_v1_chat_chat_interrupt_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatInterruptRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatInterruptResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/chat/schemas":{"get":{"tags":["chat"],"summary":"Expose Schemas","description":"Schema exposure endpoint for OpenAPI/TypeScript generation.\nThis endpoint is never called by the frontend but ensures all chat-related\nschemas are included in the OpenAPI specification for type generation.","operationId":"expose_schemas_api_v1_chat_schemas_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SchemaExposure"}}}}}}},"/api/v1/chat/archives/{project_id}":{"get":{"tags":["chat"],"summary":"Get Chat Archives","description":"Get archive metadata for a project's chat, without message bodies.","operationId":"get_chat_archives_api_v1_chat_archives__project_id__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatArchiveMetadataResponseSchema"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/chat/archives/{project_id}/{archive_id}":{"get":{"tags":["chat"],"summary":"Get Chat Archive Content","description":"Get one archive's message bodies on demand, scoped to the project's chat.\n\nThe archive UUID doubles as a strong ETag (content never changes once\nwritten), so a matching ``If-None-Match`` short-circuits to 304 before the\nexpensive blob read. The validator is client-constructible from the URL,\nso the short-circuit is gated on a cheap existence+scope check — a forged\nvalidator for an out-of-scope or missing archive still 404s. Blob\nvalidation is intentionally skipped on the 304 path: blobs are immutable\nafter write, so a validator for a corrupt archive cannot come from a real\n200, and a fresh (unconditional) read still 422s.","operationId":"get_chat_archive_content_api_v1_chat_archives__project_id___archive_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"archive_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Archive Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArchiveContentResponseSchema"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/map/{layer_id}/tiles/{z}/{x}/{y}.pbf":{"get":{"tags":["map"],"summary":"Get Layer Mvt Tile","description":"Serve an MVT tile for a layer.\n\n``v`` is a client-supplied cache-busting token — change it (e.g., to a\ntimestamp) when you know the underlying data has moved. ``filter_id``\nreferences a server-side FilterSpec (POSTed via ``/filters``); when\npresent, the tile contains only matching rows. Favorites-only filtering\npulls the user's favorite ids inline so the tile WHERE-clause includes\nthem — without that, the tile would visually drop the favorites filter\neven though the table respects it. ``viz`` names a layer column to embed\nas a feature property at every zoom (below the include-all zoom only the\ncore name/owner/address columns ship otherwise) so the client can drive a\nvalue-weighted visualization; unknown columns are dropped silently.","operationId":"get_layer_mvt_tile_api_v1_map__layer_id__tiles__z___x___y__pbf_get","parameters":[{"name":"z","in":"path","required":true,"schema":{"type":"integer","title":"Z"}},{"name":"x","in":"path","required":true,"schema":{"type":"integer","title":"X"}},{"name":"y","in":"path","required":true,"schema":{"type":"integer","title":"Y"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}},{"name":"v","in":"query","required":false,"schema":{"type":"string","default":"0","title":"V"}},{"name":"filter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filter Id"}},{"name":"viz","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Viz"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/map/{layer_id}/agg-tiles/{z}/{x}/{y}.pbf":{"get":{"tags":["map"],"summary":"Get Layer Mvt Agg Tile","description":"Serve an aggregate (bin-count) MVT tile for low-zoom rendering.\n\nEmits one MVT point per occupied grid cell with a ``count`` property —\nthe client renders bubbles sized by count at zoom levels below the\ndetail-layer threshold so panning over dense data doesn't tessellate\ntens of thousands of features the user can't actually see.\n\n``filter_id`` — same as detail tiles; the aggregate counts then reflect\nthe active filter instead of the layer total. Favorites-only resolution\nmatches ``get_layer_mvt_tile`` so agg bubbles count only the favorites\nwhen that toggle is on.","operationId":"get_layer_mvt_agg_tile_api_v1_map__layer_id__agg_tiles__z___x___y__pbf_get","parameters":[{"name":"z","in":"path","required":true,"schema":{"type":"integer","title":"Z"}},{"name":"x","in":"path","required":true,"schema":{"type":"integer","title":"X"}},{"name":"y","in":"path","required":true,"schema":{"type":"integer","title":"Y"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}},{"name":"v","in":"query","required":false,"schema":{"type":"string","default":"0","title":"V"}},{"name":"filter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filter Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/map/{layer_id}/viz-stats":{"get":{"tags":["map"],"summary":"Get Layer Viz Stats","description":"Whole-layer classed-styling stats for one column.\n\nDrives classed map styling on the client — class boundaries for numeric\ncolumns, bucketed categories for boolean/text ones. Either way the scale\nmust come from the full dataset, not the rendered viewport, or the same\nfeature changes class as the user pans.","operationId":"get_layer_viz_stats_api_v1_map__layer_id__viz_stats_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"column","in":"query","required":true,"schema":{"type":"string","maxLength":200,"title":"Column"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/NumericVizStats"},{"$ref":"#/components/schemas/CategoricalVizStats"}],"discriminator":{"propertyName":"kind","mapping":{"numeric":"#/components/schemas/NumericVizStats","categorical":"#/components/schemas/CategoricalVizStats"}},"title":"Response Get Layer Viz Stats Api V1 Map  Layer Id  Viz Stats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/map/{layer_id}/extent":{"get":{"tags":["map"],"summary":"Get Layer Extent","description":"Get the bounding box of a layer's features, optionally filtered.","operationId":"get_layer_extent_api_v1_map__layer_id__extent_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayerExtentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/map/county/{county_fips}/primitives/{z}/{x}/{y}.pbf":{"get":{"tags":["map"],"summary":"Get County Primitive Tile","description":"Serve one county primitive MVT — buildings, places, infrastructure.\n\nProject-independent by design: the query preview paints before a project\nexists, which every ``{layer_id}``-scoped tile route structurally cannot do.\nReads the caller's own workspace sandbox — or, with ``?project_id=``, the\nvalidated project's workspace, so an impersonating admin sees the counties\nthe viewed project can actually paint. Either way no county is exposed\nthat the resolved workspace has not loaded.","operationId":"get_county_primitive_tile_api_v1_map_county__county_fips__primitives__z___x___y__pbf_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"county_fips","in":"path","required":true,"schema":{"type":"string","title":"County Fips"}},{"name":"z","in":"path","required":true,"schema":{"type":"integer","title":"Z"}},{"name":"x","in":"path","required":true,"schema":{"type":"integer","title":"X"}},{"name":"y","in":"path","required":true,"schema":{"type":"integer","title":"Y"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"},{"name":"project_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"}}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/map/county/{county_fips}/primitives/prewarm":{"post":{"tags":["map"],"summary":"Prewarm County Primitives","description":"Render the county's preview tiles into the cache, ahead of any query.\n\nReturns as soon as the work is scheduled: the caller is a county click, and\nthe point is that the render is already finished by the time a query is\nsubmitted. The sandbox target is resolved *before* handing off, because the\nbackground task outlives this request's DB session.","operationId":"prewarm_county_primitives_api_v1_map_county__county_fips__primitives_prewarm_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"county_fips","in":"path","required":true,"schema":{"type":"string","title":"County Fips"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"},{"name":"project_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"}}],"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountyPrewarmResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/map/county/{county_fips}/primitives/match":{"post":{"tags":["map"],"summary":"Match County Primitives","description":"Resolve a prompt to the primitive values it selects, across every table.\n\nReturns filters, not features. The client already holds the county's tiles,\nso a value set is all it needs to repaint — which is why this can be a\nsingle small request on the interactive path instead of a re-render.\n\nUnmatched prompts return no filters rather than a best guess: a preview that\nlights something up for \"asdfghjkl\" is worse than one that stays dark.","operationId":"match_county_primitives_api_v1_map_county__county_fips__primitives_match_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"county_fips","in":"path","required":true,"schema":{"type":"string","title":"County Fips"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"},{"name":"project_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrimitiveMatchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrimitiveMatchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/table/{layer_id}/features/paginated":{"get":{"tags":["table"],"summary":"Get Layer Features Paginated","description":"Paginated features from the workspace sandbox for AG Grid SSR.\n\nQuery params use AG Grid's native camelCase (``startRow``, ``sortModel``,\netc.) to match the ``IServerSideGetRowsRequest`` shape.","operationId":"get_layer_features_paginated_api_v1_table__layer_id__features_paginated_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"startRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Startrow"}},{"name":"endRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"default":100,"title":"Endrow"}},{"name":"sortModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sortmodel"}},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}},{"name":"filterId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filterid"}},{"name":"groupKeys","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupkeys"}},{"name":"rowGroupCols","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rowgroupcols"}},{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"geometry","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geometry"}},{"name":"favoritesOnly","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"Favoritesonly"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedFeaturesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/table/{layer_id}/columns":{"get":{"tags":["table"],"summary":"Get Layer Columns Metadata","description":"Column metadata + aggregate stats for a layer, without fetching row data.","operationId":"get_layer_columns_metadata_api_v1_table__layer_id__columns_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ColumnsMetadataResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/table/{layer_id}/columns/{column_id}/values":{"get":{"tags":["table"],"summary":"Get Column Distinct Values","description":"Distinct values + counts for a column — populates AG Grid's set filter.","operationId":"get_column_distinct_values_api_v1_table__layer_id__columns__column_id__values_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"column_id","in":"path","required":true,"schema":{"type":"string","title":"Column Id"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Search"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"default":500,"title":"Limit"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DistinctValuesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/table/{layer_id}/features/filtered-ids":{"get":{"tags":["table"],"summary":"Get Layer Filtered Ids","description":"Feature ids matching the current filter set, capped by ``limit``.\n\nPowers map filter sync (which features to show on the map given the\ncurrent table filters), spatial polygon filtering (draw polygon →\nfilter table to features inside it), and enrichment targeting (find\nunenriched rows for a given enrichment, capped). ``total`` reflects\nthe full match count regardless of ``limit``.\n\nHonors ``favoritesOnly`` so map-filter sync and enrichment targeting\nstay consistent with the table when the favorites toggle is on.","operationId":"get_layer_filtered_ids_api_v1_table__layer_id__features_filtered_ids_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"enrichmentState","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Enrichmentstate"}},{"name":"enrichmentName","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enrichmentname"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500000,"minimum":1,"default":100000,"title":"Limit"}},{"name":"startRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Startrow"}},{"name":"endRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"default":100,"title":"Endrow"}},{"name":"sortModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sortmodel"}},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}},{"name":"filterId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filterid"}},{"name":"groupKeys","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupkeys"}},{"name":"rowGroupCols","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rowgroupcols"}},{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"geometry","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geometry"}},{"name":"favoritesOnly","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"Favoritesonly"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilteredIdsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/table/{layer_id}/features/filtered-count":{"get":{"tags":["table"],"summary":"Get Layer Filtered Count","description":"Total row count matching the current filter set; no ids materialized.\n\nCounterpart to ``/filtered-ids`` for callers that only need the total —\nskips the sort + id fetch. Backs the column-wide bulk-enrich confirm gate.","operationId":"get_layer_filtered_count_api_v1_table__layer_id__features_filtered_count_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"enrichmentState","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Enrichmentstate"}},{"name":"enrichmentName","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enrichmentname"}},{"name":"startRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Startrow"}},{"name":"endRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"default":100,"title":"Endrow"}},{"name":"sortModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sortmodel"}},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}},{"name":"filterId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filterid"}},{"name":"groupKeys","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupkeys"}},{"name":"rowGroupCols","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rowgroupcols"}},{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"geometry","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geometry"}},{"name":"favoritesOnly","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"Favoritesonly"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilteredCountResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/table/{layer_id}/features/navigate":{"get":{"tags":["table"],"summary":"Navigate Layer Feature","description":"Server-side prev/next cursor for the focused-feature panel.\n\nRuns a single CTE on the current filtered set per call — no cap on\nset size and no client-side id materialization, so navigation works\npast the old 100k boundary. ``wrap`` controls behavior at the\nendpoints (true → loop, false → ``None``).","operationId":"navigate_layer_feature_api_v1_table__layer_id__features_navigate_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"currentId","in":"query","required":true,"schema":{"type":"string","minLength":1,"title":"Currentid"}},{"name":"wrap","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Wrap"}},{"name":"enrichmentState","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Enrichmentstate"}},{"name":"enrichmentName","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enrichmentname"}},{"name":"startRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Startrow"}},{"name":"endRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"default":100,"title":"Endrow"}},{"name":"sortModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sortmodel"}},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}},{"name":"filterId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filterid"}},{"name":"groupKeys","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupkeys"}},{"name":"rowGroupCols","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rowgroupcols"}},{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"geometry","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geometry"}},{"name":"favoritesOnly","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"Favoritesonly"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NavigateCursorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/table/{layer_id}/export":{"get":{"tags":["table"],"summary":"Export Layer Features","description":"Stream the filtered layer rows as CSV or XLSX.\n\nReplaces the page-scoped client-side export for SSR-backed layers.\nRow shaping mirrors ``client/src/components/Table/csvExportUtils.ts``\n— contact/tenant sub-field expansion, reasoning columns, and a\n``Favorited`` column when requested. Exceeding\n``settings.MAX_EXPORT_ROWS``, or the exporting workspace's cumulative\nparcel-export budget, returns 413 before any byte streams.\n\nLicensed-parcel exports additionally tee each streamed row's\n``feature_id`` into the ``layer_export_features`` provenance log,\npersisted by the same completion hook that finalizes the audit row.","operationId":"export_layer_features_api_v1_table__layer_id__export_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"},{"name":"startRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Startrow"}},{"name":"endRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"default":100,"title":"Endrow"}},{"name":"sortModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sortmodel"}},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}},{"name":"filterId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filterid"}},{"name":"groupKeys","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupkeys"}},{"name":"rowGroupCols","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rowgroupcols"}},{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"geometry","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geometry"}},{"name":"favoritesOnly","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"Favoritesonly"}},{"name":"format","in":"query","required":false,"schema":{"anyOf":[{"enum":["csv","xlsx"],"type":"string"},{"type":"null"}],"title":"Format"}},{"name":"columns","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Columns"}},{"name":"includeReasoning","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"Includereasoning"}},{"name":"includeProvenance","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":true,"title":"Includeprovenance"}},{"name":"selectedContactFields","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selectedcontactfields"}},{"name":"includeFavorites","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"Includefavorites"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/table/{layer_id}/feature/{feature_id}":{"get":{"tags":["table"],"summary":"Get Feature Detail","description":"Full properties + GeoJSON geometry for a single feature.\n\nPowers the feature detail panel and ``MapboxService.flyToFeature()``.\nEnrichment wrappers always include ``reasoning`` and ``citations`` when\na sidecar row exists.","operationId":"get_feature_detail_api_v1_table__layer_id__feature__feature_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"feature_id","in":"path","required":true,"schema":{"type":"string","title":"Feature Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/table/{layer_id}/search":{"get":{"tags":["table"],"summary":"Search Layer Features","description":"Case-insensitive substring search across feature display fields.","operationId":"search_layer_features_api_v1_table__layer_id__search_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"title":"Q"}},{"name":"fields","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Fields"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Firebase ID token for MVT authentication","title":"Token"},"description":"Firebase ID token for MVT authentication"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/table/{layer_id}/features":{"post":{"tags":["table"],"summary":"Add Feature To Layer","description":"Add a complete GeoJSON feature to a layer.","operationId":"add_feature_to_layer_api_v1_table__layer_id__features_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureAddRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureAddResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/table/{project_id}/features/from-source":{"post":{"tags":["table"],"summary":"Create Layer From Feature","description":"Create a new typed layer seeded with one Overture feature.\n\nUsed when a nearby-features add targets an Overture table (building/parcel/\nplace) with no layer in the project yet. Idempotent on the feature ref.\n``target_layer_id`` instead adds the feature into that specific existing\nlayer (the chat destination picker).","operationId":"create_layer_from_feature_api_v1_table__project_id__features_from_source_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLayerFromFeatureRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateLayerFromFeatureResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/table/{project_id}/search/{lat}/{lng}":{"get":{"tags":["table"],"summary":"Search Feature","description":"Find a feature by latitude, longitude, or address.","operationId":"search_feature_api_v1_table__project_id__search__lat___lng__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"lat","in":"path","required":true,"schema":{"type":"number","title":"Lat"}},{"name":"lng","in":"path","required":true,"schema":{"type":"number","title":"Lng"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FindFeatureResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/filters":{"post":{"tags":["filters"],"summary":"Create Filter Spec","description":"Create (or return existing) FilterSpec for the given filter shape.\n\nIdempotent: repeated POSTs with the same canonical body return the same\n``filter_id``. Sliding TTL means downstream reads keep the spec alive.","operationId":"create_filter_spec_api_v1_filters_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilterSpecRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilterSpecResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/share/{share_token}/access":{"get":{"tags":["share"],"summary":"Get Share Access","operationId":"get_share_access_api_v1_share__share_token__access_get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/LegacyShareAccessResponse"},{"$ref":"#/components/schemas/GateRequiredShareAccessResponse"},{"$ref":"#/components/schemas/AcceptedShareAccessResponse"}],"title":"Response Get Share Access Api V1 Share  Share Token  Access Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/accept":{"post":{"tags":["share"],"summary":"Accept Share Access","operationId":"accept_share_access_api_v1_share__share_token__accept_post","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareAcceptanceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareAcceptanceResponse"}}}},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareAcceptanceRejectedResponse"}}},"description":"Conflict"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/teaser/tiles/{z}/{x}/{y}.pbf":{"get":{"tags":["share"],"summary":"Get Share Teaser Tile","operationId":"get_share_teaser_tile_api_v1_share__share_token__teaser_tiles__z___x___y__pbf_get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"z","in":"path","required":true,"schema":{"type":"integer","title":"Z"}},{"name":"x","in":"path","required":true,"schema":{"type":"integer","title":"X"}},{"name":"y","in":"path","required":true,"schema":{"type":"integer","title":"Y"}},{"name":"v","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"deprecated":true,"title":"V"},"deprecated":true}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}":{"get":{"tags":["share"],"summary":"Get Shared Project","description":"Get metadata for a shared project (read-only, no side effects).\n\nThis is the primary entry point for shared project access. Validates\nthe share token and returns project metadata. View count tracking is\nhandled separately via POST /{share_token}/view.\n\nArgs:\n    share: Validated ProjectShare from token (injected by validate_share_token)\n    share_service: ProjectShareService for fetching project data\n\nReturns:\n    Shared project metadata (subset of full project data)\n\nRaises:\n    HTTPException: 404 if project not found","operationId":"get_shared_project_api_v1_share__share_token__get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SharedProjectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/view":{"post":{"tags":["share"],"summary":"Track Share View","description":"Increment the view count for a shared project.\n\nCalled by the frontend once per browser session to track views.\nSeparated from the GET endpoint to avoid double-counting from\nReact StrictMode's double-mount cycle.\n\nArgs:\n    share: Validated ProjectShare from token\n    share_service: ProjectShareService for view count operations\n\nReturns:\n    Success confirmation","operationId":"track_share_view_api_v1_share__share_token__view_post","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShareViewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers":{"get":{"tags":["share"],"summary":"Get Shared Project Layers","description":"Get all layers for a shared project.\n\nArgs:\n    share: Validated ProjectShare from token\n    layer_service: Service for fetching layer data\n\nReturns:\n    List of layers in API format (excludes soft-deleted and\n    parcel-restricted layers)","operationId":"get_shared_project_layers_api_v1_share__share_token__layers_get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"anyOf":[{"$ref":"#/components/schemas/LayerModel"},{"$ref":"#/components/schemas/SharedLayerModel"}]},"title":"Response Get Shared Project Layers Api V1 Share  Share Token  Layers Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/enrichments":{"get":{"tags":["share"],"summary":"Get Shared Project Enrichments","description":"Get enrichment metadata for a shared project (slim, read-only).\n\nReturns only the fields needed for column mapping (id, name, layer_id,\nis_data_source, dtype). Excludes sensitive fields like params, tool,\nand description. Enrichments on share-restricted (parcel) layers are\ndropped — the layer is hidden, so its enrichment metadata must be too.\n\nArgs:\n    share: Validated ProjectShare from token\n    enrichment_repo: Repository for fetching enrichment data\n    layer_service: Service resolving which layers are share-restricted\n\nReturns:\n    Slim enrichment metadata for visible enrichments on non-restricted layers","operationId":"get_shared_project_enrichments_api_v1_share__share_token__enrichments_get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SharedEnrichmentListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/filters":{"post":{"tags":["share"],"summary":"Create Shared Filter Spec","description":"Share-mode twin of ``POST /filters`` — anonymous viewers create the\nFilterSpec their tile / paginated / count requests will dereference.\n\nWithout this, share-mode clients had no path to a ``filter_id``: the\nauthed ``POST /filters`` blocks on Firebase auth that share viewers don't\nhave, so polygon and column filters never synced to map tiles on shared\ndashboards. ``favoritesOnly`` is rejected up front — share mode has no\nuser identity to resolve favorites against (matches\n``_reject_favorites_in_share_mode``).","operationId":"create_shared_filter_spec_api_v1_share__share_token__filters_post","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilterSpecRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilterSpecResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers/{layer_id}/tiles/{z}/{x}/{y}.pbf":{"get":{"tags":["share"],"summary":"Get Shared Layer Mvt Tile","description":"Serve an MVT tile for a layer in a shared project (anonymous access).\n\n``filter_id`` references a server-side FilterSpec; when present, the\ntile contains only matching rows. ``viz`` is the share-mode twin of the\nauthed tile endpoint's param — it names a layer column to embed so\nclassed styling has values below the include-all zoom.","operationId":"get_shared_layer_mvt_tile_api_v1_share__share_token__layers__layer_id__tiles__z___x___y__pbf_get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"z","in":"path","required":true,"schema":{"type":"integer","title":"Z"}},{"name":"x","in":"path","required":true,"schema":{"type":"integer","title":"X"}},{"name":"y","in":"path","required":true,"schema":{"type":"integer","title":"Y"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}},{"name":"filter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filter Id"}},{"name":"viz","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Viz"}},{"name":"v","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"deprecated":true,"title":"V"},"deprecated":true}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers/{layer_id}/agg-tiles/{z}/{x}/{y}.pbf":{"get":{"tags":["share"],"summary":"Get Shared Layer Mvt Agg Tile","description":"Serve an aggregate MVT tile for a layer in a shared project.\n\n``filter_id`` — share-mode twin of the auth-side agg-tile endpoint;\ncounts only matching rows when present.","operationId":"get_shared_layer_mvt_agg_tile_api_v1_share__share_token__layers__layer_id__agg_tiles__z___x___y__pbf_get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"z","in":"path","required":true,"schema":{"type":"integer","title":"Z"}},{"name":"x","in":"path","required":true,"schema":{"type":"integer","title":"X"}},{"name":"y","in":"path","required":true,"schema":{"type":"integer","title":"Y"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}},{"name":"filter_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filter Id"}},{"name":"v","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"deprecated":true,"title":"V"},"deprecated":true}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers/{layer_id}/viz-stats":{"get":{"tags":["share"],"summary":"Get Shared Layer Viz Stats","description":"Share-mode twin of ``GET /map/{layer_id}/viz-stats``.\n\nShared views persist ``layerViz``, so anonymous viewers need the same\nwhole-layer classed-styling stats the owner gets.","operationId":"get_shared_layer_viz_stats_api_v1_share__share_token__layers__layer_id__viz_stats_get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}},{"name":"column","in":"query","required":true,"schema":{"type":"string","maxLength":200,"title":"Column"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/NumericVizStats"},{"$ref":"#/components/schemas/CategoricalVizStats"}],"discriminator":{"propertyName":"kind","mapping":{"numeric":"#/components/schemas/NumericVizStats","categorical":"#/components/schemas/CategoricalVizStats"}},"title":"Response Get Shared Layer Viz Stats Api V1 Share  Share Token  Layers  Layer Id  Viz Stats Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers/{layer_id}/extent":{"get":{"tags":["share"],"summary":"Get Shared Layer Extent","description":"Bounding box of a shared layer's features (anonymous access).","operationId":"get_shared_layer_extent_api_v1_share__share_token__layers__layer_id__extent_get","parameters":[{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}},{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LayerExtentResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers/{layer_id}/feature/{feature_id}":{"get":{"tags":["share"],"summary":"Get Shared Feature Detail","description":"Full properties + GeoJSON geometry for a single feature in a shared layer.","operationId":"get_shared_feature_detail_api_v1_share__share_token__layers__layer_id__feature__feature_id__get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"feature_id","in":"path","required":true,"schema":{"type":"string","title":"Feature Id"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers/{layer_id}/features/paginated":{"get":{"tags":["share"],"summary":"Get Shared Layer Features Paginated","description":"Share-scoped AG Grid SSR paginated features. Mirrors the authenticated\npath in ``table_handlers.get_layer_features_paginated`` but guards with the\nshare token + verifies the layer belongs to the shared project.","operationId":"get_shared_layer_features_paginated_api_v1_share__share_token__layers__layer_id__features_paginated_get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}},{"name":"startRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Startrow"}},{"name":"endRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"default":100,"title":"Endrow"}},{"name":"sortModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sortmodel"}},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}},{"name":"filterId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filterid"}},{"name":"groupKeys","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupkeys"}},{"name":"rowGroupCols","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rowgroupcols"}},{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"geometry","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geometry"}},{"name":"favoritesOnly","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"Favoritesonly"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedFeaturesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers/{layer_id}/features/filtered-ids":{"get":{"tags":["share"],"summary":"Get Shared Layer Filtered Ids","description":"Share-scoped feature ids matching the current filter set.\n\nMirrors ``table_handlers.get_layer_filtered_ids`` but guards with the\nshare token + verifies the layer belongs to the shared project. Powers\nmap-filter sync and spatial polygon filtering on shared dashboards.","operationId":"get_shared_layer_filtered_ids_api_v1_share__share_token__layers__layer_id__features_filtered_ids_get","parameters":[{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}},{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"enrichmentState","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Enrichmentstate"}},{"name":"enrichmentName","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enrichmentname"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500000,"minimum":1,"default":100000,"title":"Limit"}},{"name":"startRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Startrow"}},{"name":"endRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"default":100,"title":"Endrow"}},{"name":"sortModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sortmodel"}},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}},{"name":"filterId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filterid"}},{"name":"groupKeys","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupkeys"}},{"name":"rowGroupCols","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rowgroupcols"}},{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"geometry","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geometry"}},{"name":"favoritesOnly","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"Favoritesonly"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilteredIdsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers/{layer_id}/features/filtered-count":{"get":{"tags":["share"],"summary":"Get Shared Layer Filtered Count","description":"Share-scoped total row count matching the current filter set.\n\nMirrors ``table_handlers.get_layer_filtered_count`` but guards with the\nshare token + verifies the layer belongs to the shared project.","operationId":"get_shared_layer_filtered_count_api_v1_share__share_token__layers__layer_id__features_filtered_count_get","parameters":[{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}},{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"enrichmentState","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Enrichmentstate"}},{"name":"enrichmentName","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enrichmentname"}},{"name":"startRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Startrow"}},{"name":"endRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"default":100,"title":"Endrow"}},{"name":"sortModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sortmodel"}},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}},{"name":"filterId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filterid"}},{"name":"groupKeys","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupkeys"}},{"name":"rowGroupCols","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rowgroupcols"}},{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"geometry","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geometry"}},{"name":"favoritesOnly","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"Favoritesonly"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilteredCountResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers/{layer_id}/features/navigate":{"get":{"tags":["share"],"summary":"Get Shared Layer Navigate","description":"Share-scoped prev/next cursor for shared dashboards. Mirrors\n``table_handlers.navigate_layer_feature`` — single CTE per call,\ncap-free up to whatever the filtered set contains.","operationId":"get_shared_layer_navigate_api_v1_share__share_token__layers__layer_id__features_navigate_get","parameters":[{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}},{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"currentId","in":"query","required":true,"schema":{"type":"string","minLength":1,"title":"Currentid"}},{"name":"wrap","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Wrap"}},{"name":"enrichmentState","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Enrichmentstate"}},{"name":"enrichmentName","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enrichmentname"}},{"name":"startRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"default":0,"title":"Startrow"}},{"name":"endRow","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","exclusiveMinimum":0},{"type":"null"}],"default":100,"title":"Endrow"}},{"name":"sortModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sortmodel"}},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}},{"name":"filterId","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filterid"}},{"name":"groupKeys","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Groupkeys"}},{"name":"rowGroupCols","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rowgroupcols"}},{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"geometry","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geometry"}},{"name":"favoritesOnly","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"Favoritesonly"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NavigateCursorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers/{layer_id}/columns":{"get":{"tags":["share"],"summary":"Get Shared Layer Columns Metadata","description":"Share-scoped column metadata + aggregate stats. Mirrors\n``table_handlers.get_layer_columns_metadata`` with a share-token guard.","operationId":"get_shared_layer_columns_metadata_api_v1_share__share_token__layers__layer_id__columns_get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ColumnsMetadataResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/layers/{layer_id}/columns/{column_id}/values":{"get":{"tags":["share"],"summary":"Get Shared Column Distinct Values","operationId":"get_shared_column_distinct_values_api_v1_share__share_token__layers__layer_id__columns__column_id__values_get","parameters":[{"name":"column_id","in":"path","required":true,"schema":{"type":"string","title":"Column Id"}},{"name":"layer_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Layer Id"}},{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}},{"name":"searchText","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":5000,"minimum":1,"default":500,"title":"Limit"}},{"name":"filterModel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filtermodel"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DistinctValuesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/views":{"get":{"tags":["share"],"summary":"Get Shared Project Views","description":"Get all views for a shared project.\n\nPer-view state is keyed by layer id (filters, column visibility/order,\nlayer visibility), so state for share-restricted (parcel) layers is\nstripped from each view — otherwise a shared view leaks the parcel\nlayer's column keys and the user's filter values even though the layer\nis omitted from the shared layer list.\n\nArgs:\n    share: Validated ProjectShare from token\n    share_service: ProjectShareService for fetching view data\n    layer_service: Service resolving which layers are share-restricted\n\nReturns:\n    List of views with filters converted to client display units\n\nRaises:\n    HTTPException: 404 if project not found","operationId":"get_shared_project_views_api_v1_share__share_token__views_get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ViewsGetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/share/{share_token}/chats":{"get":{"tags":["share"],"summary":"Get Shared Project Chats","description":"Get chat history for a shared project (read-only).\n\nThe anonymous share wire keeps only user and assistant prose, user attribution,\nand message timestamps. It removes thinking, instructions, retry and tool parts,\nrun and provider fields, and private metadata. Assistant prose is not scanned for\nincidental parcel mentions because parsing free-form model text is unreliable and\noutside this restriction's scope.\n\nArgs:\n    share: Validated ProjectShare from token\n    share_service: ProjectShareService for fetching chat data\n\nReturns:\n    Prose-only chat history, or None if no chat exists","operationId":"get_shared_project_chats_api_v1_share__share_token__chats_get","parameters":[{"name":"share_token","in":"path","required":true,"schema":{"type":"string","title":"Share Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatHistoryResponseSchema"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workspace/discovery-allowance/warning-claim":{"post":{"tags":["workspace"],"summary":"Claim Discovery Allowance Warning","operationId":"claim_discovery_allowance_warning_api_v1_workspace_discovery_allowance_warning_claim_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoveryAllowanceWarningClaimResponse"}}}},"401":{"description":"Unauthenticated"},"403":{"description":"Forbidden"}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/workspace/discovery-allowance/request":{"post":{"tags":["workspace"],"summary":"Request Discovery Allowance","operationId":"request_discovery_allowance_api_v1_workspace_discovery_allowance_request_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoveryAllowanceRequestResponse"}}}},"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoveryAllowanceRequestResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/workspace/discovery-allowance/request/{interaction_id}":{"post":{"tags":["workspace"],"summary":"Resume Discovery Allowance Request","operationId":"resume_discovery_allowance_request_api_v1_workspace_discovery_allowance_request__interaction_id__post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"interaction_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Interaction Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoveryAllowanceRequestResponse"}}}},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoveryAllowanceRequestResponse"}}},"description":"Accepted"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workspace":{"get":{"tags":["workspace"],"summary":"Get Workspace","description":"Get current user's workspace details including credits and member count.","operationId":"get_workspace_api_v1_workspace_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"patch":{"tags":["workspace"],"summary":"Update Workspace","description":"Update workspace settings. Requires workspace admin for the name field.\n\nAll fields are optional. Only provided fields are updated.","operationId":"update_workspace_api_v1_workspace_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/workspace/members":{"get":{"tags":["workspace"],"summary":"Get Workspace Members","description":"List all members of the current user's workspace.","operationId":"get_workspace_members_api_v1_workspace_members_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"sort_by","in":"query","required":false,"schema":{"enum":["name","joined"],"type":"string","description":"Sort members by 'name' (alphabetical) or 'joined' (newest first)","default":"name","title":"Sort By"},"description":"Sort members by 'name' (alphabetical) or 'joined' (newest first)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceMembersResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workspace/members/{user_id}/role":{"patch":{"tags":["workspace"],"summary":"Update Member Role","description":"Update a workspace member's role. Requires workspace admin.\n\nCan change between 'writer' and 'reader' roles. Cannot change your own role.","operationId":"update_member_role_api_v1_workspace_members__user_id__role_patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberRoleUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceMemberResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workspace/dial-template-variables":{"get":{"tags":["workspace"],"summary":"List Dial Template Variables","description":"Return variables usable inside `dial_agent_settings` override fields.","operationId":"list_dial_template_variables_api_v1_workspace_dial_template_variables_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialTemplateVariablesResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/workspace/dial-agent-settings":{"patch":{"tags":["workspace"],"summary":"Update Dial Agent Settings","description":"Replace the workspace's dial agent prompt overrides.\n\nWhole-blob replace: clients send the desired state for every field they\nwant to keep (omit a field → it's removed; explicit `null` → also removed).\nThe dispatch path treats null/missing identically — both fall through to\nthe Retell flow node's baked-in default — so we don't preserve the\ndistinction in storage.","operationId":"update_dial_agent_settings_api_v1_workspace_dial_agent_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialAgentSettingsUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/workspace/transfer-destinations":{"get":{"tags":["workspace"],"summary":"List Transfer Destinations","operationId":"list_transfer_destinations_api_v1_workspace_transfer_destinations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferDestinationListResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"post":{"tags":["workspace"],"summary":"Create Transfer Destination","description":"Create a workspace transfer destination.","operationId":"create_transfer_destination_api_v1_workspace_transfer_destinations_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferDestinationCreateRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferDestinationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/workspace/transfer-destinations/{destination_id}":{"patch":{"tags":["workspace"],"summary":"Update Transfer Destination","description":"Update a workspace transfer destination.","operationId":"update_transfer_destination_api_v1_workspace_transfer_destinations__destination_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"destination_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Destination Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferDestinationUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TransferDestinationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["workspace"],"summary":"Delete Transfer Destination","description":"Delete a workspace transfer destination.","operationId":"delete_transfer_destination_api_v1_workspace_transfer_destinations__destination_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"destination_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Destination Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workspace/dial-usage/current":{"get":{"tags":["workspace"],"summary":"Get Dial Usage Current","description":"Current month's auto-dial usage for the user's workspace.","operationId":"get_dial_usage_current_api_v1_workspace_dial_usage_current_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialUsageResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/catalog":{"get":{"tags":["catalog"],"summary":"Get Catalog","operationId":"get_catalog_api_v1_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CatalogResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/query/parse":{"post":{"tags":["query"],"summary":"Parse User Query","description":"Parse a user query in real-time, returning structured layer identification.\n\nThis is a lightweight, stateless endpoint designed for debounced calls\nas the user types, powering the live preview chips on the Canvas empty state.","operationId":"parse_user_query_api_v1_query_parse_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryParseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryParseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/notes/{project_id}/{feature_id}":{"get":{"tags":["notes"],"summary":"Get Feature Notes","description":"Get all notes for a feature.","operationId":"get_feature_notes_api_v1_notes__project_id___feature_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"feature_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"title":"Feature Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FeatureNoteResponse"},"title":"Response Get Feature Notes Api V1 Notes  Project Id   Feature Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["notes"],"summary":"Create Feature Note","description":"Create a new note on a feature. One note per user per feature per source.","operationId":"create_feature_note_api_v1_notes__project_id___feature_id__post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"feature_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"title":"Feature Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureNoteContentRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureNoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notes/{project_id}/{note_id}":{"patch":{"tags":["notes"],"summary":"Update Feature Note","description":"Update a note's content. Only the author can update.","operationId":"update_feature_note_api_v1_notes__project_id___note_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Note Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureNoteContentRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureNoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["notes"],"summary":"Delete Feature Note","description":"Delete a note. Only the author can delete their own notes.","operationId":"delete_feature_note_api_v1_notes__project_id___note_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"note_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Note Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"boolean"},"title":"Response Delete Feature Note Api V1 Notes  Project Id   Note Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/favorite/{project_id}":{"get":{"tags":["favorite"],"summary":"Get Project Favorites","description":"Get current user's favorited feature IDs for a project.","operationId":"get_project_favorites_api_v1_favorite__project_id__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array","title":"Response Get Project Favorites Api V1 Favorite  Project Id  Get"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/favorite/{project_id}/{feature_id}":{"post":{"tags":["favorite"],"summary":"Toggle Favorite","description":"Toggle a row favorite. Returns the new favorited state.\n\nThe body is optional, and must stay so: ``deploy-full`` ships the client\nbefore the API and a loaded tab keeps its old bundle indefinitely, so a\nrequired body would 422 every favorite click in that tab until the user\nhappens to reload. It carries analytics context only and must never feed an\nauthorization decision — this route admits ``AccessLevel.READ`` callers.","operationId":"toggle_favorite_api_v1_favorite__project_id___feature_id__post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"feature_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":64,"title":"Feature Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/FavoriteToggleContext"},{"type":"null"}],"title":"Context"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoriteToggleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/exclusions/{project_id}":{"get":{"tags":["exclusions"],"summary":"Get Project Exclusions","description":"Excluded feature ids for a project.\n\nExclusions are shared project state, so reads stay at READ access — a\nread-only collaborator still needs the excluded set to render a table that\nmatches what the server serves.","operationId":"get_project_exclusions_api_v1_exclusions__project_id__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"type":"string"},"type":"array","title":"Response Get Project Exclusions Api V1 Exclusions  Project Id  Get"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"post":{"tags":["exclusions"],"summary":"Bulk Exclude","description":"Exclude rows project-wide.\n\nWRITE access, unlike favorites' READ-level toggle: an exclusion disappears\nthe row for every collaborator and share-link viewer, so a read-only user\nmust not be able to mutate the set.","operationId":"bulk_exclude_api_v1_exclusions__project_id__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkExclusionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkExclusionResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/exclusions/{project_id}/records":{"get":{"tags":["exclusions"],"summary":"Get Project Exclusion Records","description":"Excluded-bin records (audit provenance), newest first.","operationId":"get_project_exclusion_records_api_v1_exclusions__project_id__records_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/RowExclusionRecord"},"type":"array","title":"Response Get Project Exclusion Records Api V1 Exclusions  Project Id  Records Get"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/exclusions/{project_id}/restore":{"post":{"tags":["exclusions"],"summary":"Bulk Restore","description":"Restore previously excluded rows.","operationId":"bulk_restore_api_v1_exclusions__project_id__restore_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkExclusionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkExclusionResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/saved-contacts/{project_id}/contacts":{"get":{"tags":["saved-contacts"],"summary":"List Contacts","operationId":"list_contacts_api_v1_saved_contacts__project_id__contacts_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"layer_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Layer Id"}},{"name":"favorites_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Favorites Only"}},{"name":"sort_by","in":"query","required":false,"schema":{"type":"string","default":"created_at","title":"Sort By"}},{"name":"sort_dir","in":"query","required":false,"schema":{"type":"string","default":"desc","title":"Sort Dir"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedContactListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["saved-contacts"],"summary":"Save Contact","operationId":"save_contact_api_v1_saved_contacts__project_id__contacts_post","security":[{"FirebaseAuthMiddleware":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveContactRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedContactResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/saved-contacts/{project_id}/contacts/check":{"get":{"tags":["saved-contacts"],"summary":"Check Saved Contacts","operationId":"check_saved_contacts_api_v1_saved_contacts__project_id__contacts_check_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"feature_ids","in":"query","required":false,"schema":{"type":"string","default":"","title":"Feature Ids"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactCheckResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/saved-contacts/{project_id}/contacts/export":{"get":{"tags":["saved-contacts"],"summary":"Export Contacts","operationId":"export_contacts_api_v1_saved_contacts__project_id__contacts_export_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/saved-contacts/{project_id}/contacts/{contact_id}":{"get":{"tags":["saved-contacts"],"summary":"Get Contact Detail","operationId":"get_contact_detail_api_v1_saved_contacts__project_id__contacts__contact_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contact Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedContactDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["saved-contacts"],"summary":"Update Contact","operationId":"update_contact_api_v1_saved_contacts__project_id__contacts__contact_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contact Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedContactResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["saved-contacts"],"summary":"Delete Contact","operationId":"delete_contact_api_v1_saved_contacts__project_id__contacts__contact_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contact Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"boolean"},"title":"Response Delete Contact Api V1 Saved Contacts  Project Id  Contacts  Contact Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/saved-contacts/{project_id}/contacts/{contact_id}/status":{"patch":{"tags":["saved-contacts"],"summary":"Update Contact Status","operationId":"update_contact_status_api_v1_saved_contacts__project_id__contacts__contact_id__status_patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contact Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactStatusRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedContactResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/saved-contacts/{project_id}/contacts/{contact_id}/notes":{"post":{"tags":["saved-contacts"],"summary":"Add Contact Note","operationId":"add_contact_note_api_v1_saved_contacts__project_id__contacts__contact_id__notes_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contact Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddContactNoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedContactNoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/saved-contacts/{project_id}/contacts/{contact_id}/notes/{note_id}":{"patch":{"tags":["saved-contacts"],"summary":"Update Contact Note","operationId":"update_contact_note_api_v1_saved_contacts__project_id__contacts__contact_id__notes__note_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contact Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Note Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactNoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedContactNoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["saved-contacts"],"summary":"Delete Contact Note","operationId":"delete_contact_note_api_v1_saved_contacts__project_id__contacts__contact_id__notes__note_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contact Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Note Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"boolean"},"title":"Response Delete Contact Note Api V1 Saved Contacts  Project Id  Contacts  Contact Id  Notes  Note Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dial/{project_id}/contacts/{contact_id}":{"post":{"tags":["dial"],"summary":"Start Dial","operationId":"start_dial_api_v1_dial__project_id__contacts__contact_id__post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contact Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartDialRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialCallResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dial/{project_id}/contacts/{contact_id}/calls":{"get":{"tags":["dial"],"summary":"List Calls","operationId":"list_calls_api_v1_dial__project_id__contacts__contact_id__calls_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"contact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Contact Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialCallListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dial/{project_id}/campaigns":{"post":{"tags":["dial"],"summary":"Start Campaign","operationId":"start_campaign_api_v1_dial__project_id__campaigns_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartCampaignRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialCampaignResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["dial"],"summary":"List Campaigns","operationId":"list_campaigns_api_v1_dial__project_id__campaigns_get","security":[{"FirebaseAuthMiddleware":[]}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialCampaignListResponse"}}}}}}},"/api/v1/dial/{project_id}/campaigns/{campaign_id}/pause":{"post":{"tags":["dial"],"summary":"Pause Campaign","operationId":"pause_campaign_api_v1_dial__project_id__campaigns__campaign_id__pause_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialCampaignResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dial/{project_id}/campaigns/{campaign_id}/resume":{"post":{"tags":["dial"],"summary":"Resume Campaign","operationId":"resume_campaign_api_v1_dial__project_id__campaigns__campaign_id__resume_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialCampaignResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dial/{project_id}/campaigns/{campaign_id}/cancel":{"post":{"tags":["dial"],"summary":"Cancel Campaign","operationId":"cancel_campaign_api_v1_dial__project_id__campaigns__campaign_id__cancel_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialCampaignResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dial/{project_id}/campaigns/{campaign_id}":{"get":{"tags":["dial"],"summary":"Get Campaign Detail","operationId":"get_campaign_detail_api_v1_dial__project_id__campaigns__campaign_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DialCampaignDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dial/webhooks/retell/{workspace_id}":{"post":{"tags":["dial"],"summary":"Retell Webhook","operationId":"retell_webhook_api_v1_dial_webhooks_retell__workspace_id__post","parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/audit-log/":{"get":{"tags":["internal","audit-log"],"summary":"List Audit Log","description":"List admin audit log entries with optional filters.\n\nBoth from_date and to_date are inclusive. Because the client sends bare dates\n(parsed by FastAPI as midnight UTC), to_date is shifted to end-of-day so that\nentries logged any time on the selected date are included.","operationId":"list_audit_log_api_v1_internal_audit_log__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"target_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Type"}},{"name":"admin_user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Admin User Id"}},{"name":"target_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Id"}},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action"}},{"name":"from_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"From Date"}},{"name":"to_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"To Date"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAuditLogListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/self-serve/admit":{"post":{"tags":["internal","self-serve"],"summary":"Admit Account","description":"Admit an address, or attach it to the setup it already has.\n\nRe-entrant: an account already ready, in flight, or waitlisted comes back as\nit stands rather than starting a second setup.","operationId":"admit_account_api_v1_internal_self_serve_admit_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdmitAccountRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdmitAccountResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/self-serve/settings":{"get":{"tags":["internal","self-serve"],"summary":"Get Admission Controls","description":"The public operator controls and the capacity they govern.","operationId":"get_admission_controls_api_v1_internal_self_serve_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperatorControlsResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"patch":{"tags":["internal","self-serve"],"summary":"Set Admission Controls","description":"Update the stated public controls, effective for the next request.\n\nReturns the refreshed controls so the caller confirms the new state without\na second round-trip.","operationId":"set_admission_controls_api_v1_internal_self_serve_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOperatorControlsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperatorControlsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/self-serve/waitlist":{"get":{"tags":["internal","self-serve"],"summary":"List Waitlist","description":"Who is waiting and since when, in the order the operator asked for.","operationId":"list_waitlist_api_v1_internal_self_serve_waitlist_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"sort","in":"query","required":false,"schema":{"$ref":"#/components/schemas/WaitlistSort","default":"longest_wait"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaitlistPageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/self-serve/setups":{"get":{"tags":["internal","self-serve"],"summary":"List Setups Needing Attention","description":"Admitted accounts still running, failed, or never told, newest first.\n\nThe waitlist answers who is waiting; this answers what happened to the\npeople who stopped waiting, which nothing else on the screen shows.","operationId":"list_setups_needing_attention_api_v1_internal_self_serve_setups_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"view","in":"query","required":false,"schema":{"$ref":"#/components/schemas/SetupFilter","default":"all"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/self-serve/waitlist/admit":{"post":{"tags":["internal","self-serve"],"summary":"Admit From Waitlist","description":"Admit a named waiting person, consuming a seat from the same cap.\n\nNot gated by the admissions pause — an operator hand-picking someone is the\nexception that control exists to allow — but the cap still binds, so a full\ncohort refuses.","operationId":"admit_from_waitlist_api_v1_internal_self_serve_waitlist_admit_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdmitAccountRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdmitAccountResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/example-projects/":{"get":{"tags":["internal","example-projects"],"summary":"List Example Projects","description":"List all example projects ordered by created_at.","operationId":"list_example_projects_api_v1_internal_example_projects__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminExampleProjectListResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/example-projects/search":{"get":{"tags":["internal","example-projects"],"summary":"Search Projects","description":"List created projects in the admin's workspace for mark-as-example picker.","operationId":"search_projects_api_v1_internal_example_projects_search_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProjectSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/example-projects/search-all":{"get":{"tags":["internal","example-projects"],"summary":"Search All Projects","description":"List created projects across all workspaces for the admin duplicate-any picker.","operationId":"search_all_projects_api_v1_internal_example_projects_search_all_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Q"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProjectSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/example-projects/{project_id}/mark-example":{"post":{"tags":["internal","example-projects"],"summary":"Mark As Example","description":"Mark a project as an example project.","operationId":"mark_as_example_api_v1_internal_example_projects__project_id__mark_example_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminExampleProjectListItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/example-projects/{project_id}/unmark-example":{"post":{"tags":["internal","example-projects"],"summary":"Unmark As Example","description":"Unmark a project as an example (sets visibility to private).","operationId":"unmark_as_example_api_v1_internal_example_projects__project_id__unmark_example_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminExampleProjectListItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/example-projects/{project_id}/duplicate":{"post":{"tags":["internal","example-projects"],"summary":"Duplicate Example Project","description":"Deliver a curated project to a workspace.\n\nDelivery is a durable cross-Neon-branch workflow: the response carries a\n``workflow_id`` and the client tracks progress via the Recent duplications\npanel (which polls the per-row status).","operationId":"duplicate_example_project_api_v1_internal_example_projects__project_id__duplicate_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminDuplicateProjectRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminDuplicateProjectResponse"}}}},"409":{"description":"The project has no assigned county or the target workspace hasn't loaded it; re-submit with acknowledge_missing_counties=true to deliver anyway.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MissingCountyCoverageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/example-projects/duplicate/{workflow_id}/status":{"get":{"tags":["internal","example-projects"],"summary":"Get Duplicate Status","description":"Poll a cross-branch delivery workflow's terminal state.","operationId":"get_duplicate_status_api_v1_internal_example_projects_duplicate__workflow_id__status_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workflow_id","in":"path","required":true,"schema":{"type":"string","title":"Workflow Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminDeliveryStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/example-projects/duplications/recent":{"get":{"tags":["internal","example-projects"],"summary":"List Recent Duplications","description":"Recent duplications (newest first) for the admin tracker panel.","operationId":"list_recent_duplications_api_v1_internal_example_projects_duplications_recent_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminDuplicationLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/example-projects/{project_id}/preview":{"get":{"tags":["internal","example-projects"],"summary":"Get Project Preview","description":"Get project preview with metadata and layer summary.","operationId":"get_project_preview_api_v1_internal_example_projects__project_id__preview_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProjectPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/feature-flags/":{"get":{"tags":["internal","feature-flags"],"summary":"List Feature Flags","description":"List every registered feature toggle with its global default + override count.","operationId":"list_feature_flags_api_v1_internal_feature_flags__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalFeatureFlagsResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/feature-flags/{key}/overrides":{"get":{"tags":["internal","feature-flags"],"summary":"List Feature Overrides","description":"List the workspaces that override one feature (deviate from the global\ndefault), with each workspace's current value. Internal admin only.","operationId":"list_feature_overrides_api_v1_internal_feature_flags__key__overrides_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureOverridesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["internal","feature-flags"],"summary":"Reset Feature Overrides","description":"Clear every per-workspace override for one feature. Internal admin only.","operationId":"reset_feature_overrides_api_v1_internal_feature_flags__key__overrides_delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetFeatureOverridesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/feature-flags/{key}/default":{"patch":{"tags":["internal","feature-flags"],"summary":"Set Global Feature Default","description":"Set the platform-wide default for one feature. Internal admin only.\n\nReturns the refreshed flag list so the client reflects the new default\nwithout a second round-trip.","operationId":"set_global_feature_default_api_v1_internal_feature_flags__key__default_patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetGlobalFlagDefaultRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalFeatureFlagsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/geographies/":{"get":{"tags":["internal","geographies"],"summary":"List Available Geographies","description":"Return US states with parcel coverage.","operationId":"list_available_geographies_api_v1_internal_geographies__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GeographyOptionsResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/parcel-coverage/":{"get":{"tags":["internal","parcel-coverage"],"summary":"List Covered Counties","description":"Return every covered county for the internal coverage map.","operationId":"list_covered_counties_api_v1_internal_parcel_coverage__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParcelCoverageResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/icp-categories":{"get":{"tags":["internal","icp-categories"],"summary":"List Icp Categories","description":"List every ICP category with its dependency counts, ordered by name.","operationId":"list_icp_categories_api_v1_internal_icp_categories_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IcpCategoryListResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"post":{"tags":["internal","icp-categories"],"summary":"Create Icp Category","description":"Create an ICP category.","operationId":"create_icp_category_api_v1_internal_icp_categories_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IcpCategoryWriteRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IcpCategoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/icp-categories/{category_id}":{"patch":{"tags":["internal","icp-categories"],"summary":"Rename Icp Category","description":"Rename an ICP category. Workspace assignments are unaffected.","operationId":"rename_icp_category_api_v1_internal_icp_categories__category_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"category_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Category Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IcpCategoryWriteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IcpCategoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["internal","icp-categories"],"summary":"Delete Icp Category","description":"Delete an ICP category no workspace is using.","operationId":"delete_icp_category_api_v1_internal_icp_categories__category_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"category_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Category Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/icp-categories/{category_id}/workspaces":{"post":{"tags":["internal","icp-categories"],"summary":"Change Icp Category Workspaces","description":"Move workspaces onto or off this category.\n\nTakes the changes to make, not the membership to end up with, so two\nadmins editing at once merge instead of the later save undoing the\nearlier one. Each change lands in the admin audit trail as a workspace\nupdate.","operationId":"change_icp_category_workspaces_api_v1_internal_icp_categories__category_id__workspaces_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"category_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Category Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IcpCategoryMembersRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IcpCategoryListItem"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/knowledge":{"get":{"tags":["internal","internal-knowledge"],"summary":"List Knowledge Entries","description":"List a target owner's entries for a scope (user or workspace).\n\nThe ``require_internal`` injection is redundant with the router-level gate\ntoday, but kept for symmetry with the mutating handlers so the read path\nstays admin-gated even if this router is ever re-mounted standalone.","operationId":"list_knowledge_entries_api_v1_internal_knowledge_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"scope","in":"query","required":true,"schema":{"$ref":"#/components/schemas/AccountKnowledgeScope"}},{"name":"owner_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Owner Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/KnowledgeEntryResponse"},"title":"Response List Knowledge Entries Api V1 Internal Knowledge Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["internal","internal-knowledge"],"summary":"Create Knowledge Entry","description":"Create an entry at the requested scope for the target owner.","operationId":"create_knowledge_entry_api_v1_internal_knowledge_post","security":[{"FirebaseAuthMiddleware":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminKnowledgeCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeEntryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/knowledge/apply-run":{"post":{"tags":["internal","internal-knowledge"],"summary":"Apply Knowledge Run","description":"Apply one populate-knowledge run atomically (all-or-nothing).\n\nWrites are confined to the request's workspace; every mutation carries the\nrun's provenance in its audit metadata, and a run-marker audit row advances\nthe refresh cursor. Any invalid item rolls back the whole run.","operationId":"apply_knowledge_run_api_v1_internal_knowledge_apply_run_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminKnowledgeApplyRunRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminKnowledgeApplyRunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/knowledge/run-cursor":{"get":{"tags":["internal","internal-knowledge"],"summary":"Get Knowledge Run Cursor","description":"Read a workspace's populate-knowledge refresh cursor (newest run marker).","operationId":"get_knowledge_run_cursor_api_v1_internal_knowledge_run_cursor_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminKnowledgeRunCursorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/knowledge/{entry_id}":{"patch":{"tags":["internal","internal-knowledge"],"summary":"Update Knowledge Entry","description":"Replace any entry's title + content (admin override).","operationId":"update_knowledge_entry_api_v1_internal_knowledge__entry_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminKnowledgeUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeEntryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["internal","internal-knowledge"],"summary":"Delete Knowledge Entry","description":"Delete any entry (admin override).","operationId":"delete_knowledge_entry_api_v1_internal_knowledge__entry_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/projects/{project_id}/knowledge-skill-context":{"get":{"tags":["internal","internal-projects"],"summary":"Get Knowledge Skill Context","operationId":"get_knowledge_skill_context_api_v1_internal_projects__project_id__knowledge_skill_context_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectKnowledgeSkillContextStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/projects/{project_id}/edit-session":{"post":{"tags":["internal","internal-projects"],"summary":"Start Edit Session","description":"Begin an admin write-mode editing session on a user's project.\n\nAcquires the project editing lock for the admin (409 if another user holds\nit) and records one EDIT_PROJECT_AS_ADMIN audit row. With ``force=true``\nthe holder is evicted instead of 409ing and the audit metadata records the\ntakeover. The client then navigates into the project with\n``?admin_mode=write``.","operationId":"start_edit_session_api_v1_internal_projects__project_id__edit_session_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Force"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectLockStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-email/digests":{"get":{"tags":["internal","release-email"],"summary":"List Digests","operationId":"list_digests_api_v1_internal_release_email_digests_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ReleaseEmailDigestResponse"},"type":"array","title":"Response List Digests Api V1 Internal Release Email Digests Get"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/release-email/digests/{digest_id}":{"get":{"tags":["internal","release-email"],"summary":"Get Digest","operationId":"get_digest_api_v1_internal_release_email_digests__digest_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"digest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Digest Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseEmailDigestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["internal","release-email"],"summary":"Discard Draft","description":"Throw a draft away and return its entries to the pending queue.\n\nOnly a draft. A sent or in-flight digest is the record that a broadcast was\nattempted, and that record outlives any wish to be rid of it.","operationId":"discard_draft_api_v1_internal_release_email_digests__digest_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"digest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Digest Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["internal","release-email"],"summary":"Update Digest","operationId":"update_digest_api_v1_internal_release_email_digests__digest_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"digest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Digest Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDigestRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseEmailDigestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-email/recipients":{"get":{"tags":["internal","release-email"],"summary":"Get Recipient Summary","operationId":"get_recipient_summary_api_v1_internal_release_email_recipients_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"internal","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Internal"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipientSummaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-email/recipients/list":{"get":{"tags":["internal","release-email"],"summary":"List Recipients","description":"The audience roll-call, so a send is never confirmed against a number\nnobody can inspect.\n\n``internal`` switches to the staff audience an internal test broadcast\nreaches, which the same rule covers.\n\nCarries each recipient's product-updates consent so a delivered count lower\nthan the audience count is explainable here. Read-only: no route on this\nrouter writes a subscription field.","operationId":"list_recipients_api_v1_internal_release_email_recipients_list_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"internal","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Internal"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ReleaseEmailRecipientResponse"},"title":"Response List Recipients Api V1 Internal Release Email Recipients List Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-email/recipients/exclusions":{"post":{"tags":["internal","release-email"],"summary":"Set Recipient Exclusion","description":"Hold one person back from sends, or lift the hold.\n\nDatabase-only; the next contact sync (every send runs one) converges\nResend's segment membership.","operationId":"set_recipient_exclusion_api_v1_internal_release_email_recipients_exclusions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetExclusionRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/release-email/recipients/exclusions/bulk":{"post":{"tags":["internal","release-email"],"summary":"Set Recipient Exclusions Bulk","description":"One hold-or-lift across many recipients; per-email outcomes.\n\nSame database-only semantics as the single toggle.","operationId":"set_recipient_exclusions_bulk_api_v1_internal_release_email_recipients_exclusions_bulk_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetExclusionsBulkRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetExclusionsBulkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/release-email/periods":{"get":{"tags":["internal","release-email"],"summary":"List Period Options","description":"The weeks and months that hold shipped work, and what each one holds.","operationId":"list_period_options_api_v1_internal_release_email_periods_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/DigestPeriodOptionResponse"},"type":"array","title":"Response List Period Options Api V1 Internal Release Email Periods Get"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/release-email/roll-up-pending":{"post":{"tags":["internal","release-email"],"summary":"Roll Up Pending","description":"Draft from a period's shipped work.\n\nThe period decides which entries are in scope; whether a digest already\nclaimed one decides which of those are new. Repeating a claimed entry\ntakes ``include_already_sent``, so nothing is mailed twice by accident.","operationId":"roll_up_pending_api_v1_internal_release_email_roll_up_pending_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RollUpPendingRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseEmailDigestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/release-email/digests/{digest_id}/preview":{"get":{"tags":["internal","release-email"],"summary":"Preview Digest","description":"The exact document a send would deliver, for rendering in an iframe.","operationId":"preview_digest_api_v1_internal_release_email_digests__digest_id__preview_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"digest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Digest Id"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-email/digests/{digest_id}/test-send":{"post":{"tags":["internal","release-email"],"summary":"Test Send Digest","description":"Deliver the proof to the signed-in staff member, and nobody else.","operationId":"test_send_digest_api_v1_internal_release_email_digests__digest_id__test_send_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"digest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Digest Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseEmailDigestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-email/digests/{digest_id}/internal-test-broadcast":{"post":{"tags":["internal","release-email"],"summary":"Send Internal Test Broadcast","description":"Broadcast the draft to the staff segment, without consuming the month.","operationId":"send_internal_test_broadcast_api_v1_internal_release_email_digests__digest_id__internal_test_broadcast_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"digest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Digest Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseEmailDigestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-email/digests/{digest_id}/reopen":{"post":{"tags":["internal","release-email"],"summary":"Reopen Digest","operationId":"reopen_digest_api_v1_internal_release_email_digests__digest_id__reopen_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"digest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Digest Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReopenDigestRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseEmailDigestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-email/digests/{digest_id}/send":{"post":{"tags":["internal","release-email"],"summary":"Send Digest","operationId":"send_digest_api_v1_internal_release_email_digests__digest_id__send_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"digest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Digest Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseEmailDigestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-email/contacts/sync":{"post":{"tags":["internal","release-email"],"summary":"Sync Contacts","operationId":"sync_contacts_api_v1_internal_release_email_contacts_sync_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactSyncResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/release-notes/triage-queue":{"get":{"tags":["internal","release-notes"],"summary":"List Triage Queue","operationId":"list_triage_queue_api_v1_internal_release_notes_triage_queue_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/TriageWeekResponse"},"type":"array","title":"Response List Triage Queue Api V1 Internal Release Notes Triage Queue Get"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/release-notes/entries":{"get":{"tags":["internal","release-notes"],"summary":"List Entries","description":"Deploy-window shim preserving the pre-envelope array shape.\n\nClient bundles built before the paged envelope existed call this route and\n``.map`` the response, and the API promotes before the client deploy — so\nthe shape must hold until no deployed bundle calls it. Delete once the\nrelease carrying ``/entries-paged`` is live and old admin tabs have aged\nout (grep: no client reference to ``/internal/release-notes/entries`` that\nis not ``entries-paged``).","operationId":"list_entries_api_v1_internal_release_notes_entries_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ReleaseNoteEntryResponse"},"type":"array","title":"Response List Entries Api V1 Internal Release Notes Entries Get"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/release-notes/entries-paged":{"get":{"tags":["internal","release-notes"],"summary":"List Entries Paged","operationId":"list_entries_paged_api_v1_internal_release_notes_entries_paged_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"include_deleted","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Deleted"}},{"name":"before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Before"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseNoteEntryListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-notes/sync":{"post":{"tags":["internal","release-notes"],"summary":"Sync From Github","operationId":"sync_from_github_api_v1_internal_release_notes_sync_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/release-notes/roll-up":{"post":{"tags":["internal","release-notes"],"summary":"Roll Up Week","operationId":"roll_up_week_api_v1_internal_release_notes_roll_up_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RollUpWeekRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RollUpWeekResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/release-notes/entries/{entry_id}":{"delete":{"tags":["internal","release-notes"],"summary":"Delete Entry","description":"Remove a draft that should not exist; its releases return to triage.","operationId":"delete_entry_api_v1_internal_release_notes_entries__entry_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["internal","release-notes"],"summary":"Update Entry","operationId":"update_entry_api_v1_internal_release_notes_entries__entry_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateEntryRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseNoteEntryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-notes/entries/{entry_id}/publish":{"post":{"tags":["internal","release-notes"],"summary":"Publish Entry","operationId":"publish_entry_api_v1_internal_release_notes_entries__entry_id__publish_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseNoteEntryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-notes/entries/{entry_id}/unpublish":{"post":{"tags":["internal","release-notes"],"summary":"Unpublish Entry","operationId":"unpublish_entry_api_v1_internal_release_notes_entries__entry_id__unpublish_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseNoteEntryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-notes/entries/{entry_id}/schedule":{"post":{"tags":["internal","release-notes"],"summary":"Schedule Entry","operationId":"schedule_entry_api_v1_internal_release_notes_entries__entry_id__schedule_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleEntryRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReleaseNoteEntryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/release-notes/releases/nothing-user-facing":{"post":{"tags":["internal","release-notes"],"summary":"Mark Nothing User Facing","operationId":"mark_nothing_user_facing_api_v1_internal_release_notes_releases_nothing_user_facing_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkNothingUserFacingRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/release-notes/releases/nothing-user-facing/undo":{"post":{"tags":["internal","release-notes"],"summary":"Unmark Nothing User Facing","operationId":"unmark_nothing_user_facing_api_v1_internal_release_notes_releases_nothing_user_facing_undo_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkNothingUserFacingRequest"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/skills/draft":{"post":{"tags":["internal","internal-skills"],"summary":"Draft System Skill","description":"Draft a system skill from a plain-language prompt (LLM; no persistence).\n\nPowers the admin \"Build with MAIA\" mode: the draft pre-fills the create form,\nwhich staff review and save through the audited create path. ``current_*``\nlet ``prompt`` act as revision feedback on an existing draft.","operationId":"draft_system_skill_api_v1_internal_skills_draft_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSkillDraftRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSkillDraftResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/skills":{"get":{"tags":["internal","internal-skills"],"summary":"List System Skills","description":"List every MAIA-curated (system) skill with its workspace-availability set.","operationId":"list_system_skills_api_v1_internal_skills_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AdminSkillResponse"},"type":"array","title":"Response List System Skills Api V1 Internal Skills Get"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]},"post":{"tags":["internal","internal-skills"],"summary":"Create System Skill","description":"Create a curated (system) skill, available globally or restricted to\nspecific workspaces and/or ICP categories, optionally flagged as a\nnew-project starter.","operationId":"create_system_skill_api_v1_internal_skills_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSkillWriteRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSkillResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/skills/for-owner":{"get":{"tags":["internal","internal-skills"],"summary":"List Owner Skills","description":"List a specific user's or workspace's own skills (admin read-only view).\n\n``scope`` must be ``user`` or ``workspace`` (system skills have no owner → 422).","operationId":"list_owner_skills_api_v1_internal_skills_for_owner_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"scope","in":"query","required":true,"schema":{"$ref":"#/components/schemas/SkillScope"}},{"name":"owner_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Owner Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SkillResponse"},"title":"Response List Owner Skills Api V1 Internal Skills For Owner Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/skills/available-to":{"get":{"tags":["internal","internal-skills"],"summary":"List Context Skills For Workspace","description":"List the workspace and system skills available to an active workspace.","operationId":"list_context_skills_for_workspace_api_v1_internal_skills_available_to_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SkillResponse"},"title":"Response List Context Skills For Workspace Api V1 Internal Skills Available To Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/skills/{skill_id}/promote":{"post":{"tags":["internal","internal-skills"],"summary":"Promote Skill","description":"Promote an internal-authored user/workspace skill into the system catalog.\n\nCopies the source (which stays intact) into a new owner-less system skill\nwith the given curation controls. Sources outside internal workspaces /\ninternal authors are rejected (403); a name collision is a 409 the caller\nresolves by re-submitting with a ``name`` override.","operationId":"promote_skill_api_v1_internal_skills__skill_id__promote_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Skill Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSkillPromoteRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSkillResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/skills/{skill_id}":{"patch":{"tags":["internal","internal-skills"],"summary":"Update System Skill","description":"Replace a curated skill's content, starter flag, and availability.\n\n``workspace_ids`` and ``icp_category_ids`` set availability together:\nclearing both makes it global, either one restricts it.","operationId":"update_system_skill_api_v1_internal_skills__skill_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Skill Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSkillWriteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSkillResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["internal","internal-skills"],"summary":"Delete System Skill","description":"Delete a system skill.","operationId":"delete_system_skill_api_v1_internal_skills__skill_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Skill Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/stats/discovery-spend":{"get":{"tags":["internal","stats"],"summary":"Get Discovery Spend","operationId":"get_discovery_spend_api_v1_internal_stats_discovery_spend_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoverySpendResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/stats/":{"get":{"tags":["internal","stats"],"summary":"Get Stats","description":"Return summary statistics for the admin dashboard.","operationId":"get_stats_api_v1_internal_stats__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminStatsResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/users/":{"get":{"tags":["internal","users"],"summary":"List Users","description":"List all users with optional search by name or email.","operationId":"list_users_api_v1_internal_users__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":200},{"type":"null"}],"title":"Search"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["internal","users"],"summary":"Create User","description":"Create a new user account with Firebase Auth and DB record.","operationId":"create_user_api_v1_internal_users__post","security":[{"FirebaseAuthMiddleware":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCreateUserRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/users/{user_id}":{"get":{"tags":["internal","users"],"summary":"Get User Detail","description":"Get detailed user information.","operationId":"get_user_detail_api_v1_internal_users__user_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["internal","users"],"summary":"Update User","description":"Update user profile fields.","operationId":"update_user_api_v1_internal_users__user_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/users/{user_id}/projects":{"get":{"tags":["internal","users"],"summary":"List User Projects","description":"List all created projects owned by a user, annotated with lock status.","operationId":"list_user_projects_api_v1_internal_users__user_id__projects_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProjectListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/users/{user_id}/suspend":{"post":{"tags":["internal","users"],"summary":"Suspend User","description":"Suspend a user's account, blocking them from logging in.","operationId":"suspend_user_api_v1_internal_users__user_id__suspend_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/users/{user_id}/unsuspend":{"post":{"tags":["internal","users"],"summary":"Unsuspend User","description":"Restore login access for a suspended user.","operationId":"unsuspend_user_api_v1_internal_users__user_id__unsuspend_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/users/{user_id}/setup-link":{"post":{"tags":["internal","users"],"summary":"Issue Setup Link","description":"Mint a copyable account-setup link without sending any email.\n\nThis is the path that makes onboarding independent of deliverability: an\nadmin can hand the link over any channel when mail is filtered.","operationId":"issue_setup_link_api_v1_internal_users__user_id__setup_link_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSetupLinkResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/users/{user_id}/send-invite":{"post":{"tags":["internal","users"],"summary":"Send Invite Email","description":"Send an invite email (password setup link or Google SSO invite).","operationId":"send_invite_email_api_v1_internal_users__user_id__send_invite_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSendInviteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/":{"get":{"tags":["internal","workspaces"],"summary":"List Workspaces","description":"List all workspaces with member counts and credit info.","operationId":"list_workspaces_api_v1_internal_workspaces__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceListResponse"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/workspaces/available-counties":{"get":{"tags":["internal","workspaces"],"summary":"List All Available Counties","description":"Return every coverage-supported county in GCS (workspace-agnostic).\n\nSource for the create-workspace picker, which runs before a workspace\nexists. The per-workspace `GET /{workspace_id}/available-counties` reuses\nthe same gate minus already-loaded counties.","operationId":"list_all_available_counties_api_v1_internal_workspaces_available_counties_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AvailableCountyResponse"},"type":"array","title":"Response List All Available Counties Api V1 Internal Workspaces Available Counties Get"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/workspaces/county-load-stats":{"get":{"tags":["internal","workspaces"],"summary":"Get County Load Stats","description":"Duration stats over one county's recent succeeded loads (any workspace).\n\nFeeds the admin uploader's elapsed/ETA display; workspace-agnostic\nbecause load duration is a property of the county's data volume, not the\nworkspace. Zero sample means the county has no representative load\nhistory and the UI shows no estimate.","operationId":"get_county_load_stats_api_v1_internal_workspaces_county_load_stats_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"county_fips","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{5}$","title":"County Fips"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountyLoadStatsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/provision":{"post":{"tags":["internal","workspaces"],"summary":"Provision Workspace","description":"Provision a new workspace end-to-end with a Neon sandbox + counties.\n\nReplaces the legacy bare-create `POST /`. A workspace with no loaded\ncounties has zero geographic query access, so provisioning is the only\nsanctioned create path. Seeds the `workspace_counties` rows as `loading`\nand fires the `stand_up_workspace` Dagster job. Returns once the rows\nare persisted (5-15s for Neon create); county data loads asynchronously\nthereafter.","operationId":"provision_workspace_api_v1_internal_workspaces_provision_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceProvisionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/internal/workspaces/{workspace_id}":{"get":{"tags":["internal","workspaces"],"summary":"Get Workspace Detail","description":"Get detailed workspace information including members.","operationId":"get_workspace_detail_api_v1_internal_workspaces__workspace_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["internal","workspaces"],"summary":"Update Workspace","description":"Update workspace fields.","operationId":"update_workspace_api_v1_internal_workspaces__workspace_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/projects":{"get":{"tags":["internal","workspaces"],"summary":"List Workspace Projects","description":"List all created projects in a workspace, annotated with lock status.","operationId":"list_workspace_projects_api_v1_internal_workspaces__workspace_id__projects_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminProjectListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/credits":{"get":{"tags":["internal","workspaces"],"summary":"Get Workspace Credits","description":"Get credit summary with per-user breakdown.","operationId":"get_workspace_credits_api_v1_internal_workspaces__workspace_id__credits_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCreditsSummaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/discovery-allowance":{"get":{"tags":["internal","workspaces"],"summary":"Get Discovery Allowance","operationId":"get_discovery_allowance_api_v1_internal_workspaces__workspace_id__discovery_allowance_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoveryAllowanceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["internal","workspaces"],"summary":"Set Discovery Allowance","operationId":"set_discovery_allowance_api_v1_internal_workspaces__workspace_id__discovery_allowance_put","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoveryAllowanceUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DiscoveryAllowanceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/discovery-allowance/history":{"get":{"tags":["internal","workspaces"],"summary":"Get Discovery Allowance History","operationId":"get_discovery_allowance_history_api_v1_internal_workspaces__workspace_id__discovery_allowance_history_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAuditLogListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/credits/add":{"post":{"tags":["internal","workspaces"],"summary":"Add Workspace Credits","description":"Add enrichment credits to a workspace.","operationId":"add_workspace_credits_api_v1_internal_workspaces__workspace_id__credits_add_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAddCreditsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/credits/set":{"post":{"tags":["internal","workspaces"],"summary":"Set Workspace Credits","description":"Set available enrichment credits to an exact value.","operationId":"set_workspace_credits_api_v1_internal_workspaces__workspace_id__credits_set_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminSetCreditsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/credits/reset":{"post":{"tags":["internal","workspaces"],"summary":"Reset Workspace Credits","description":"Reset used enrichment credits for workspace and all members.","operationId":"reset_workspace_credits_api_v1_internal_workspaces__workspace_id__credits_reset_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/suspend":{"post":{"tags":["internal","workspaces"],"summary":"Suspend Workspace","description":"Suspend a workspace, blocking all members from logging in.","operationId":"suspend_workspace_api_v1_internal_workspaces__workspace_id__suspend_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/unsuspend":{"post":{"tags":["internal","workspaces"],"summary":"Unsuspend Workspace","description":"Restore login access for a suspended workspace.","operationId":"unsuspend_workspace_api_v1_internal_workspaces__workspace_id__unsuspend_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminWorkspaceDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/credits/history":{"get":{"tags":["internal","workspaces"],"summary":"Get Workspace Credits History","description":"Get credit change history from the audit log.","operationId":"get_workspace_credits_history_api_v1_internal_workspaces__workspace_id__credits_history_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAuditLogListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/retell-config":{"get":{"tags":["internal","workspaces"],"summary":"Get Retell Config","description":"Read the workspace's Retell config + auto-dial gate.\n\nSecrets returned masked (last 4 only). Internal admin only — workspace\nadmins do not manage Retell config themselves; MAIA staff onboard a\nworkspace by setting agent IDs/creds + flipping `auto_dial_enabled`.","operationId":"get_retell_config_api_v1_internal_workspaces__workspace_id__retell_config_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetellConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["internal","workspaces"],"summary":"Update Retell Config","description":"Update Retell config and/or flip the auto-dial gate. Admin-only,\naudit-logged. Pass an explicit `null` to clear an override; omit a\nfield to leave it untouched.","operationId":"update_retell_config_api_v1_internal_workspaces__workspace_id__retell_config_patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetellConfigUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetellConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/feature-toggles":{"get":{"tags":["internal","workspaces"],"summary":"Get Feature Toggles","description":"List every governable feature toggle with its effective state, override\nflag, and inherited global default for the workspace. Internal admin only.","operationId":"get_feature_toggles_api_v1_internal_workspaces__workspace_id__feature_toggles_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureTogglesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["internal","workspaces"],"summary":"Update Feature Toggle","description":"Set one per-workspace override. Admin-only, audit-logged.\nAn unregistered key is rejected with 422.","operationId":"update_feature_toggle_api_v1_internal_workspaces__workspace_id__feature_toggles_patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureToggleUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureTogglesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/feature-toggles/{key}":{"delete":{"tags":["internal","workspaces"],"summary":"Clear Feature Toggle Override","description":"Clear one per-workspace override so it inherits the global default.\nAdmin-only, audit-logged. An unregistered key is rejected with 422.","operationId":"clear_feature_toggle_override_api_v1_internal_workspaces__workspace_id__feature_toggles__key__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeatureTogglesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/counties":{"get":{"tags":["internal","workspaces"],"summary":"List Workspace Counties","description":"Return per-county sandbox load state for the workspace.","operationId":"list_workspace_counties_api_v1_internal_workspaces__workspace_id__counties_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceCountyResponse"},"title":"Response List Workspace Counties Api V1 Internal Workspaces  Workspace Id  Counties Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["internal","workspaces"],"summary":"Append Workspace County","description":"Insert a single pending `workspace_counties` row.\n\nThe env-matched `workspace_county_pickup_{staging,prod}` Dagster sensor\npicks the row up on its next tick (≤30s typical), registers the\npartition, launches `sandbox_load`, and the run-status callbacks stamp\ncompletion back. `workspace_counties` is the single source of truth for\nworkspace RBAC — `WorkspaceCountyRepository.get_loaded_fips` reads it\ndirectly.","operationId":"append_workspace_county_api_v1_internal_workspaces__workspace_id__counties_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppendCountyRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceCountyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/available-counties":{"get":{"tags":["internal","workspaces"],"summary":"List Available Counties","description":"Return GCS-known counties not yet loaded for this workspace.","operationId":"list_available_counties_api_v1_internal_workspaces__workspace_id__available_counties_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AvailableCountyResponse"},"title":"Response List Available Counties Api V1 Internal Workspaces  Workspace Id  Available Counties Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/counties/bulk":{"post":{"tags":["internal","workspaces"],"summary":"Append Workspace Counties","description":"Insert pending `workspace_counties` rows for several counties at once.\n\nSame sensor-pickup contract as the single-county append; the whole batch\nis validated (state FIPS, coverage, duplicates, already-loaded) before any\nrow is inserted, so a bad selection rejects atomically.","operationId":"append_workspace_counties_api_v1_internal_workspaces__workspace_id__counties_bulk_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppendCountiesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceCountyResponse"},"title":"Response Append Workspace Counties Api V1 Internal Workspaces  Workspace Id  Counties Bulk Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/counties/{county_id}/reload":{"post":{"tags":["internal","workspaces"],"summary":"Reload Workspace County","description":"Reset a failed or succeeded county row to `pending` for a fresh load.\n\nThe pickup sensor claims the reset row on its next tick and re-runs\n`sandbox_load` (idempotent per-table delete+insert). A previously\nsucceeded county keeps its workspace RBAC access during the re-run via\n`data_loaded_at`; an in-flight row is rejected with 409.","operationId":"reload_workspace_county_api_v1_internal_workspaces__workspace_id__counties__county_id__reload_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"county_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"County Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceCountyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/counties/{county_id}/cancel":{"post":{"tags":["internal","workspaces"],"summary":"Cancel Workspace County","description":"Cancel an in-flight (pending or loading) county load.\n\nThe row flips to `canceled` immediately; a run that is already executing\nis best-effort terminated. Previously loaded data and its workspace\naccess are unaffected (`data_loaded_at`). Terminal or provisioning rows\nare rejected with 409; the reload endpoint re-queues a canceled row.","operationId":"cancel_workspace_county_api_v1_internal_workspaces__workspace_id__counties__county_id__cancel_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"county_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"County Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceCountyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/counties/{county_id}/suspend":{"post":{"tags":["internal","workspaces"],"summary":"Suspend Workspace County","description":"Suspend a county's workspace access without removing it.\n\nThe row and its sandbox data stay intact — resume restores access with\nno re-load, unlike delete + re-add. Rows with nothing loaded, or\nalready suspended, are rejected with 409.","operationId":"suspend_workspace_county_api_v1_internal_workspaces__workspace_id__counties__county_id__suspend_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"county_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"County Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceCountyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/counties/{county_id}/unsuspend":{"post":{"tags":["internal","workspaces"],"summary":"Unsuspend Workspace County","description":"Restore a suspended county's workspace access. 409 if not suspended.","operationId":"unsuspend_workspace_county_api_v1_internal_workspaces__workspace_id__counties__county_id__unsuspend_post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"county_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"County Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceCountyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/workspaces/{workspace_id}/counties/{county_id}":{"delete":{"tags":["internal","workspaces"],"summary":"Remove Workspace County","description":"Revoke RBAC access to a county and remove its tracker row.\n\nDoes NOT drop the loaded sandbox data — the partition stays in the\nworkspace's Neon branch so a re-add is idempotent (re-add still runs\nthe loader from scratch, the sandbox infra just doesn't need to be\nre-provisioned).","operationId":"remove_workspace_county_api_v1_internal_workspaces__workspace_id__counties__county_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}},{"name":"county_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"County Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/internal/health":{"get":{"tags":["internal"],"summary":"Internal Health","description":"Health check endpoint for internal routes.\n\nConfirms the caller is authenticated and has internal staff access.","operationId":"internal_health_api_v1_internal_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Internal Health Api V1 Internal Health Get"}}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/v1/release-notes/":{"get":{"tags":["release-notes"],"summary":"List Published Entries","description":"The default call is the panel's recency window; any browsing argument\n(week bound or paging) widens to the full published history.","operationId":"list_published_entries_api_v1_release_notes__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Before"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ReleaseNoteEntryResponse"},"title":"Response List Published Entries Api V1 Release Notes  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge":{"get":{"tags":["knowledge"],"summary":"List Knowledge Entries","description":"List the caller's entries for a scope (user or workspace).","operationId":"list_knowledge_entries_api_v1_knowledge_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"scope","in":"query","required":true,"schema":{"$ref":"#/components/schemas/AccountKnowledgeScope"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/KnowledgeEntryResponse"},"title":"Response List Knowledge Entries Api V1 Knowledge Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["knowledge"],"summary":"Create Knowledge Entry","description":"Create a titled user- or workspace-scoped knowledge entry.","operationId":"create_knowledge_entry_api_v1_knowledge_post","security":[{"FirebaseAuthMiddleware":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeEntryCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeEntryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/project/{project_id}":{"get":{"tags":["knowledge"],"summary":"List Project Knowledge Entries","description":"List memory for an access-validated project.","operationId":"list_project_knowledge_entries_api_v1_knowledge_project__project_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/KnowledgeEntryResponse"},"title":"Response List Project Knowledge Entries Api V1 Knowledge Project  Project Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["knowledge"],"summary":"Create Project Knowledge Entry","description":"Create memory for an access-validated project.","operationId":"create_project_knowledge_entry_api_v1_knowledge_project__project_id__post","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectKnowledgeEntryCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeEntryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/project/{project_id}/{entry_id}":{"patch":{"tags":["knowledge"],"summary":"Update Project Knowledge Entry","description":"Replace memory belonging to an access-validated project.","operationId":"update_project_knowledge_entry_api_v1_knowledge_project__project_id___entry_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}},{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeEntryUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeEntryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["knowledge"],"summary":"Delete Project Knowledge Entry","description":"Delete memory belonging to an access-validated project.","operationId":"delete_project_knowledge_entry_api_v1_knowledge_project__project_id___entry_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}},{"name":"project_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Project Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/knowledge/{entry_id}":{"patch":{"tags":["knowledge"],"summary":"Update Knowledge Entry","description":"Replace an entry's title + content (caller must be entitled to edit it).","operationId":"update_knowledge_entry_api_v1_knowledge__entry_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeEntryUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeEntryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["knowledge"],"summary":"Delete Knowledge Entry","description":"Delete an entry the caller is entitled to edit.","operationId":"delete_knowledge_entry_api_v1_knowledge__entry_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/skills":{"get":{"tags":["skills"],"summary":"List Skills","description":"List the skills visible to the caller for a scope (user/workspace/system).","operationId":"list_skills_api_v1_skills_get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"scope","in":"query","required":true,"schema":{"$ref":"#/components/schemas/SkillScope"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SkillResponse"},"title":"Response List Skills Api V1 Skills Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["skills"],"summary":"Create Skill","description":"Create a user- or workspace-scoped skill (system scope is read-only → 403).","operationId":"create_skill_api_v1_skills_post","security":[{"FirebaseAuthMiddleware":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/skills/{skill_id}":{"get":{"tags":["skills"],"summary":"Get Skill","description":"Return a single skill (incl. body); 404 if not visible to the caller.","operationId":"get_skill_api_v1_skills__skill_id__get","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Skill Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["skills"],"summary":"Update Skill","description":"Replace a skill's name + description + body (caller must be entitled).","operationId":"update_skill_api_v1_skills__skill_id__patch","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Skill Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["skills"],"summary":"Delete Skill","description":"Delete a skill the caller is entitled to edit.","operationId":"delete_skill_api_v1_skills__skill_id__delete","security":[{"FirebaseAuthMiddleware":[]}],"parameters":[{"name":"skill_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Skill Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/me/events":{"get":{"tags":["user-events"],"summary":"User Events Stream","description":"Subscribe to the authenticated user's live event channel via SSE.\n\nForwards messages on ``user:{user_id}:events`` to the browser via the\nper-instance ``UserEventsFanout``. Heartbeat every 15 s. The connection\ncloses when the client disconnects or the server shuts down; the FE\nreconnects with jittered backoff and re-fetches snapshot state on each\n(re)connect so a dropped event during a disconnect window is recovered\nautomatically.\n\nNo payload is required from the FE — the subscription is implicit in\nopening the connection, scoped by the authenticated user.","operationId":"user_events_stream_api_v1_users_me_events_get","responses":{"200":{"description":"One JSON frame per `data:` line.","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CreditStateChangedEvent"},{"$ref":"#/components/schemas/DiscoveryAllowanceStateChangedEvent"},{"$ref":"#/components/schemas/EnrichmentStartedEvent"},{"$ref":"#/components/schemas/EnrichmentStatusChangedEvent"},{"$ref":"#/components/schemas/ViewStateChangedEvent"},{"$ref":"#/components/schemas/LayerStateChangedEvent"},{"$ref":"#/components/schemas/ProjectRenamedEvent"},{"$ref":"#/components/schemas/ChatSummarizationCompletedEvent"},{"$ref":"#/components/schemas/ImportProgressEvent"},{"$ref":"#/components/schemas/MapFlyToEvent"},{"$ref":"#/components/schemas/ExclusionStateChangedEvent"}],"title":"Response 200 User Events Stream Api V1 Users Me Events Get"}},"text/event-stream":{}}}},"security":[{"FirebaseAuthMiddleware":[]}]}},"/api/ext/{path}":{"options":{"tags":["analytics"],"summary":"Proxy Posthog","description":"Proxy requests to PostHog API.\n\nThis allows analytics to work even when ad blockers are enabled,\nsince requests go through our own domain instead of posthog.com.","operationId":"proxy_posthog_options","parameters":[{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["analytics"],"summary":"Proxy Posthog","description":"Proxy requests to PostHog API.\n\nThis allows analytics to work even when ad blockers are enabled,\nsince requests go through our own domain instead of posthog.com.","operationId":"proxy_posthog_post","parameters":[{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["analytics"],"summary":"Proxy Posthog","description":"Proxy requests to PostHog API.\n\nThis allows analytics to work even when ad blockers are enabled,\nsince requests go through our own domain instead of posthog.com.","operationId":"proxy_posthog_get","parameters":[{"name":"path","in":"path","required":true,"schema":{"type":"string","title":"Path"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AcceptedShareAccessResponse":{"properties":{"state":{"type":"string","const":"accepted","title":"State"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"shared_by_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Shared By Email"}},"additionalProperties":false,"type":"object","required":["state","expires_at"],"title":"AcceptedShareAccessResponse"},"AccountKnowledgeScope":{"type":"string","enum":["user","workspace"]},"ActionType":{"type":"string","enum":["new_enrichment","new_layer","analyze_row","invoke_skill"],"title":"ActionType","description":"Enum for different action types in the system."},"ActiveChatRunStatus":{"properties":{"status":{"type":"string","const":"active","title":"Status","default":"active"},"active_run_id":{"type":"string","title":"Active Run Id"}},"type":"object","required":["active_run_id"],"title":"ActiveChatRunStatus","description":"A chat run that can be resumed from its durable stream."},"AddContactNoteRequest":{"properties":{"content":{"type":"string","maxLength":5000,"minLength":1,"title":"Content"}},"type":"object","required":["content"],"title":"AddContactNoteRequest"},"AddEnrichmentToLayerRequest":{"properties":{"enrichment_id":{"type":"string","format":"uuid","title":"Enrichment Id","examples":["00000000-0000-0000-0000-000000000001"]},"layer_id":{"type":"string","format":"uuid","title":"Layer Id","examples":["00000000-0000-0000-0000-000000000000"]}},"type":"object","required":["enrichment_id","layer_id"],"title":"AddEnrichmentToLayerRequest","description":"Request model for adding an enrichment to a project."},"AddEnrichmentToLayerResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"AddEnrichmentToLayerResponse","description":"Response model for adding an enrichment to a project."},"AddressBatchCreateFlowRequest":{"properties":{"features":{"anyOf":[{"items":{"$ref":"#/components/schemas/AddressCreateFlowRequest"},"type":"array","maxItems":1000,"minItems":1},{"type":"null"}],"title":"Features"},"upload":{"anyOf":[{"$ref":"#/components/schemas/ImportUploadCommit"},{"type":"null"}]},"spine":{"type":"string","enum":["matched_only","all_rows"],"title":"Spine","default":"matched_only"},"knowledge_skill_workspace_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Knowledge Skill Workspace Id"}},"type":"object","title":"AddressBatchCreateFlowRequest","description":"Create one sandbox project from several confirmed features.\n\nEvery feature must derive to the same county (a project is scoped to one\ncounty under RLS); the server enforces this and 422s a cross-county batch.\n\nExactly one source: ``features`` is the paste flow, which has no file behind\nit; ``upload`` is the file-import flow, which references a held inspect\nresult so the server reads the user's rows from its own parse rather than\nfrom this request. ``spine=\"all_rows\"`` is meaningful only for ``upload`` —\nthere are no rows to seed a layer from without a file."},"AddressCandidate":{"properties":{"source_table":{"$ref":"#/components/schemas/SourceTable"},"feature_id":{"type":"string","title":"Feature Id"},"label":{"type":"string","title":"Label"},"similarity":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Similarity"},"matched_via":{"type":"string","title":"Matched Via"},"county_fips":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"County Fips"},"request_match":{"$ref":"#/components/schemas/RequestMatch","default":"not_checked"}},"type":"object","required":["source_table","feature_id","label","matched_via"],"title":"AddressCandidate","description":"One ranked candidate the confirm surface can render and hand back to\n``POST /project/sandbox/from-feature`` as ``(source_table, feature_id)``.\n\n``similarity`` is the raw match signal (1.0 for an exact/normalized match,\ntrigram score otherwise) and ``matched_via`` the ``table.column`` that\nproduced the hit — ranking signals only. ``request_match`` is the one field a\nsurface may read as a verdict: label an exact match, and tick a row for\ninclusion, from it alone."},"AddressCreateFlowRequest":{"properties":{"source_table":{"$ref":"#/components/schemas/SourceTable"},"feature_id":{"type":"string","title":"Feature Id"},"knowledge_skill_workspace_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Knowledge Skill Workspace Id"}},"additionalProperties":false,"type":"object","required":["source_table","feature_id"],"title":"AddressCreateFlowRequest","description":"Create a sandbox project from a confirmed resolved feature reference.\n\nThe confirm card holds ``(source_table, feature_id)`` — the server derives\nthe county scope from the matched feature and provisions the RLS-scoped\nproject, since the FE can't do either. This is the single-address and paste\nshape, which carries no uploaded columns; the file-upload flow commits\nthrough ``AddressBatchCreateFlowRequest.upload`` instead, where the columns\ncome from the server's own held parse rather than the request body.\n\nExtras are forbidden rather than ignored: a caller still sending the\nretired ``columns`` field must get a 422, not have its data silently\ndropped on the way to a project that then looks mysteriously empty."},"AddressFeatureGeometryResponse":{"properties":{"geometry":{"additionalProperties":true,"type":"object","title":"Geometry"},"bbox":{"prefixItems":[{"type":"number"},{"type":"number"},{"type":"number"},{"type":"number"}],"type":"array","maxItems":4,"minItems":4,"title":"Bbox"}},"type":"object","required":["geometry","bbox"],"title":"AddressFeatureGeometryResponse","description":"Drawable shape for one candidate: GeoJSON ``geometry`` plus its envelope\n``bbox`` ``(min_lng, min_lat, max_lng, max_lat)`` so the confirm card can\ndraw the boundary and frame the camera in one request."},"AddressProjectResponse":{"properties":{"project_id":{"type":"string","format":"uuid","title":"Project Id"},"status":{"$ref":"#/components/schemas/ProjectStatus"},"county_fips":{"type":"string","title":"County Fips"}},"type":"object","required":["project_id","status","county_fips"],"title":"AddressProjectResponse","description":"Response for the address create-flow.\n\n``status`` is always ``pending`` at sync-response time; the async DBOS seed\nflips it to ``ready``/``failed`` and the seeded layer arrives via the\n``LayerStateChangedEvent`` SSE. ``county_fips`` is the 5-digit scope derived\nfrom the matched feature."},"AddressResolveManyRequest":{"properties":{"queries":{"items":{"type":"string","maxLength":256},"type":"array","maxItems":1000,"minItems":1,"title":"Queries"},"county_fips":{"anyOf":[{"type":"string","pattern":"^\\d{5}$"},{"type":"null"}],"title":"County Fips"}},"type":"object","required":["queries"],"title":"AddressResolveManyRequest","description":"Batch resolve for paste-a-handful entry: a few free-text address rows, one\nper pasted line (blanks already dropped client-side but tolerated here).\n``county_fips`` bounds every row to the soft-selected county, exactly like the\nsingle resolve.\n\n``max_length`` is ``ADDRESS_ROW_CAP``, the same cap the inspect endpoint\nenforces on how many uploaded rows may ride to the client: an upload that\nreached the review list is exactly the list this endpoint is asked to\nresolve, so a lower cap here rejects work the server already handed out."},"AddressResolveManyResponse":{"properties":{"rows":{"items":{"$ref":"#/components/schemas/BatchResolutionRow"},"type":"array","title":"Rows"}},"type":"object","required":["rows"],"title":"AddressResolveManyResponse","description":"Per-row outcomes for a pasted batch, one row per input in input order."},"AddressResolveRequest":{"properties":{"query":{"type":"string","maxLength":256,"minLength":1,"title":"Query"},"county_fips":{"anyOf":[{"type":"string","pattern":"^\\d{5}$"},{"type":"null"}],"title":"County Fips"}},"type":"object","required":["query"],"title":"AddressResolveRequest","description":"Autocomplete resolve for address entry: free text (street address, place\nname, or parcel number) — no project exists yet on this path. ``county_fips``\n(5-digit GEOID) bounds the match to the picked county; absent, it matches\nacross every county the caller's workspace has loaded."},"AddressResolveResponse":{"properties":{"outcome":{"$ref":"#/components/schemas/ResolutionOutcome"},"candidates":{"items":{"$ref":"#/components/schemas/AddressCandidate"},"type":"array","title":"Candidates"}},"type":"object","required":["outcome"],"title":"AddressResolveResponse","description":"Ranked, label-hydrated candidates for one resolve. ``not_in_dataset``\nmeans the reference isn't in any county the workspace has loaded — the\nsurface reports \"not in your coverage\" rather than an empty dropdown."},"AdminAddCreditsRequest":{"properties":{"amount":{"type":"integer","exclusiveMinimum":0.0,"title":"Amount"}},"type":"object","required":["amount"],"title":"AdminAddCreditsRequest","description":"Request schema for adding credits to a workspace."},"AdminAuditLogListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminAuditLogResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"offset":{"type":"integer","title":"Offset"}},"type":"object","required":["items","total","limit","offset"],"title":"AdminAuditLogListResponse","description":"Paginated response for audit log queries."},"AdminAuditLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"admin_user_id":{"type":"string","format":"uuid","title":"Admin User Id"},"admin_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Admin Email"},"action":{"type":"string","title":"Action"},"target_type":{"type":"string","title":"Target Type"},"target_id":{"type":"string","format":"uuid","title":"Target Id"},"target_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Display Name"},"before_value":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Before Value"},"after_value":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"After Value"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","admin_user_id","admin_email","action","target_type","target_id","target_display_name","before_value","after_value","metadata","created_at"],"title":"AdminAuditLogResponse","description":"Response schema for a single audit log entry."},"AdminCreateUserRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"display_name":{"type":"string","title":"Display Name"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"plan_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan Type"},"is_internal":{"type":"boolean","title":"Is Internal","default":false},"auth_method":{"type":"string","enum":["google","password"],"title":"Auth Method","default":"google"},"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password"},"send_invite":{"type":"boolean","title":"Send Invite","default":false}},"additionalProperties":false,"type":"object","required":["email","display_name","workspace_id"],"title":"AdminCreateUserRequest","description":"Request schema for creating a new user account.\n\nRejects unknown fields with 422 — legacy callers sending the removed\n`create_workspace_allowed_geographies` key should fail loud rather than\nsilently no-op (see MAIA-1562)."},"AdminCreditUserUsageItem":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"email":{"type":"string","title":"Email"},"used_enrichment_credits":{"type":"integer","title":"Used Enrichment Credits"}},"type":"object","required":["user_id","display_name","email","used_enrichment_credits"],"title":"AdminCreditUserUsageItem","description":"Per-user credit usage in a workspace."},"AdminCreditsSummaryResponse":{"properties":{"available_enrichment_credits":{"type":"integer","title":"Available Enrichment Credits"},"used_enrichment_credits":{"type":"integer","title":"Used Enrichment Credits"},"remaining_credits":{"type":"integer","title":"Remaining Credits"},"users":{"items":{"$ref":"#/components/schemas/AdminCreditUserUsageItem"},"type":"array","title":"Users"}},"type":"object","required":["available_enrichment_credits","used_enrichment_credits","remaining_credits","users"],"title":"AdminCreditsSummaryResponse","description":"Response schema for workspace credit summary with per-user breakdown."},"AdminDeliveryStatusResponse":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"AdminDeliveryStatusResponse","description":"Status of a cross-branch delivery workflow: PENDING | SUCCESS | FAILURE."},"AdminDuplicateProjectRequest":{"properties":{"target_workspace_id":{"type":"string","format":"uuid","title":"Target Workspace Id"},"acknowledge_missing_counties":{"type":"boolean","title":"Acknowledge Missing Counties","default":false}},"type":"object","required":["target_workspace_id"],"title":"AdminDuplicateProjectRequest","description":"Request schema for delivering a curated project to a workspace."},"AdminDuplicateProjectResponse":{"properties":{"workflow_id":{"type":"string","title":"Workflow Id"}},"type":"object","required":["workflow_id"],"title":"AdminDuplicateProjectResponse","description":"Response schema for the duplicate (workspace delivery) endpoint.\n\nDelivery is a durable cross-Neon-branch workflow that returns only a\n``workflow_id``; the delivered project id isn't known until the workflow's\nclone step runs, so the UI tracks progress via the Recent duplications panel."},"AdminDuplicationLogEntry":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"source_project_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Project Name"},"target_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Name"},"duplicate_type":{"type":"string","title":"Duplicate Type"},"status":{"type":"string","title":"Status"},"delivered_project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Delivered Project Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","source_project_name","target_name","duplicate_type","status","delivered_project_id","created_at"],"title":"AdminDuplicationLogEntry","description":"One recent duplication for the admin tracker.\n\n``status`` is PENDING | SUCCESS | FAILURE. Synchronous user duplications are\nalways SUCCESS (logged after the copy committed); workspace deliveries\nresolve their durable workflow's live status. ``delivered_project_id`` is the\nresulting project once it exists (immediately for the user path, on SUCCESS\nfor the workspace path), used to link straight to the copy."},"AdminDuplicationLogResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminDuplicationLogEntry"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"AdminDuplicationLogResponse","description":"Recent duplications, newest first, for the admin tracker panel."},"AdminExampleProjectListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"owner_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Display Name"},"knowledge_skill_workspace_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Knowledge Skill Workspace Id"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","name","description","owner_display_name","knowledge_skill_workspace_id","created_at"],"title":"AdminExampleProjectListItem","description":"Summary schema for example project list items."},"AdminExampleProjectListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminExampleProjectListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"AdminExampleProjectListResponse","description":"Response schema for example project list endpoint."},"AdminKnowledgeApplyRunRequest":{"properties":{"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"provenance":{"$ref":"#/components/schemas/KnowledgeRunProvenance"},"creates":{"items":{"$ref":"#/components/schemas/KnowledgeRunCreate"},"type":"array","title":"Creates"},"updates":{"items":{"$ref":"#/components/schemas/KnowledgeRunUpdate"},"type":"array","title":"Updates"},"deletes":{"items":{"$ref":"#/components/schemas/KnowledgeRunDelete"},"type":"array","title":"Deletes"}},"type":"object","required":["workspace_id","provenance"],"title":"AdminKnowledgeApplyRunRequest","description":"One populate-knowledge run, applied atomically to a single workspace.\n\nThe item shapes (with title/content caps) are the domain run models; the\naudit actor is the authenticated internal caller, so the payload carries no\nadmin id."},"AdminKnowledgeApplyRunResponse":{"properties":{"created":{"items":{"$ref":"#/components/schemas/KnowledgeEntryResponse"},"type":"array","title":"Created"},"updated":{"items":{"$ref":"#/components/schemas/KnowledgeEntryResponse"},"type":"array","title":"Updated"},"deleted_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Deleted Ids"},"run_marker_id":{"type":"string","format":"uuid","title":"Run Marker Id"}},"type":"object","required":["created","updated","deleted_ids","run_marker_id"],"title":"AdminKnowledgeApplyRunResponse","description":"What an applied run changed, plus the run-marker audit row's id."},"AdminKnowledgeCreateRequest":{"properties":{"scope":{"$ref":"#/components/schemas/AccountKnowledgeScope"},"owner_id":{"type":"string","format":"uuid","title":"Owner Id"},"title":{"type":"string","maxLength":120,"minLength":1,"title":"Title"},"content":{"type":"string","maxLength":100000,"minLength":1,"title":"Content"}},"type":"object","required":["scope","owner_id","title","content"],"title":"AdminKnowledgeCreateRequest","description":"Create a titled entry at ``scope`` for the target ``owner_id``.\n\n``owner_id`` is the target user id (user scope) or workspace id (workspace\nscope)."},"AdminKnowledgeRunCursorResponse":{"properties":{"meetings_through":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Meetings Through"},"last_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Run At"},"runs":{"type":"integer","title":"Runs"}},"type":"object","required":["meetings_through","last_run_at","runs"],"title":"AdminKnowledgeRunCursorResponse","description":"Refresh cursor for a workspace's populate-knowledge runs.\n\n``meetings_through`` is the opaque ISO-8601 string from the newest run\nmarker's metadata; ``runs`` counts all markers for the workspace."},"AdminKnowledgeUpdateRequest":{"properties":{"title":{"type":"string","maxLength":120,"minLength":1,"title":"Title"},"content":{"type":"string","maxLength":100000,"minLength":1,"title":"Content"}},"type":"object","required":["title","content"],"title":"AdminKnowledgeUpdateRequest","description":"Replace an entry's title + content."},"AdminLayerSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"feature_count":{"type":"integer","title":"Feature Count"}},"type":"object","required":["id","name","description","feature_count"],"title":"AdminLayerSummary","description":"Layer summary for project preview."},"AdminProjectListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"status":{"type":"string","title":"Status"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"owner_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Display Name"},"is_locked":{"type":"boolean","title":"Is Locked","default":false},"locked_by_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locked By Display Name"}},"type":"object","required":["id","name","status","created_at","updated_at"],"title":"AdminProjectListItem","description":"Summary schema for project list items in admin views."},"AdminProjectListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminProjectListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"AdminProjectListResponse","description":"Response schema for admin project list endpoints."},"AdminProjectPreviewResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"owner_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Display Name"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"layers":{"items":{"$ref":"#/components/schemas/AdminLayerSummary"},"type":"array","title":"Layers"}},"type":"object","required":["id","name","description","owner_display_name","created_at","layers"],"title":"AdminProjectPreviewResponse","description":"Response schema for project preview endpoint."},"AdminProjectSearchResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminProjectSearchResult"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"AdminProjectSearchResponse","description":"Response schema for project search endpoint."},"AdminProjectSearchResult":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"owner_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Display Name"},"workspace_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace Name"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"visibility":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Visibility"},"knowledge_skill_workspace_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Knowledge Skill Workspace Id"}},"type":"object","required":["id","name","owner_display_name","workspace_name","created_at","updated_at","visibility","knowledge_skill_workspace_id"],"title":"AdminProjectSearchResult","description":"Search result item for project search."},"AdminSendInviteResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"}},"type":"object","required":["success","message"],"title":"AdminSendInviteResponse","description":"Response schema for send invite email endpoint."},"AdminSetCreditsRequest":{"properties":{"available_credits":{"type":"integer","minimum":0.0,"title":"Available Credits"}},"type":"object","required":["available_credits"],"title":"AdminSetCreditsRequest","description":"Request schema for setting available credits to an exact value."},"AdminSetupLinkResponse":{"properties":{"url":{"type":"string","title":"Url"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["url","expires_at"],"title":"AdminSetupLinkResponse","description":"Response schema for the copyable account-setup link endpoint."},"AdminSkillDraftRequest":{"properties":{"prompt":{"type":"string","maxLength":4000,"minLength":1,"title":"Prompt"},"current_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Name"},"current_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Description"},"current_body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Body"}},"type":"object","required":["prompt"],"title":"AdminSkillDraftRequest","description":"Draft a system skill from a plain-language description (no persistence).\n\n``current_*`` carry an existing draft so ``prompt`` can be read as revision\nfeedback rather than a fresh request; omit them for a first draft. The draft\nis reviewed and saved through ``AdminSkillWriteRequest``, so this is\nuncapped beyond the prompt length."},"AdminSkillDraftResponse":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"body":{"type":"string","title":"Body"}},"type":"object","required":["name","description","body"],"title":"AdminSkillDraftResponse","description":"A drafted skill's three authored fields, for pre-filling the editor."},"AdminSkillPromoteRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120,"minLength":1},{"type":"null"}],"title":"Name"},"is_starter":{"type":"boolean","title":"Is Starter","default":false},"workspace_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Workspace Ids"},"icp_category_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Icp Category Ids"}},"additionalProperties":false,"type":"object","title":"AdminSkillPromoteRequest","description":"Promote an internal-authored user/workspace skill into the system catalog.\n\nThe source skill's description, body, and type are copied as-is; ``name``\noverrides the source's name (rename on collision), else the source name is\nkept. ``is_starter``, ``workspace_ids``, and ``icp_category_ids`` are the\nsame curation controls as ``AdminSkillWriteRequest`` — promotion never\ninherits them from the source, since they only mean something at system\nscope."},"AdminSkillResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"scope":{"$ref":"#/components/schemas/SkillScope"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"workspace_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Workspace Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"body":{"type":"string","title":"Body"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"is_starter":{"type":"boolean","title":"Is Starter","description":"Whether this skill surfaces as a first-run starter in the new-project gallery. System (Ready-made by MAIA) and workspace-scoped skills may be starters; user-scoped skills are never starters.","default":false},"skill_type":{"$ref":"#/components/schemas/SkillType","description":"What kind of work the skill encodes: a whole 'workflow', an 'enrichment' configuration, or a single 'agent_column'. Only workflow skills default into the new-project starter gallery.","default":"workflow"},"supersedes_skill_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Supersedes Skill Id","description":"If set, the MAIA/workspace starter this skill was customized from; that original is hidden from this caller's starter gallery and the agent's routing catalog in favor of this skill."},"workspace_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Workspace Ids","description":"The workspaces this curated (system) skill is explicitly available in. Global means this AND icp_category_ids are both empty."},"icp_category_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Icp Category Ids","description":"The ICP categories this curated (system) skill targets. Any workspace carrying one of them can see it."}},"type":"object","required":["id","scope","name","description","body","created_at","updated_at"],"title":"AdminSkillResponse","description":"A curated skill as returned to the internal admin catalog.\n\nAdds the ``workspace_ids`` availability set, which the public\n``SkillResponse`` deliberately omits: for a skill restricted to a set of\nworkspaces, that set contains *other* tenants' workspace ids, so exposing it\non the public read paths (picker / gallery) would leak cross-tenant data to\nany workspace the skill is visible in. Only the internal admin surface\n(``require_internal``) sees the availability set."},"AdminSkillWriteRequest":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"description":{"type":"string","maxLength":400,"minLength":1,"title":"Description"},"body":{"type":"string","maxLength":32000,"minLength":1,"title":"Body"},"is_starter":{"type":"boolean","title":"Is Starter","default":false},"skill_type":{"$ref":"#/components/schemas/SkillType","default":"workflow"},"workspace_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Workspace Ids"},"icp_category_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Icp Category Ids","description":"ICP categories this skill targets. Every workspace carrying one of these categories can see it, including workspaces assigned to the category after this write."}},"additionalProperties":false,"type":"object","required":["name","description","body"],"title":"AdminSkillWriteRequest","description":"Create or replace a MAIA-curated (``scope=system``) skill.\n\n``workspace_ids`` and ``icp_category_ids`` together set availability on both\ncreate and update: both empty is a global skill (visible to every\nworkspace); either one restricts it. ``is_starter`` is independent of\navailability.\n\n``extra=\"forbid\"`` rejects the retired scalar ``workspace_id`` field: a stale\ncaller from before the multi-workspace cutover would otherwise have it\nsilently dropped, defaulting ``workspace_ids`` to empty and publishing a\nworkspace-scoped skill to every workspace. A 422 surfaces the stale call."},"AdminStatsResponse":{"properties":{"workspace_count":{"type":"integer","title":"Workspace Count"},"user_count":{"type":"integer","title":"User Count"},"project_count":{"type":"integer","title":"Project Count"},"example_project_count":{"type":"integer","title":"Example Project Count"}},"type":"object","required":["workspace_count","user_count","project_count","example_project_count"],"title":"AdminStatsResponse","description":"Summary statistics for the admin dashboard."},"AdminUserDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"workspace_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace Name"},"is_internal":{"type":"boolean","title":"Is Internal"},"is_suspended":{"type":"boolean","title":"Is Suspended"},"has_completed_onboarding":{"type":"boolean","title":"Has Completed Onboarding"},"plan_type":{"type":"string","title":"Plan Type"},"available_enrichment_credits":{"type":"integer","title":"Available Enrichment Credits"},"used_enrichment_credits":{"type":"integer","title":"Used Enrichment Credits"},"remaining_credits":{"type":"integer","title":"Remaining Credits"},"project_count":{"type":"integer","title":"Project Count"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Active At"}},"type":"object","required":["id","email","display_name","role","workspace_id","workspace_name","is_internal","is_suspended","has_completed_onboarding","plan_type","available_enrichment_credits","used_enrichment_credits","remaining_credits","project_count","created_at","updated_at","last_active_at"],"title":"AdminUserDetailResponse","description":"Full user detail response for admin view."},"AdminUserListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"workspace_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace Name"},"is_internal":{"type":"boolean","title":"Is Internal"},"is_suspended":{"type":"boolean","title":"Is Suspended"},"has_completed_onboarding":{"type":"boolean","title":"Has Completed Onboarding"},"plan_type":{"type":"string","title":"Plan Type"},"project_count":{"type":"integer","title":"Project Count"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Active At"}},"type":"object","required":["id","email","display_name","workspace_id","workspace_name","is_internal","is_suspended","has_completed_onboarding","plan_type","project_count","created_at","last_active_at"],"title":"AdminUserListItem","description":"Summary schema for user list items."},"AdminUserListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminUserListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"AdminUserListResponse","description":"Response schema for user list endpoint."},"AdminUserUpdateRequest":{"properties":{"is_internal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Internal"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"plan_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Plan Type"},"has_completed_onboarding":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Completed Onboarding"}},"type":"object","title":"AdminUserUpdateRequest","description":"Request schema for updating user fields."},"AdminWorkspaceDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"budget_authority":{"$ref":"#/components/schemas/BudgetAuthority"},"avatar_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Color"},"available_enrichment_credits":{"type":"integer","title":"Available Enrichment Credits"},"used_enrichment_credits":{"type":"integer","title":"Used Enrichment Credits"},"remaining_credits":{"type":"integer","title":"Remaining Credits"},"is_suspended":{"type":"boolean","title":"Is Suspended"},"is_internal":{"type":"boolean","title":"Is Internal"},"icp_category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Icp Category Id"},"member_count":{"type":"integer","title":"Member Count"},"project_count":{"type":"integer","title":"Project Count"},"members":{"items":{"$ref":"#/components/schemas/AdminWorkspaceMemberItem"},"type":"array","title":"Members"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["id","name","budget_authority","avatar_color","available_enrichment_credits","used_enrichment_credits","remaining_credits","is_suspended","is_internal","icp_category_id","member_count","project_count","members","created_at","updated_at"],"title":"AdminWorkspaceDetailResponse","description":"Full workspace detail response for admin view."},"AdminWorkspaceListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"budget_authority":{"$ref":"#/components/schemas/BudgetAuthority"},"member_count":{"type":"integer","title":"Member Count"},"project_count":{"type":"integer","title":"Project Count"},"available_enrichment_credits":{"type":"integer","title":"Available Enrichment Credits"},"used_enrichment_credits":{"type":"integer","title":"Used Enrichment Credits"},"remaining_credits":{"type":"integer","title":"Remaining Credits"},"is_suspended":{"type":"boolean","title":"Is Suspended"},"is_internal":{"type":"boolean","title":"Is Internal"},"icp_category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Icp Category Id"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Active At"}},"type":"object","required":["id","name","budget_authority","member_count","project_count","available_enrichment_credits","used_enrichment_credits","remaining_credits","is_suspended","is_internal","icp_category_id","created_at","last_active_at"],"title":"AdminWorkspaceListItem","description":"Summary schema for workspace list items."},"AdminWorkspaceListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminWorkspaceListItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"AdminWorkspaceListResponse","description":"Response schema for workspace list endpoint."},"AdminWorkspaceMemberItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"workspace_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace Role"},"is_internal":{"type":"boolean","title":"Is Internal"},"is_suspended":{"type":"boolean","title":"Is Suspended"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"used_enrichment_credits":{"type":"integer","title":"Used Enrichment Credits"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Active At"}},"type":"object","required":["id","email","display_name","workspace_role","is_internal","is_suspended","created_at","used_enrichment_credits","last_active_at"],"title":"AdminWorkspaceMemberItem","description":"Member summary for workspace detail view."},"AdminWorkspaceProvisionRequest":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"counties":{"items":{"$ref":"#/components/schemas/WorkspaceCountySelection"},"type":"array","title":"Counties"},"initial_credits":{"type":"integer","minimum":0.0,"title":"Initial Credits","default":5000},"region_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Region Id"},"icp_category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Icp Category Id","description":"Optional ICP category to assign at creation. Omit or pass null to leave the workspace unassigned."}},"additionalProperties":false,"type":"object","required":["name","counties"],"title":"AdminWorkspaceProvisionRequest","description":"Request body for provisioning a new workspace end-to-end.\n\nWraps `AdminWorkspaceService.provision_workspace_with_counties`: creates\nthe Neon sandbox and seeds `workspace_counties` rows. At least one county\nis mandatory — a workspace with no loaded counties has zero geographic\nquery access. Rejects unknown fields with 422.\n\n`counties` non-emptiness and in-list duplicates are validated in the\nservice (400) rather than here, so the same guard covers the script caller\n(`scripts/provision_prod_admin_workspace.py`) and the error is a 400, not a\n422, matching the rest of the provisioning contract."},"AdminWorkspaceUpdateRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"is_internal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Internal"},"icp_category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Icp Category Id","description":"Id of a staff-administered ICP category. Omit to leave unchanged; pass an explicit null to clear (unassigned)."}},"additionalProperties":false,"type":"object","title":"AdminWorkspaceUpdateRequest","description":"Request schema for updating workspace fields.\n\nAll fields optional; uses exclude_unset semantics. Rejects unknown fields\nwith 422 — legacy callers sending the removed `allowed_geographies` key\nshould fail loud rather than silently no-op."},"AdmissionsPausedControlUpdate":{"properties":{"admissions_paused":{"type":"boolean","title":"Admissions Paused"},"public_signup_enabled":{"type":"boolean","title":"Public Signup Enabled"}},"additionalProperties":false,"type":"object","required":["admissions_paused"],"title":"AdmissionsPausedControlUpdate"},"AdmitAccountRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"AdmitAccountRequest"},"AdmitAccountResponse":{"properties":{"account_id":{"type":"string","format":"uuid","title":"Account Id"},"state":{"$ref":"#/components/schemas/SelfServeAccountState"},"workflow_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workflow Id"}},"type":"object","required":["account_id","state","workflow_id"],"title":"AdmitAccountResponse"},"AgeRange":{"properties":{"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"},"is_approximate":{"type":"boolean","title":"Is Approximate","default":true},"reasoning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reasoning","description":"The reasoning for the age range."},"sources":{"items":{"type":"string"},"type":"array","title":"Sources","description":"The sources for the age range."}},"type":"object","title":"AgeRange","description":"Age range from PDL. Can represent exact age (min == max) or range."},"AllInFlightTasksResponse":{"properties":{"projects":{"items":{"$ref":"#/components/schemas/ProjectInFlightTasks"},"type":"array","title":"Projects","description":"List of projects with in-flight tasks"},"total_count":{"type":"integer","title":"Total Count","description":"Total number of in-flight tasks across all projects"}},"type":"object","required":["projects","total_count"],"title":"AllInFlightTasksResponse","description":"Response schema for listing all in-flight enrichment tasks across all projects."},"AllUserEnrichmentsResponse":{"properties":{"enrichments":{"items":{"$ref":"#/components/schemas/EnrichmentModel"},"type":"array","title":"Enrichments"},"available_enrichment_names":{"items":{"$ref":"#/components/schemas/EnrichmentNameConstants"},"type":"array","title":"Available Enrichment Names","description":"Available enrichment names from constants"}},"type":"object","required":["enrichments"],"title":"AllUserEnrichmentsResponse","description":"Response model for returning a list of all user enrichments."},"AllowanceCode":{"type":"string","enum":["allowed","discovery_allowance_exhausted","discovery_allowance_unavailable","discovery_allowance_run_unaffordable","discovery_allowance_confirmation_required"],"title":"AllowanceCode"},"AppendCountiesRequest":{"properties":{"counties":{"items":{"$ref":"#/components/schemas/WorkspaceCountySelection"},"type":"array","minItems":1,"title":"Counties"}},"additionalProperties":false,"type":"object","required":["counties"],"title":"AppendCountiesRequest","description":"Request body for appending several counties in one call.\n\n`min_length=1` rejects an empty selection at the schema layer (422) —\nunlike provisioning, no script caller shares this path, so the wire\ncontract owns the non-emptiness rule. In-list duplicate and coverage\nvalidation stay in the service (400), mirroring `append_county`."},"AppendCountyRequest":{"properties":{"state_fips":{"type":"string","maxLength":2,"minLength":2,"pattern":"^\\d{2}$","title":"State Fips"},"county_fips":{"type":"string","maxLength":3,"minLength":3,"pattern":"^\\d{3}$","title":"County Fips"}},"additionalProperties":false,"type":"object","required":["state_fips","county_fips"],"title":"AppendCountyRequest","description":"Request body for appending one county to an existing workspace sandbox."},"ArchiveContentResponseSchema":{"properties":{"archived_messages":{"items":{"oneOf":[{"$ref":"#/components/schemas/ModelRequest"},{"$ref":"#/components/schemas/ModelResponse"}],"discriminator":{"propertyName":"kind","mapping":{"request":"#/components/schemas/ModelRequest","response":"#/components/schemas/ModelResponse"}}},"type":"array","title":"Archived Messages","description":"The validated archived messages for one archive."}},"type":"object","required":["archived_messages"],"title":"ArchiveContentResponseSchema","description":"Schema for one archive's message bodies, fetched on demand."},"ArchiveMetadataSchema":{"properties":{"id":{"type":"string","format":"uuid","title":"Id","description":"The archive's id, used to fetch its content."},"summary_content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary Content","description":"The summary content that replaced these messages."},"safe_split_index":{"type":"integer","title":"Safe Split Index","description":"The split index used for summarization."},"message_count":{"type":"integer","title":"Message Count","description":"Number of archived messages."},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When the messages were archived (UTC timestamp)."}},"type":"object","required":["id","safe_split_index","message_count","created_at"],"title":"ArchiveMetadataSchema","description":"Light metadata for a single archive, without message bodies."},"AttributionPayload":{"properties":{"kind":{"type":"string","enum":["skill","knowledge"],"title":"Kind"},"entryId":{"type":"string","title":"Entryid"},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Displayname"},"scope":{"anyOf":[{"$ref":"#/components/schemas/KnowledgeScope"},{"type":"null"}]}},"type":"object","required":["kind","entryId"],"title":"AttributionPayload","description":"One trust-receipt entry.\n\nCarried under two metadata keys with the same shape: `attribution` (the\nreply ran a skill / applied a saved preference) and `knowledge_saved` (the\nreply saved a new knowledge entry). The key distinguishes the semantic; for\n`knowledge_saved` `kind` is always `\"knowledge\"`."},"AudioUrl":{"properties":{"url":{"type":"string","title":"Url"},"force_download":{"anyOf":[{"type":"boolean"},{"type":"string","const":"allow-local"}],"title":"Force Download","default":false},"vendor_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Vendor Metadata"},"kind":{"type":"string","const":"audio-url","title":"Kind","default":"audio-url"},"media_type":{"type":"string","title":"Media Type","description":"Return the media type of the file, based on the URL or the provided `media_type`.","readOnly":true},"identifier":{"type":"string","title":"Identifier","description":"The identifier of the file, such as a unique ID.\n\nThis identifier can be provided to the model in a message to allow it to refer to this file in a tool call argument,\nand the tool can look up the file in question by iterating over the message history and finding the matching `FileUrl`.\n\nThis identifier is only automatically passed to the model when the `FileUrl` is returned by a tool.\nIf you're passing the `FileUrl` as a user message, it's up to you to include a separate text part with the identifier,\ne.g. \"This is file <identifier>:\" preceding the `FileUrl`.\n\nIt's also included in inline-text delimiters for providers that require inlining text documents, so the model can\ndistinguish multiple files.","readOnly":true}},"type":"object","required":["url","media_type","identifier"],"title":"AudioUrl","description":"A URL to an audio file."},"AvailableCountyResponse":{"properties":{"state":{"type":"string","title":"State"},"county_name":{"type":"string","title":"County Name"},"state_fips":{"type":"string","title":"State Fips"},"county_fips":{"type":"string","title":"County Fips"}},"type":"object","required":["state","county_name","state_fips","county_fips"],"title":"AvailableCountyResponse","description":"A county available to load (not yet in this workspace).\n\n``county_name`` is the TIGER LSAD form (e.g. ``\"Los Angeles County\"``)\npopulated from the picker's ``AvailableCounty`` named tuple."},"BatchEnrichmentInfo":{"properties":{"coordinator_workflow_id":{"type":"string","title":"Coordinator Workflow Id","description":"The coordinator workflow id identifying this run/batch"},"field_name":{"type":"string","title":"Field Name","description":"The enrichment field name"},"launched_total":{"type":"integer","title":"Launched Total","description":"Rows this action launched, fixed at kickoff (manifest size)"},"resolved_count":{"type":"integer","title":"Resolved Count","description":"Launched rows that have reached a terminal state"},"started_at":{"type":"string","format":"date-time","title":"Started At","description":"When this batch was enqueued"}},"type":"object","required":["coordinator_workflow_id","field_name","launched_total","resolved_count","started_at"],"title":"BatchEnrichmentInfo","description":"Run-scoped progress for a single enrichment action [MAIA-2116].\n\nOne per kickoff, keyed on the MAIA-2111 coordinator. ``launched_total`` is\nthe fixed denominator (the coordinator manifest's row count — immune to the\nrolling window AND to waved fan-out); ``resolved_count`` is the numerator\n(manifest children that reached a terminal state)."},"BatchOutcomeKind":{"type":"string","enum":["matched","ambiguous","not_in_dataset","empty_input"],"title":"BatchOutcomeKind","description":"Per-row bucket for a batch resolve, derived from a single row's\n``ResolutionResult`` plus its raw input. Coarser than the single-address\n``ResolutionOutcome``: it splits ``matched`` by CARDINALITY (one candidate vs.\nseveral) and distinguishes a blank input row, so a caller can route each row\n(seed / disambiguate / report-missing / flag-blank) without re-deriving. The\naccept/reject verdict on candidates still lives with the agent / human — this\nis a count, not a confidence threshold."},"BatchResolutionRow":{"properties":{"index":{"type":"integer","title":"Index"},"query":{"type":"string","title":"Query"},"kind":{"$ref":"#/components/schemas/BatchOutcomeKind"},"candidates":{"items":{"$ref":"#/components/schemas/AddressCandidate"},"type":"array","title":"Candidates"}},"type":"object","required":["index","query","kind","candidates"],"title":"BatchResolutionRow","description":"One pasted row's outcome for the review list. ``kind`` buckets the row\n(matched / ambiguous / not_in_dataset / empty_input); ``candidates`` are the\nranked, label-hydrated matches (one for ``matched``, several for ``ambiguous``,\nempty otherwise). ``index`` preserves the input row position."},"BinaryContent":{"properties":{"data":{"type":"string","contentEncoding":"base64","contentMediaType":"application/octet-stream","title":"Data"},"media_type":{"anyOf":[{"type":"string","enum":["audio/wav","audio/mpeg","audio/ogg","audio/flac","audio/aiff","audio/aac"]},{"type":"string","enum":["image/jpeg","image/png","image/gif","image/webp"]},{"type":"string","enum":["application/pdf","text/plain","text/csv","application/vnd.openxmlformats-officedocument.wordprocessingml.document","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","text/html","text/markdown","application/msword","application/vnd.ms-excel"]},{"type":"string"}],"title":"Media Type"},"vendor_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Vendor Metadata"},"kind":{"type":"string","const":"binary","title":"Kind","default":"binary"},"identifier":{"type":"string","title":"Identifier","description":"Identifier for the binary content, such as a unique ID.\n\nThis identifier can be provided to the model in a message to allow it to refer to this file in a tool call argument,\nand the tool can look up the file in question by iterating over the message history and finding the matching `BinaryContent`.\n\nThis identifier is only automatically passed to the model when the `BinaryContent` is returned by a tool.\nIf you're passing the `BinaryContent` as a user message, it's up to you to include a separate text part with the identifier,\ne.g. \"This is file <identifier>:\" preceding the `BinaryContent`.\n\nIt's also included in inline-text delimiters for providers that require inlining text documents, so the model can\ndistinguish multiple files.","readOnly":true}},"type":"object","required":["data","media_type","identifier"],"title":"BinaryContent","description":"Binary content, e.g. an audio or image file."},"Body_inspect_import_api_v1_import_inspect_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"truncate":{"type":"boolean","title":"Truncate","default":false},"include_rows":{"type":"boolean","title":"Include Rows","default":false}},"type":"object","required":["file"],"title":"Body_inspect_import_api_v1_import_inspect_post"},"Body_inspect_import_for_project_api_v1_import__project_id__inspect_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"truncate":{"type":"boolean","title":"Truncate","default":false},"include_rows":{"type":"boolean","title":"Include Rows","default":false}},"type":"object","required":["file"],"title":"Body_inspect_import_for_project_api_v1_import__project_id__inspect_post"},"Body_upload_chat_attachment_api_v1_chat__project_id__attachment_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_chat_attachment_api_v1_chat__project_id__attachment_post"},"Body_upload_layer_api_v1_layer__project_id__upload_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"},"name":{"type":"string","maxLength":255,"title":"Name"},"truncate":{"type":"boolean","title":"Truncate","default":false},"ignore_geometry":{"type":"boolean","title":"Ignore Geometry","default":false}},"type":"object","required":["file","name"],"title":"Body_upload_layer_api_v1_layer__project_id__upload_post"},"BooleanCondition":{"properties":{"filterType":{"type":"string","const":"boolean","title":"Filtertype","default":"boolean"},"type":{"type":"string","enum":["blank","notBlank","equals","notEqual","unavailable"],"title":"Type"},"filter":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Filter"}},"type":"object","required":["type"],"title":"BooleanCondition"},"BudgetAuthority":{"type":"string","enum":["credits","discovery_allowance"],"title":"BudgetAuthority"},"BulkCancelEnrichmentRequest":{"properties":{"workflow_ids":{"items":{"type":"string"},"type":"array","maxItems":100000,"minItems":1,"title":"Workflow Ids"}},"type":"object","required":["workflow_ids"],"title":"BulkCancelEnrichmentRequest","description":"Bulk-cancel request body. The service chunks the reservation lookup\ninternally so callers don't have to. ``max_length`` is a DOS guard, not\na chunking signal."},"BulkExclusionRequest":{"properties":{"feature_ids":{"items":{"type":"string","maxLength":64,"minLength":1},"type":"array","maxItems":10000,"minItems":1,"title":"Feature Ids"},"source_layer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Source Layer Id"}},"type":"object","required":["feature_ids"],"title":"BulkExclusionRequest","description":"Bulk exclude/restore payload.\n\n``feature_ids`` accepts sandbox UUIDs and legacy bigint-as-string ids alike;\nlength caps match the ``row_exclusions.feature_id`` column so an oversized\nid is rejected at the boundary instead of raising mid-transaction. The list\ncap is the lockstep twin of the client's ``EXCLUSION_SELECTION_LIMIT``\n(``resolveSelectedFeatureIds.ts``) — the UI never sends more, so anything\nlarger is a runaway direct call, not a user action."},"BulkExclusionResult":{"properties":{"outcomes":{"items":{"$ref":"#/components/schemas/RowExclusionOutcome"},"type":"array","title":"Outcomes"},"excluded_count":{"type":"integer","title":"Excluded Count"}},"type":"object","required":["outcomes","excluded_count"],"title":"BulkExclusionResult","description":"Outcome of one bulk exclusion mutation.\n\n``excluded_count`` is the project's total excluded-row count after the\nwrite — the number the \"Excluded (n)\" surface renders."},"CachePoint":{"properties":{"kind":{"type":"string","const":"cache-point","title":"Kind","default":"cache-point"},"ttl":{"type":"string","enum":["5m","1h"],"title":"Ttl","default":"5m"}},"type":"object","title":"CachePoint","description":"A cache point marker for prompt caching.\n\nCan be inserted into UserPromptPart.content to mark cache boundaries.\nModels that don't support caching will filter these out.\n\nSupported by:\n\n- Anthropic\n- Amazon Bedrock (Converse API)\n- OpenAI (GPT-5.6 models)\n- OpenRouter (Anthropic and Gemini models via `OpenRouterModel`, plus OpenAI GPT-5.6 models when\n  using `OpenAIChatModel` or `OpenAIResponsesModel` with `OpenRouterProvider`)"},"CandidateLayer":{"properties":{"layer_id":{"type":"string","format":"uuid","title":"Layer Id"},"layer_name":{"type":"string","title":"Layer Name"},"already_in_layer":{"type":"boolean","title":"Already In Layer","default":false}},"type":"object","required":["layer_id","layer_name"],"title":"CandidateLayer","description":"A project layer the clicked feature could be added to.\n\nPopulated when more than one sandbox layer matches the feature's source\ntable, so the client can offer a target-layer picker instead of silently\nusing ``recommended_layer``. ``already_in_layer`` is True when the feature is\nalready a row in *this* layer — the client hides it from the picker so a user\ncan't pick a layer the feature is already in (which would fail the add)."},"CatalogContactsResponse":{"properties":{"key":{"type":"string","title":"Key"},"display_name":{"type":"string","title":"Display Name"},"tagline":{"type":"string","title":"Tagline"},"description":{"type":"string","title":"Description"},"compliance_note":{"type":"string","title":"Compliance Note"},"credits_per_row":{"type":"integer","title":"Credits Per Row"},"add_prompt":{"type":"string","title":"Add Prompt"}},"type":"object","required":["key","display_name","tagline","description","compliance_note","credits_per_row","add_prompt"],"title":"CatalogContactsResponse"},"CatalogCountyResponse":{"properties":{"county_fips":{"type":"string","title":"County Fips"},"name":{"type":"string","title":"Name"},"state":{"type":"string","title":"State"},"status":{"type":"string","enum":["loaded","loading","failed"],"title":"Status"}},"type":"object","required":["county_fips","name","state","status"],"title":"CatalogCountyResponse"},"CatalogDatasetResponse":{"properties":{"slug":{"type":"string","title":"Slug"},"display_name":{"type":"string","title":"Display Name"},"short_description":{"type":"string","title":"Short Description"},"description":{"type":"string","title":"Description"},"coverage_label":{"type":"string","title":"Coverage Label"},"unit_label":{"type":"string","title":"Unit Label"},"example_questions":{"items":{"type":"string"},"type":"array","title":"Example Questions"},"whats_included":{"type":"string","title":"Whats Included"},"good_to_know":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Good To Know"},"works_well_with":{"items":{"type":"string"},"type":"array","title":"Works Well With"},"add_prompt":{"type":"string","title":"Add Prompt"},"source_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Note"}},"type":"object","required":["slug","display_name","short_description","description","coverage_label","unit_label","example_questions","whats_included","good_to_know","works_well_with","add_prompt","source_note"],"title":"CatalogDatasetResponse"},"CatalogEnrichmentResponse":{"properties":{"key":{"type":"string","title":"Key"},"display_name":{"type":"string","title":"Display Name"},"tagline":{"type":"string","title":"Tagline"},"credits_per_row":{"type":"integer","title":"Credits Per Row"},"add_prompt":{"type":"string","title":"Add Prompt"}},"type":"object","required":["key","display_name","tagline","credits_per_row","add_prompt"],"title":"CatalogEnrichmentResponse"},"CatalogGroupResponse":{"properties":{"key":{"type":"string","title":"Key"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"last_updated":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Updated"},"datasets":{"items":{"$ref":"#/components/schemas/CatalogDatasetResponse"},"type":"array","title":"Datasets"}},"type":"object","required":["key","name","description","last_updated","datasets"],"title":"CatalogGroupResponse"},"CatalogResponse":{"properties":{"groups":{"items":{"$ref":"#/components/schemas/CatalogGroupResponse"},"type":"array","title":"Groups"},"enrichments":{"items":{"$ref":"#/components/schemas/CatalogEnrichmentResponse"},"type":"array","title":"Enrichments"},"contacts_enrichment":{"$ref":"#/components/schemas/CatalogContactsResponse"},"counties":{"items":{"$ref":"#/components/schemas/CatalogCountyResponse"},"type":"array","title":"Counties"}},"type":"object","required":["groups","enrichments","contacts_enrichment","counties"],"title":"CatalogResponse"},"CategoricalVizStats":{"properties":{"kind":{"type":"string","const":"categorical","title":"Kind","default":"categorical"},"categories":{"items":{"$ref":"#/components/schemas/VizCategory"},"type":"array","title":"Categories"},"other_count":{"type":"integer","title":"Other Count"},"null_count":{"type":"integer","title":"Null Count"},"count":{"type":"integer","title":"Count"},"geometry_kind":{"anyOf":[{"type":"string","enum":["point","line","polygon"]},{"type":"null"}],"title":"Geometry Kind"}},"type":"object","required":["categories","other_count","null_count","count","geometry_kind"],"title":"CategoricalVizStats","description":"Whole-layer stats for one boolean or text column, for classed map styling.\n\n``categories`` is the top slice by count (descending, ties broken by value\nascending); anything past the cap is summed into ``other_count``. NULL and\nempty string are never categories — they are one \"no value\" class carried\nby ``null_count``. ``count`` is the non-null population, so\n``count - sum(categories) == other_count``."},"ChatArchiveMetadataResponseSchema":{"properties":{"archives":{"items":{"$ref":"#/components/schemas/ArchiveMetadataSchema"},"type":"array","title":"Archives","description":"Metadata for each archive of the chat session, no bodies."}},"type":"object","required":["archives"],"title":"ChatArchiveMetadataResponseSchema","description":"Schema for the bounded chat archive metadata response."},"ChatAttachmentPayload":{"properties":{"attachmentId":{"type":"string","title":"Attachmentid"},"filename":{"type":"string","title":"Filename"},"mediaType":{"type":"string","title":"Mediatype"},"byteSize":{"type":"integer","title":"Bytesize"}},"type":"object","required":["attachmentId","filename","mediaType","byteSize"],"title":"ChatAttachmentPayload","description":"The receipt stamped onto a user turn's ``ModelRequest.metadata``.\n\nOnce the turn is persisted this is the only record that a document was ever\nattached: the bytes are dehydrated out of the message before the row is\nwritten, and the frontend renders its attachment pill from this alone."},"ChatAttachmentResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"filename":{"type":"string","title":"Filename"},"media_type":{"type":"string","title":"Media Type"},"byte_size":{"type":"integer","title":"Byte Size"}},"type":"object","required":["id","filename","media_type","byte_size"],"title":"ChatAttachmentResponse","description":"The stored document a client references on its next chat turn."},"ChatFeedbackRequest":{"properties":{"message_id":{"type":"string","title":"Message Id","description":"The ID of the message being rated."},"feedback_type":{"type":"string","enum":["positive","negative"],"title":"Feedback Type","description":"Type of feedback ('positive' or 'negative')."},"feedback_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feedback Text","description":"Optional free text feedback."},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Id","description":"Optional project ID."}},"type":"object","required":["message_id","feedback_type"],"title":"ChatFeedbackRequest","description":"Schema for chat feedback requests."},"ChatFeedbackResponse":{"properties":{"status":{"type":"string","title":"Status","default":"received"},"message":{"type":"string","title":"Message","default":"Feedback received successfully."}},"type":"object","title":"ChatFeedbackResponse","description":"Schema for chat feedback responses."},"ChatHistoryResponseSchema":{"properties":{"chat":{"anyOf":[{"$ref":"#/components/schemas/ChatHistorySchema"},{"type":"null"}],"description":"The chat history for the project, or None if no chat exists."},"users":{"additionalProperties":{"$ref":"#/components/schemas/ChatUserInfo"},"type":"object","title":"Users","description":"Map of user_id to display info for message attribution."}},"type":"object","required":["chat"],"title":"ChatHistoryResponseSchema","description":"Schema for the chat history of a project."},"ChatHistorySchema":{"properties":{"project_id":{"type":"string","title":"Project Id"},"chat_history":{"items":{"oneOf":[{"$ref":"#/components/schemas/ModelRequest"},{"$ref":"#/components/schemas/ModelResponse"}],"discriminator":{"propertyName":"kind","mapping":{"request":"#/components/schemas/ModelRequest","response":"#/components/schemas/ModelResponse"}}},"type":"array","title":"Chat History"},"active_run_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Active Run Id","description":"Workflow id of a currently-live chat run for this project, or None. Populated only when a run is genuinely in flight (DBOS ACTIVE) — the FE uses it to re-attach to the durable stream after a mid-run page refresh instead of showing static (pre-completion) history."},"last_turn_continuable":{"type":"boolean","title":"Last Turn Continuable","description":"True when the most recent persisted turn failed terminally mid-way and left a continuable partial. The FE renders the Continue affordance on the last turn after a refresh, when the live partial_result terminal frame is no longer available.","default":false},"selected_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Model","description":"The chat's persisted model-picker selection (a curated picker key), or None for the default chain. Seeds the composer dropdown."},"selected_thinking":{"anyOf":[{"$ref":"#/components/schemas/MainAgentThinking"},{"type":"null"}],"description":"The chat's persisted thinking setting for selected_model."}},"type":"object","required":["project_id","chat_history"],"title":"ChatHistorySchema","description":"Schema for a single chat with its full history."},"ChatInterruptRequest":{"properties":{"project_id":{"type":"string","title":"Project Id","description":"The project ID to interrupt."},"reason":{"type":"string","title":"Reason","description":"Reason for interruption (e.g., 'user_requested', 'timeout', 'error').","default":"user_requested"}},"type":"object","required":["project_id"],"title":"ChatInterruptRequest","description":"Schema for chat interrupt requests."},"ChatInterruptResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Whether the interrupt was successful."},"message":{"type":"string","title":"Message","description":"Status message."},"was_active":{"type":"boolean","title":"Was Active","description":"Whether the chat stream was active when interrupt was requested."}},"type":"object","required":["success","message","was_active"],"title":"ChatInterruptResponse","description":"Schema for chat interrupt responses."},"ChatModelOption":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"is_default":{"type":"boolean","title":"Is Default"},"thinking_levels":{"items":{"$ref":"#/components/schemas/MainAgentThinking"},"type":"array","title":"Thinking Levels"}},"type":"object","required":["key","label","is_default","thinking_levels"],"title":"ChatModelOption","description":"One curated model-picker option (see GET /chat/models)."},"ChatModelsResponse":{"properties":{"models":{"items":{"$ref":"#/components/schemas/ChatModelOption"},"type":"array","title":"Models"}},"type":"object","required":["models"],"title":"ChatModelsResponse","description":"Curated model-picker options for the chat composer dropdown."},"ChatNoteRequest":{"properties":{"content":{"type":"string","maxLength":2000,"minLength":1,"title":"Content","description":"The summary text to persist as an assistant message."}},"type":"object","required":["content"],"title":"ChatNoteRequest","description":"A deterministic action summary to append to the project's chat history."},"ChatNoteResponse":{"properties":{"recorded":{"type":"boolean","title":"Recorded","description":"True when the note was persisted to the chat."}},"type":"object","required":["recorded"],"title":"ChatNoteResponse","description":"Result of appending an action summary to the chat history."},"ChatRequest":{"properties":{"message":{"type":"string","maxLength":20000,"title":"Message"},"project_id":{"type":"string","format":"uuid","title":"Project Id","examples":["00000000-0000-0000-0000-000000000001"]},"current_focused_layer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Current Focused Layer Id","examples":["00000000-0000-0000-0000-000000000000"]},"action_type":{"anyOf":[{"$ref":"#/components/schemas/ActionType"},{"type":"null"}]},"action_subtype":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action Subtype","description":"Optional preset identifier that disambiguates actions sharing an action_type. For detail-panel presets, matches the client-side noteSource (e.g. 'environment', 'zoning', 'summary')."},"hidden_context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Hidden Context"},"current_view_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current View Id"},"iterate_over_rows":{"type":"boolean","title":"Iterate Over Rows","default":false},"selected_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selected Model","description":"Model-picker selection for this chat (a curated picker key, see GET /chat/models). Persisted on the chat; honored only when the workspace's model-picker feature toggle is on."},"selected_thinking":{"anyOf":[{"$ref":"#/components/schemas/MainAgentThinking"},{"type":"null"}],"description":"Provider-native thinking setting for selected_model. Auto uses the selected provider's native default. Persisted with the model choice."},"feature_context":{"anyOf":[{"$ref":"#/components/schemas/FeatureContext"},{"type":"null"}]},"mentioned_feature_contexts":{"anyOf":[{"items":{"$ref":"#/components/schemas/FeatureContext"},"type":"array"},{"type":"null"}],"title":"Mentioned Feature Contexts"},"prior_answer":{"anyOf":[{"$ref":"#/components/schemas/InteractiveQuestionAnswer"},{"type":"null"}],"description":"When the user answers a structured question by clicking a button (deterministic-alias path), the FE sends the chosen option here alongside the label as `message`. The endpoint writes this onto the prior question's `metadata.interactive_question_answer` so the agent's Authority rule treats it as ground truth and the reload path reads it off the typed field instead of reconstructing from the user-reply text."},"tool_approval":{"anyOf":[{"$ref":"#/components/schemas/ToolApprovalAnswer"},{"type":"null"}],"description":"Approve/decline for a pending requires_approval tool call (save_skill / update_skill). Rides the same round-trip as prior_answer: the endpoint marks the prior pending message answered in metadata (flipping the card inert on reload) and the workflow resumes the deferred run with the result. `message` may be empty on an approval turn."},"continue_turn":{"type":"boolean","title":"Continue Turn","description":"Continue a terminally-failed turn from its persisted partial without a new prompt. The FE sends an empty `message` and the endpoint runs a promptless turn on the persisted history (the same no-user-bubble shape as a tool approval, minus the approval payload) so the agent resumes where it left off.","default":false},"attachment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Attachment Id","description":"A document previously uploaded to this project's chat via POST /chat/{project_id}/attachment. The agent receives it as a native document alongside `message`; the turn's persisted history keeps only a reference, so a later turn can read the same document without re-uploading it."}},"type":"object","required":["message","project_id"],"title":"ChatRequest"},"ChatResumeRequest":{"properties":{"project_id":{"type":"string","format":"uuid","title":"Project Id","description":"The project whose live chat run to re-attach to."},"expected_run_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expected Run Id","description":"The run id the chat GET reported as active. The reattach tails this run only; if the pointer has since moved to a newer run, the server yields nothing so the client reloads persisted history. Omit to tail whatever run is currently active."}},"type":"object","required":["project_id"],"title":"ChatResumeRequest","description":"Schema for re-attaching to a project's in-flight chat run (refresh-resume)."},"ChatStopReason":{"type":"string","enum":["user_requested","timeout","lock_lost"],"title":"ChatStopReason","description":"Why a chat run was stopped — the cooperative flag's reason taxonomy.\n\nCarried in the Redis stop flag and, on the monitor's escalation path, in the\ndurable stop event. ``USER_REQUESTED`` (and any unknown reason) synthesizes\nthe generic ``interrupted`` terminal; the two monitor-initiated reasons get\ntheir specific error copy."},"ChatSummarizationCompletedEvent":{"properties":{"type":{"type":"string","const":"chat_summarization_completed","title":"Type","default":"chat_summarization_completed"},"projectId":{"type":"string","format":"uuid","title":"Projectid"}},"type":"object","required":["projectId"],"title":"ChatSummarizationCompletedEvent","description":"Fired when a chat's background ``summarize_workflow`` finishes persisting.\n\nSummarization runs as a fire-and-forget DBOS workflow after a turn crosses\nthe context threshold; the turn's ``complete`` SSE frame (carrying\n``summarization_task_id``) is the *enqueue* moment, ~50s before the summary\nactually generates + persists. The original turn's direct stream has closed\nby then, so this advisory event over the per-user fanout is how the client\nlearns the summary is genuinely done and renders the \"summarized\" divider.\n\nAdvisory only — the durable summary is the source of truth: on reload the FE\nreconstructs the divider from persisted history (``detectSummarization``), so\na dropped publish degrades to \"divider appears on next reload,\" never a stuck\nstate.\n\nCarries only ``projectId`` (camelCase wire shape, matching\n``ViewStateChangedEvent`` / ``LayerStateChangedEvent``): ``chats.project_id``\nis UNIQUE (one chat per project), so the project anchors the chat and the FE\nneeds no ``chat_id`` to route."},"ChatUserInfo":{"properties":{"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"avatar_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Color"}},"type":"object","title":"ChatUserInfo","description":"Sender info for chat message attribution."},"ColumnDataType":{"type":"string","enum":["string","number","integer","boolean","date","geometry","array","object"],"title":"ColumnDataType","description":"Optional frontend type hint for a layer column."},"ColumnDetail":{"properties":{"name":{"type":"string","title":"Name"},"pg_type":{"type":"string","title":"Pg Type"},"type":{"type":"string","title":"Type"},"source":{"type":"string","enum":["base","enrichment","agent"],"title":"Source"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"categorical_options":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Categorical Options"},"stats":{"$ref":"#/components/schemas/ColumnStats"},"enrichment":{"anyOf":[{"$ref":"#/components/schemas/EnrichmentColumnConfig"},{"type":"null"}]},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"}},"type":"object","required":["name","pg_type","type","source","stats"],"title":"ColumnDetail","description":"Rich per-column metadata for the columns endpoint."},"ColumnKind":{"type":"string","enum":["source","merged","enrichment","system","agent_derived"],"title":"ColumnKind","description":"Provenance discriminator for a layer column.\n\n* `source` — column SELECTed directly from the canonical Overture table.\n* `merged` — column joined in from another canonical source table (e.g.\n  `parcel_owner` on a building layer joined parcel data).\n* `enrichment` — populated by an enrichment runner, not the agent's SQL.\n  (Reserved for the upcoming enrichment unification — not used yet.)\n* `system` — agent-facing hide-by-default escape for lineage columns\n  merged for enrichment plumbing the user shouldn't see by default\n  (e.g. parcel address fields plumbed onto a building layer for Owner\n  Contact Info). Stays in the registered schema and can be surfaced\n  later via `update_view`.\n* `agent_derived` — computed in the agent's SQL (`SUM(...) AS total`,\n  `CASE WHEN ... END AS bucket`). Still requires source_table+source_column\n  anchoring so view deltas survive a column rename."},"ColumnMeta":{"properties":{"type":{"type":"string","title":"Type"},"source":{"type":"string","enum":["base","enrichment","agent"],"title":"Source"},"enrichment_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enrichment Id"},"sidecar_column":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sidecar Column"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"}},"type":"object","required":["type","source"],"title":"ColumnMeta","description":"Per-column metadata returned on the first page.\n\n``sidecar_column`` is set only for enrichment columns and names the typed\n`additions` column (`value_text` / `value_numeric` /\n`value_boolean` / `value_jsonb`) that drives sort and filter.\n\n``display_name`` is the user-facing header name. Resolved via\n``get_column_display_names`` so dotted paths produced by JSONB flattening\n(``names.primary``, ``addresses.list.0.element.postcode``) map to the same\nfriendly names the legacy pre-SSR table used; user overrides on\n``LayerColumn.display_name`` win on key conflict."},"ColumnProvenance":{"properties":{"kind":{"$ref":"#/components/schemas/ColumnKind"},"source_table":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Table","description":"Canonical Overture table this column derives from — or, for imported layers (file upload / GIS fetch / all-rows import), the sandbox relation itself, which is the only source the data has. None for fully derived (composite) columns with no canonical lineage."},"source_column":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Column","description":"Canonical column path on `source_table` (e.g. `names.primary`). Used by the resolver for display-name lookup and stable column ids — NOT the agent's SQL alias."}},"type":"object","required":["kind"],"title":"ColumnProvenance","description":"Where a column came from and how to look up its canonical metadata.\n\n`source_column` is the canonical Overture column path (e.g.\n`names.primary`, not the agent's SQL alias `name`). The resolver uses it\nto look up the display label and to derive a rename-stable column id —\nmaking alias mismatches impossible by construction."},"ColumnRole":{"type":"string","enum":["stat","other"],"title":"ColumnRole","description":"Narrow detail-panel placement signal, orthogonal to ``semantic_type``.\n\nThe one signal that cannot be derived from ``semantic_type``: parcel\n``parval`` and ``improvval`` are both ``CURRENCY``, but only ``parval`` is\na headline stat. ``role`` carries that; ``semantic_type`` carries\ncontent/format. Ordering and visibility live on the *view*, not here."},"ColumnStats":{"properties":{"total_rows":{"type":"integer","title":"Total Rows"},"enriched_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Enriched Count"},"unenriched_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Unenriched Count"}},"type":"object","required":["total_rows"],"title":"ColumnStats","description":"Aggregate counts for one column.\n\nOnly enrichment columns carry ``enriched_count``/``unenriched_count`` (from\nthe ``additions`` sidecar). Base columns carry ``total_rows`` alone."},"ColumnsMetadataResponse":{"properties":{"tile_url_template":{"type":"string","title":"Tile Url Template"},"total_rows":{"type":"integer","title":"Total Rows"},"columns":{"additionalProperties":{"$ref":"#/components/schemas/ColumnDetail"},"type":"object","title":"Columns"}},"type":"object","required":["tile_url_template","total_rows","columns"],"title":"ColumnsMetadataResponse","description":"Response for GET /table/{layer_id}/columns.\n\n``tile_url_template`` is a literal template; the client substitutes\n``{layer_id}`` before handing the URL to Mapbox."},"CompactionPart":{"properties":{"content":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"compaction","title":"Part Kind","default":"compaction"}},"type":"object","title":"CompactionPart","description":"A compaction part that summarizes previous conversation history.\n\nCompaction parts contain an opaque or readable summary of prior messages,\nproduced by provider-specific compaction mechanisms. They must be round-tripped\nback to the same provider in subsequent requests.\n\nFor Anthropic, `content` contains a readable text summary.\nFor OpenAI, `content` is `None` and the encrypted data is stored in `provider_details`."},"CompoundFilter-Input":{"properties":{"filterType":{"type":"string","enum":["text","number","set","date","boolean"],"title":"Filtertype"},"operator":{"type":"string","enum":["AND","OR"],"title":"Operator"},"conditions":{"items":{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Input"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},"type":"array","title":"Conditions"},"condition1":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Input"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},{"type":"null"}],"title":"Condition1"},"condition2":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Input"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},{"type":"null"}],"title":"Condition2"}},"type":"object","required":["filterType","operator"],"title":"CompoundFilter"},"CompoundFilter-Output":{"properties":{"filterType":{"type":"string","enum":["text","number","set","date","boolean"],"title":"Filtertype"},"operator":{"type":"string","enum":["AND","OR"],"title":"Operator"},"conditions":{"items":{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Output"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},"type":"array","title":"Conditions"},"condition1":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Output"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},{"type":"null"}],"title":"Condition1"},"condition2":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Output"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},{"type":"null"}],"title":"Condition2"}},"type":"object","required":["filterType","operator"],"title":"CompoundFilter"},"ConfirmQuestionPayload":{"properties":{"type":{"type":"string","const":"confirm","title":"Type","default":"confirm"},"id":{"type":"string","title":"Id"},"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt"},"yesLabel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Yeslabel"},"noLabel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nolabel"},"destructive":{"type":"boolean","title":"Destructive","default":false},"sourceTable":{"anyOf":[{"$ref":"#/components/schemas/SourceTable"},{"type":"null"}],"description":"REQUIRED when this confirm proposes adding the single resolve_to_feature candidate: the candidate's source_table. Carries the feature binding so a 'yes' adds it as a map layer. Leave unset for ordinary yes/no questions, skill proposals, and view offers."},"featureId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Featureid","description":"REQUIRED with sourceTable: the resolved candidate's id."},"featureLabel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Featurelabel","description":"REQUIRED with sourceTable: the candidate's readable label. Names the layer the 'yes' creates; the system overwrites it with the hydrated label, so a fabricated value can't mislabel the layer."},"skillId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Skillid","description":"REQUIRED when this confirm question proposes running a skill: set to the matched catalog entry's id so the proposal links to the skill. Leave unset for ordinary yes/no questions."},"viewOffer":{"anyOf":[{"$ref":"#/components/schemas/ViewOfferPreview"},{"type":"null"}],"description":"REQUIRED when this confirm question proactively offers to save the current set as a View: carry the proposed name and a summary of what will be saved. Leave unset for ordinary yes/no questions and for skill proposals."}},"type":"object","required":["id"],"title":"ConfirmQuestionPayload"},"ContactCheckResponse":{"properties":{"saved_feature_contacts":{"additionalProperties":{"items":{"$ref":"#/components/schemas/SavedContactIdentity"},"type":"array"},"type":"object","title":"Saved Feature Contacts"}},"type":"object","required":["saved_feature_contacts"],"title":"ContactCheckResponse","description":"Maps feature_id -> list of saved contact identities (id + full_name + work_email)."},"ContactIdentityEvidence":{"properties":{"identity":{"type":"string","enum":["corroborated","single_source","conflicting"],"title":"Identity","description":"corroborated: at least two independent sources agree this is the person. single_source: one source reported it and nothing independent confirms it. conflicting: the name disagrees with the record's owner or target person."},"identity_basis":{"type":"string","title":"Identity Basis","description":"What establishes (or undermines) the identity, in one sentence."},"corroborating_sources":{"items":{"type":"string"},"type":"array","title":"Corroborating Sources","description":"Named independent sources backing the identity. At least two distinct sources are required to declare 'corroborated'."},"reachability_source":{"anyOf":[{"type":"string","enum":["property_records","published","both"]},{"type":"null"}],"title":"Reachability Source","description":"Where the phone/email came from; 'both' means both source types were used. A vendor match score is not evidence a number is reachable."}},"type":"object","required":["identity","identity_basis"],"title":"ContactIdentityEvidence","description":"How this contact's identity was established, as a typed claim.\n\n``corroborated`` is reserved for identities at least two independent\nsources agree on. The validator enforces a floor — two distinct non-empty\nsource *strings* — so a bare or duplicated claim cannot be represented;\nwhether the named sources are genuinely independent remains the agent's\nassertion. ``single_source``\nstates exactly what an unconfirmed vendor return is. ``conflicting``\nflags a name that disagrees with the record's owner or target person."},"ContactModel":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id","description":"Unique identifier for the contact. Required for PDL contacts, auto-generated for web search contacts."},"full_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Full Name"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"middle_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Middle Name"},"middle_initial":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Middle Initial"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"last_initial":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Initial"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"job_title_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title Role"},"job_title_sub_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title Sub Role"},"job_title_levels":{"items":{"type":"string"},"type":"array","title":"Job Title Levels"},"job_title_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title Class"},"job_company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Name"},"job_company_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Id"},"job_company_website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Website"},"job_company_size":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Size"},"job_company_industry":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Industry"},"job_company_location_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Location Name"},"job_company_location_locality":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Location Locality"},"job_company_location_region":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Location Region"},"job_company_location_country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Location Country"},"job_start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Start Date"},"job_last_changed":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Last Changed"},"job_last_verified":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Last Verified"},"linkedin_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Url"},"linkedin_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Username"},"linkedin_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Id"},"has_email":{"type":"boolean","title":"Has Email","default":false},"has_phone":{"type":"boolean","title":"Has Phone","default":false},"has_personal_email":{"type":"boolean","title":"Has Personal Email","default":false},"has_work_email":{"type":"boolean","title":"Has Work Email","default":false},"has_mobile_phone":{"type":"boolean","title":"Has Mobile Phone","default":false},"work_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Email"},"personal_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Personal Email"},"mobile_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mobile Phone"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"location_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Name"},"location_locality":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Locality"},"location_region":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Region"},"location_country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Country"},"location_continent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Continent"},"twitter_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Twitter Url"},"twitter_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Twitter Username"},"facebook_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Facebook Url"},"facebook_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Facebook Username"},"github_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Github Url"},"github_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Github Username"},"industry":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Industry"},"sex":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sex"},"age_range":{"anyOf":[{"$ref":"#/components/schemas/AgeRange"},{"type":"null"}]},"skills":{"items":{"type":"string"},"type":"array","title":"Skills"},"interests":{"items":{"type":"string"},"type":"array","title":"Interests"},"tenure":{"anyOf":[{"$ref":"#/components/schemas/TenureRange"},{"type":"null"}]},"ownership_duration":{"anyOf":[{"$ref":"#/components/schemas/OwnershipDuration"},{"type":"null"}]},"identity_evidence":{"anyOf":[{"$ref":"#/components/schemas/ContactIdentityEvidence"},{"type":"null"}]},"experience":{"items":{"$ref":"#/components/schemas/PDLExperience"},"type":"array","title":"Experience"},"education":{"items":{"$ref":"#/components/schemas/PDLEducation"},"type":"array","title":"Education"},"profiles":{"items":{"$ref":"#/components/schemas/PDLProfile"},"type":"array","title":"Profiles"},"dataset_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dataset Version"}},"type":"object","title":"ContactModel","description":"Person contact model parsed from PDL Person Search API.\n\nThis model represents a person with their contact information,\ncurrent job, work history, and education."},"ContactSyncResponse":{"properties":{"created":{"type":"integer","title":"Created"},"updated":{"type":"integer","title":"Updated"},"unchanged":{"type":"integer","title":"Unchanged"},"stale":{"type":"integer","title":"Stale"},"removed":{"type":"integer","title":"Removed"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["created","updated","unchanged","stale","removed","total"],"title":"ContactSyncResponse"},"ContextFallbackReason":{"type":"string","enum":["empty","unavailable","load_failed"],"title":"ContextFallbackReason"},"ContextMode":{"type":"string","enum":["internal","selected","fallback"],"title":"ContextMode"},"CopyLayerParameters":{"properties":{"source_table_name":{"type":"string","title":"Source Table Name","description":"Name of the source Overture table (e.g., 'building', 'place')"},"columns_to_copy":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Columns To Copy","description":"List of column names to copy (if None, copies all non-geometry columns)"},"column_filters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Column Filters","description":"Dictionary of column_name: value filters for data filtering"}},"type":"object","required":["source_table_name"],"title":"CopyLayerParameters","description":"Parameters for creating a layer from an Overture/core data table.\n\nDefines the source table, column selection, and filters used by the layer\ncreation pipeline. target_layer_id and reference_layer_id are provided separately."},"CostCompleteness":{"type":"string","enum":["priced","unpriced","unmeasured"],"title":"CostCompleteness"},"CountyLoadStatsResponse":{"properties":{"median_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Median Seconds"},"p90_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"P90 Seconds"},"sample_size":{"type":"integer","title":"Sample Size"}},"type":"object","required":["median_seconds","p90_seconds","sample_size"],"title":"CountyLoadStatsResponse","description":"Aggregate county-load duration stats for the admin ETA display.\n\nSeconds from request to completion over recent succeeded loads;\n`median_seconds` / `p90_seconds` are null when `sample_size` is 0."},"CountyOption":{"properties":{"fips":{"type":"string","title":"Fips"},"name":{"type":"string","title":"Name"},"state":{"type":"string","title":"State"}},"type":"object","required":["fips","name","state"],"title":"CountyOption","description":"A FIPS county available for geography restriction."},"CountyPrewarmResponse":{"properties":{"scheduled":{"type":"boolean","title":"Scheduled"},"tile_count":{"type":"integer","title":"Tile Count"}},"type":"object","required":["scheduled","tile_count"],"title":"CountyPrewarmResponse","description":"Outcome of scheduling a county's preview tiles.\n\n``scheduled`` is False when the county has no boundary on file — the caller\ntreats that as \"no preview available\" rather than an error, because a\nmissing boundary is an unseeded environment, not a bad request."},"CoveredCounty":{"properties":{"geoid":{"type":"string","title":"Geoid"},"statefp":{"type":"string","title":"Statefp"},"countyfp":{"type":"string","title":"Countyfp"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"owning_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owning Source"},"source_kind":{"anyOf":[{"$ref":"#/components/schemas/ParcelSourceKind"},{"type":"null"}]},"source_class":{"anyOf":[{"$ref":"#/components/schemas/ParcelSourceClass"},{"type":"null"}]},"batchdata_match_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Batchdata Match Rate"},"apn_match_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Apn Match Rate"},"spatial_match_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Spatial Match Rate"},"bd_rows":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bd Rows"},"zoning_rows":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Zoning Rows"},"zoning_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Zoning Rate"},"zoning_sourced_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Zoning Sourced Rate"},"measured_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Measured At"},"last_refreshed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Refreshed At"}},"type":"object","required":["geoid","statefp","countyfp"],"title":"CoveredCounty","description":"One county with BatchData-verified parcel coverage, plus its source\nprovenance and join-quality from ``parcel_source_registry``.\n\nProvenance fields are populated today; the measurement fields stay ``null``\nuntil the coverage recorder measures the county (the viewer renders those as\n\"not yet measured\"). All are optional — a covered county with no registry\nrow still serializes.\n\n``zoning_sourced_rate`` 0.0 on a measured county means no zoning arrived with the\ngeometry MAIA sources for it, so every designation it holds came from the vendor — which\nis what makes it a candidate for the sourcing rollout. The vendor-only share is\n``zoning_rate - zoning_sourced_rate``, derived here rather than stored."},"CreateEnrichmentRequest":{"properties":{"project_id":{"type":"string","format":"uuid","title":"Project Id","examples":["00000000-0000-0000-0000-000000000001"]},"layer_id":{"type":"string","format":"uuid","title":"Layer Id","examples":["00000000-0000-0000-0000-000000000000"]}},"type":"object","required":["project_id","layer_id"],"title":"CreateEnrichmentRequest","description":"Request schema for creating an enrichment.\n\nAttributes:\n    project_id: Unique identifier for the project"},"CreateLayerFailure":{"properties":{"message":{"type":"string","title":"Message","description":"A detailed message explaining why layer creation failed or what information is needed to try again. Include information about the strategy taken and why it failed. Suggest alternative strategies that could be tried. Limit to 100 words."}},"type":"object","required":["message"],"title":"CreateLayerFailure","description":"Model for a layer creation failure."},"CreateLayerFromFeatureRequest":{"properties":{"source_table":{"$ref":"#/components/schemas/SourceTable"},"source_feature_id":{"type":"string","title":"Source Feature Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"accumulate":{"type":"boolean","title":"Accumulate","default":false},"target_layer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Layer Id"}},"type":"object","required":["source_table","source_feature_id"],"title":"CreateLayerFromFeatureRequest","description":"Request to create a new typed layer seeded with one Overture feature."},"CreateLayerFromFeatureResponse":{"properties":{"layer_id":{"type":"string","format":"uuid","title":"Layer Id"},"layer_name":{"type":"string","title":"Layer Name"},"created":{"type":"boolean","title":"Created","default":true},"data_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Data Version"}},"type":"object","required":["layer_id","layer_name"],"title":"CreateLayerFromFeatureResponse","description":"Response for creating a new typed layer seeded with one Overture feature.\n\nReturned when the user adds a nearby feature whose Overture table has no\nlayer in the project yet; the client uses ``layer_id`` to focus/refresh the\nnewly created layer."},"CreateLayerSuccess":{"properties":{"message":{"type":"string","title":"Message","description":"Success message explaining the recommended layer configuration"},"copy_parameters":{"$ref":"#/components/schemas/CopyLayerParameters","description":"Parameters to use with copy_from_overture_table_by_layer_geometry function"},"layer_description":{"type":"string","title":"Layer Description","description":"One-sentence description of what this layer contains and its purpose"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Any caveats or limitations that should be considered when using this layer. Include information about the strategy taken to create the layer and any issues that had occured. Limit to 100 words. Omit if there are no issues."}},"type":"object","required":["message","copy_parameters","layer_description"],"title":"CreateLayerSuccess","description":"Successful layer creation result with copy parameters."},"CreditBalance":{"properties":{"total":{"type":"integer","title":"Total"},"used":{"type":"integer","title":"Used"},"remaining":{"type":"integer","title":"Remaining"}},"type":"object","required":["total","used","remaining"],"title":"CreditBalance","description":"Credit balance breakdown for a workspace.\n\nUses pool accounting: total is the credits ever granted (never decremented),\nused is cumulative consumption, remaining = total - used."},"CreditStateChangedEvent":{"properties":{"type":{"type":"string","const":"credit_state_changed","title":"Type","default":"credit_state_changed"}},"type":"object","title":"CreditStateChangedEvent","description":"Fired when a workspace credit total changes (reserve / commit / refund).\n\nPayload-less by design: the FE invalidates the credits query and\nrefetches the authoritative state. Keeps the channel cheap (one short\nJSON per transition) and frees the publisher from needing to compute\nworkspace totals at emit time."},"DateCondition":{"properties":{"filterType":{"type":"string","const":"date","title":"Filtertype","default":"date"},"type":{"type":"string","enum":["blank","notBlank","inRange","equals","notEqual","lessThan","greaterThan","unavailable"],"title":"Type"},"dateFrom":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Datefrom"},"dateTo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dateto"}},"type":"object","required":["type"],"title":"DateCondition"},"DialAgentSettings":{"properties":{"voicemail_message":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Voicemail Message"},"intro_line":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Intro Line"},"transfer_pitch":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Transfer Pitch"}},"additionalProperties":false,"type":"object","title":"DialAgentSettings","description":"Per-workspace overrides for placeholders in the Retell agent flow.\n\nEach field maps to a `{{placeholder}}` in the Retell flow config. Unset\nfields are omitted at dispatch so the flow node's baked-in default applies."},"DialAgentSettingsUpdateRequest":{"properties":{"voicemail_message":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Voicemail Message"},"intro_line":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Intro Line"},"transfer_pitch":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Transfer Pitch"}},"type":"object","title":"DialAgentSettingsUpdateRequest","description":"Request model for updating per-workspace dial agent prompt overrides.\n\nAll fields optional; pass `null` to clear an individual override and let\nthe Retell flow node's baked-in default apply.\n\n`{{variable_name}}` placeholders are allowed inside each field; the\nhandler validates them against the allowed-variable registry and\nreturns 422 with the offending names when an unknown variable is used."},"DialCallListResponse":{"properties":{"calls":{"items":{"$ref":"#/components/schemas/DialCallResponse"},"type":"array","title":"Calls"}},"type":"object","required":["calls"],"title":"DialCallListResponse"},"DialCallResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"saved_contact_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Saved Contact Id"},"started_by":{"type":"string","format":"uuid","title":"Started By"},"campaign_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Id"},"retell_call_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Retell Call Id"},"to_number":{"type":"string","title":"To Number"},"transfer_destination":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transfer Destination"},"status":{"type":"string","title":"Status"},"outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outcome"},"disconnect_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Disconnect Reason"},"transcript":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transcript"},"recording_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recording Url"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ended At"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"last_event_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Event Type"},"contact_outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Outcome"},"interest_topics":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Interest Topics"},"interest_unclear":{"type":"boolean","title":"Interest Unclear"},"callback_window":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Callback Window"},"notes_for_rep":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes For Rep"},"requested_dnc":{"type":"boolean","title":"Requested Dnc"},"disclosure_acknowledged":{"type":"boolean","title":"Disclosure Acknowledged"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"saved_contact_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Saved Contact Name"}},"type":"object","required":["id","workspace_id","project_id","saved_contact_id","started_by","campaign_id","retell_call_id","to_number","transfer_destination","status","outcome","disconnect_reason","transcript","recording_url","started_at","ended_at","duration_seconds","last_event_type","contact_outcome","interest_topics","interest_unclear","callback_window","notes_for_rep","requested_dnc","disclosure_acknowledged","created_at","updated_at"],"title":"DialCallResponse","description":"API response — inherits DialCall, hides the internal `events_log`."},"DialCampaignDetailResponse":{"properties":{"campaign":{"$ref":"#/components/schemas/DialCampaignResponse"},"calls":{"items":{"$ref":"#/components/schemas/DialCallResponse"},"type":"array","title":"Calls"}},"type":"object","required":["campaign","calls"],"title":"DialCampaignDetailResponse"},"DialCampaignListResponse":{"properties":{"campaigns":{"items":{"$ref":"#/components/schemas/DialCampaignResponse"},"type":"array","title":"Campaigns"}},"type":"object","required":["campaigns"],"title":"DialCampaignListResponse"},"DialCampaignResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"started_by":{"type":"string","format":"uuid","title":"Started By"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"status":{"type":"string","title":"Status"},"contact_count":{"type":"integer","title":"Contact Count"},"transfer_destination":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transfer Destination"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","workspace_id","project_id","started_by","name","status","contact_count","transfer_destination","completed_at","created_at","updated_at"],"title":"DialCampaignResponse"},"DialTemplateVariable":{"properties":{"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"}},"type":"object","required":["name","description"],"title":"DialTemplateVariable","description":"Single entry in the dial-prompt template-variable registry."},"DialTemplateVariablesResponse":{"properties":{"variables":{"items":{"$ref":"#/components/schemas/DialTemplateVariable"},"type":"array","title":"Variables"}},"type":"object","required":["variables"],"title":"DialTemplateVariablesResponse","description":"Available template variables for `dial_agent_settings` overrides.\n\nReturned by `GET /workspaces/dial-template-variables`. The FE\nautocomplete menu reads this directly so client and server can't\ndrift on the supported set."},"DialUsageResponse":{"properties":{"period_start":{"type":"string","format":"date","title":"Period Start"},"total_calls":{"type":"integer","title":"Total Calls"},"total_minutes":{"type":"integer","title":"Total Minutes"},"transferred_calls":{"type":"integer","title":"Transferred Calls"},"monthly_dial_minute_cap":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Monthly Dial Minute Cap"}},"type":"object","required":["period_start","total_calls","total_minutes","transferred_calls"],"title":"DialUsageResponse","description":"Per-period dial usage rollup for billing/cap display."},"DigestPeriodKind":{"type":"string","enum":["week","month"],"title":"DigestPeriodKind"},"DigestPeriodOptionResponse":{"properties":{"kind":{"$ref":"#/components/schemas/DigestPeriodKind"},"start":{"type":"string","format":"date","title":"Start"},"label":{"type":"string","title":"Label"},"eligible":{"type":"integer","title":"Eligible"},"already_sent":{"type":"integer","title":"Already Sent"}},"type":"object","required":["kind","start","label","eligible","already_sent"],"title":"DigestPeriodOptionResponse"},"DiscoveryAllowanceAdmissionDetail":{"properties":{"code":{"$ref":"#/components/schemas/AllowanceCode"},"message":{"type":"string","title":"Message"},"requested_rows":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Requested Rows"},"affordable_rows":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Affordable Rows"},"selection_fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Selection Fingerprint"}},"type":"object","required":["code","message"],"title":"DiscoveryAllowanceAdmissionDetail"},"DiscoveryAllowanceAdmissionErrorResponse":{"properties":{"detail":{"$ref":"#/components/schemas/DiscoveryAllowanceAdmissionDetail"}},"type":"object","required":["detail"],"title":"DiscoveryAllowanceAdmissionErrorResponse"},"DiscoveryAllowanceCustomerProjection":{"properties":{"status":{"type":"string","enum":["available","near_limit","exhausted","unavailable"],"title":"Status"},"episode_key":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Episode Key"},"remaining_percent":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Remaining Percent"},"display_remaining_percent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Remaining Percent"}},"type":"object","required":["status","remaining_percent","display_remaining_percent"],"title":"DiscoveryAllowanceCustomerProjection","description":"Customer-safe allowance state with no internal cost detail."},"DiscoveryAllowanceRequestResponse":{"properties":{"interaction_id":{"type":"string","format":"uuid","title":"Interaction Id"},"status":{"type":"string","enum":["sent","processing"],"title":"Status"},"newly_requested":{"type":"boolean","title":"Newly Requested"}},"type":"object","required":["interaction_id","status","newly_requested"],"title":"DiscoveryAllowanceRequestResponse"},"DiscoveryAllowanceResponse":{"properties":{"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"workspace_type":{"$ref":"#/components/schemas/WorkspaceType"},"discovery_allowance_usd":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Discovery Allowance Usd"},"consumed_usd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Consumed Usd"},"remaining_usd":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Remaining Usd"}},"type":"object","required":["workspace_id","workspace_type","discovery_allowance_usd","consumed_usd","remaining_usd"],"title":"DiscoveryAllowanceResponse"},"DiscoveryAllowanceStateChangedEvent":{"properties":{"type":{"type":"string","const":"discovery_allowance_state_changed","title":"Type","default":"discovery_allowance_state_changed"}},"type":"object","title":"DiscoveryAllowanceStateChangedEvent","description":"Fired after a discovery allowance state change commits."},"DiscoveryAllowanceUpdateRequest":{"properties":{"discovery_allowance_usd":{"anyOf":[{"type":"number","minimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*(?:\\d{0,14}|(?=[\\d.]{1,21}0*$)\\d{0,14}\\.\\d{0,6}0*$)"},{"type":"null"}],"title":"Discovery Allowance Usd"}},"additionalProperties":false,"type":"object","required":["discovery_allowance_usd"],"title":"DiscoveryAllowanceUpdateRequest"},"DiscoveryAllowanceWarningClaimResponse":{"properties":{"newly_claimed":{"type":"boolean","title":"Newly Claimed"}},"type":"object","required":["newly_claimed"],"title":"DiscoveryAllowanceWarningClaimResponse"},"DiscoverySpendResponse":{"properties":{"as_of":{"type":"string","format":"date-time","title":"As Of"},"known_cost_usd":{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$","title":"Known Cost Usd"},"total_cost_usd":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Total Cost Usd"},"completeness":{"$ref":"#/components/schemas/CostCompleteness"},"event_count":{"type":"integer","title":"Event Count"},"rate_ids":{"items":{"type":"string"},"type":"array","title":"Rate Ids"}},"type":"object","required":["as_of","known_cost_usd","total_cost_usd","completeness","event_count","rate_ids"],"title":"DiscoverySpendResponse"},"DistinctValue":{"properties":{"value":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"},{"type":"null"}],"title":"Value"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["value","count"],"title":"DistinctValue","description":"A single distinct value and its occurrence count for the set-filter list.\n\n``value`` is the server-rendered text of the column value (the SQL\nprojects ``(col)::text``) so a client echoing it back into a set filter\nmatches the ``col::text IN`` predicate byte-for-byte. The non-string\nscalars appear only on list-shape JSONB columns, whose envelopes are\nexploded into their elements after the query."},"DistinctValuesResponse":{"properties":{"values":{"items":{"$ref":"#/components/schemas/DistinctValue"},"type":"array","title":"Values"},"truncated":{"type":"boolean","title":"Truncated"}},"type":"object","required":["values","truncated"],"title":"DistinctValuesResponse","description":"Response for the per-column distinct-values endpoint (AG Grid set filter)."},"DocumentUrl":{"properties":{"url":{"type":"string","title":"Url"},"force_download":{"anyOf":[{"type":"boolean"},{"type":"string","const":"allow-local"}],"title":"Force Download","default":false},"vendor_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Vendor Metadata"},"kind":{"type":"string","const":"document-url","title":"Kind","default":"document-url"},"media_type":{"type":"string","title":"Media Type","description":"Return the media type of the file, based on the URL or the provided `media_type`.","readOnly":true},"identifier":{"type":"string","title":"Identifier","description":"The identifier of the file, such as a unique ID.\n\nThis identifier can be provided to the model in a message to allow it to refer to this file in a tool call argument,\nand the tool can look up the file in question by iterating over the message history and finding the matching `FileUrl`.\n\nThis identifier is only automatically passed to the model when the `FileUrl` is returned by a tool.\nIf you're passing the `FileUrl` as a user message, it's up to you to include a separate text part with the identifier,\ne.g. \"This is file <identifier>:\" preceding the `FileUrl`.\n\nIt's also included in inline-text delimiters for providers that require inlining text documents, so the model can\ndistinguish multiple files.","readOnly":true}},"type":"object","required":["url","media_type","identifier"],"title":"DocumentUrl","description":"The URL of the document."},"EmailVerificationRequest":{"properties":{"token":{"type":"string","maxLength":256,"minLength":1,"title":"Token"}},"type":"object","required":["token"],"title":"EmailVerificationRequest","description":"Request model for redeeming a signup email-verification link."},"EnrichRowRequest":{"properties":{"feature_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Feature Ids","examples":[["00000000-0000-0000-0000-000000000001"]]},"selection":{"anyOf":[{"$ref":"#/components/schemas/FilterSelectionRequest"},{"type":"null"}]},"selection_limit":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Selection Limit"},"allowance_confirmation_fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Allowance Confirmation Fingerprint"},"high_priority":{"type":"boolean","title":"High Priority","description":"Execute with high priority if True","default":false},"point_action":{"type":"boolean","title":"Point Action","description":"True for a deliberate single-cell enrichment. Only a point action skips the coordinator; column kickoffs stay coordinator-keyed even when they resolve to a single row.","default":false}},"type":"object","title":"EnrichRowRequest","description":"Request schema for enriching rows.\n\nTwo mutually-exclusive selection modes:\n\n- ``feature_ids`` — explicit ids the client has materialized (legacy\n  path; row-detail trigger and small-N enrich-from-cell).\n- ``selection`` — the filter spec the client saw at confirm time;\n  the server recomputes the matching id set and fingerprint/count\n  under a live session. Used by the column-wide enrich confirm gate\n  where the id list would exceed wire-payload limits.\n\nExactly one must be provided; the model-validator enforces this so\na request that drops both or duplicates both is rejected with 422."},"EnrichRowResponse":{"properties":{"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"items":{"type":"string"},"type":"array"},{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"additionalProperties":true,"type":"object"},{"type":"integer"},{"items":{"$ref":"#/components/schemas/ContactModel"},"type":"array"},{"items":{"$ref":"#/components/schemas/TenantLeaseConcise"},"type":"array"},{"type":"null"}],"title":"Value"},"reasoning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reasoning"},"citations":{"anyOf":[{"items":{"$ref":"#/components/schemas/EnrichmentCitation"},"type":"array"},{"type":"null"}],"title":"Citations"},"state":{"$ref":"#/components/schemas/EnrichmentState"}},"type":"object","required":["value","state"],"title":"EnrichRowResponse","description":"Response schema for enriching a specific row.\n\nAttributes:\n    value: The enriched value (result of the enrichment)\n    reasoning: Explanation or rationale for the enrichment value\n    citations: List of web search sources that support the enrichment value\n    state: The final state of the enrichment for this row"},"EnrichmentAdmissionPreflightResponse":{"properties":{"admitted":{"type":"boolean","title":"Admitted"},"decision":{"$ref":"#/components/schemas/DiscoveryAllowanceAdmissionDetail"}},"type":"object","required":["admitted","decision"],"title":"EnrichmentAdmissionPreflightResponse"},"EnrichmentAgentStatusResponse":{"properties":{"workflow_id":{"type":"string","title":"Workflow Id","description":"The ID of the DBOS workflow (or legacy Celery task)."},"status":{"type":"string","title":"Status","description":"The current status of the workflow (PENDING, SUCCESS, FAILURE, etc.)."},"result":{"anyOf":[{"$ref":"#/components/schemas/EnrichmentAgentTaskPayload"},{"type":"null"}]},"error_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Info","description":"Error information if the workflow failed."},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At","description":"Timestamp when the workflow completed."}},"type":"object","required":["workflow_id","status"],"title":"EnrichmentAgentStatusResponse","description":"Status response for enrichment agent (creation/update) tasks.\n\nMirrors `EnrichmentStatusResponse` shape — also intentionally non-inheriting\nso the `workflow_id` rename stays local to the enrichment surface."},"EnrichmentAgentTaskPayload":{"properties":{"status":{"type":"string","title":"Status"},"output_type":{"type":"string","title":"Output Type"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"resources":{"anyOf":[{"items":{"$ref":"#/components/schemas/ResourceReference"},"type":"array"},{"type":"null"}],"title":"Resources"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"output":{"anyOf":[{},{"type":"null"}],"title":"Output"},"deep_research_timed_out":{"type":"boolean","title":"Deep Research Timed Out","default":false}},"type":"object","required":["status","output_type"],"title":"EnrichmentAgentTaskPayload","description":"Payload returned by the enrichment agent background task."},"EnrichmentBatchStartResponse":{"properties":{"workflow_ids":{"items":{"type":"string"},"type":"array","title":"Workflow Ids"},"feature_ids":{"items":{"type":"string"},"type":"array","title":"Feature Ids"},"coordinator_workflow_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coordinator Workflow Id"}},"type":"object","required":["workflow_ids","feature_ids"],"title":"EnrichmentBatchStartResponse","description":"Response from POST /enrichment/enrich_async/{enrichment_id}.\n\nEnqueue-only; clients drive cell freshness via the polling endpoint.\n``feature_ids[i]`` corresponds to ``workflow_ids[i]`` — clients use this\nparallel mapping to attribute polled workflow results back to rows when\nthey didn't materialize the id list themselves (selection path)."},"EnrichmentCitation":{"properties":{"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url","description":"Optional URL of the source that supports the enrichment value."},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"Optional human-readable title for the source."},"snippet":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Snippet","description":"Optional snippet or excerpt from the cited material."},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider","description":"Provider or domain the citation originated from."},"source_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Type","description":"Provider-specific type identifier for the cited source."}},"type":"object","title":"EnrichmentCitation","description":"Metadata describing a cited source returned by an enrichment."},"EnrichmentColumnConfig":{"properties":{"enrichment_id":{"type":"string","format":"uuid","title":"Enrichment Id"},"dtype":{"type":"string","title":"Dtype"},"tool":{"type":"string","title":"Tool"},"params":{"additionalProperties":true,"type":"object","title":"Params"},"sidecar_column":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sidecar Column"}},"type":"object","required":["enrichment_id","dtype","tool","params","sidecar_column"],"title":"EnrichmentColumnConfig","description":"Enrichment config surfaced for enrichment-source columns."},"EnrichmentCreditsResponse":{"properties":{"available_credits":{"type":"integer","title":"Available Credits","examples":[10]},"used_credits":{"type":"integer","title":"Used Credits","examples":[5]},"reserved_credits":{"type":"integer","title":"Reserved Credits","examples":[2]}},"type":"object","required":["available_credits","used_credits","reserved_credits"],"title":"EnrichmentCreditsResponse","description":"Response schema for enrichment credits."},"EnrichmentDelete":{"properties":{"enrichment_id":{"type":"string","format":"uuid","title":"Enrichment Id","examples":["00000000-0000-0000-0000-000000000001"]},"project_id":{"type":"string","format":"uuid","title":"Project Id","examples":["00000000-0000-0000-0000-000000000001"]}},"type":"object","required":["enrichment_id","project_id"],"title":"EnrichmentDelete","description":"Request schema for deleting an enrichment.\n\nAttributes:\n    enrichment_id: Unique identifier for the enrichment to delete"},"EnrichmentDeleteFromLibraryRequest":{"properties":{"enrichment_id":{"type":"string","format":"uuid","title":"Enrichment Id","examples":["00000000-0000-0000-0000-000000000001"]}},"type":"object","required":["enrichment_id"],"title":"EnrichmentDeleteFromLibraryRequest","description":"Request schema for deleting an enrichment from the library.\n\nAttributes:\n    enrichment_id: Unique identifier for the enrichment to delete"},"EnrichmentDeleteFromLibraryResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"EnrichmentDeleteFromLibraryResponse","description":"Response schema for deleting an enrichment from the library."},"EnrichmentDeleteResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"EnrichmentDeleteResponse","description":"Response schema for enrichment deletion endpoint.\n\nAttributes:\n    message: Descriptive message about the deletion result"},"EnrichmentDispatchConflictResponse":{"anyOf":[{"$ref":"#/components/schemas/DiscoveryAllowanceAdmissionErrorResponse"},{"$ref":"#/components/schemas/SelectionDriftErrorResponse"}]},"EnrichmentLimitsResponse":{"properties":{"filtered_ids_default_limit":{"type":"integer","title":"Filtered Ids Default Limit","description":"Default page size on /features/filtered-ids when `limit` is omitted from the query string."},"filtered_ids_max_limit":{"type":"integer","title":"Filtered Ids Max Limit","description":"Hard upper bound on /features/filtered-ids `limit`. Requests above this return 422."}},"type":"object","required":["filtered_ids_default_limit","filtered_ids_max_limit"],"title":"EnrichmentLimitsResponse","description":"Per-batch limits for column-wide enrichment.\n\nBacks the FE column-header Enrich submenu's 'All in list' clamp and\nits >100k confirm gate. Both values are the canonical server limits;\nthe FE should never carry its own copy."},"EnrichmentListResponse":{"properties":{"enrichments":{"items":{"$ref":"#/components/schemas/EnrichmentModel"},"type":"array","title":"Enrichments"}},"type":"object","required":["enrichments"],"title":"EnrichmentListResponse","description":"Response schema for listing all enrichments.\n\nAttributes:\n    enrichments: List of enrichment data"},"EnrichmentModel":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"layer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Layer Id"},"name":{"type":"string","title":"Name","default":"Unconfigured enrichment"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","default":"This enrichment is not configured with a tool."},"tool":{"type":"string","title":"Tool","default":"unconfigured"},"params":{"additionalProperties":true,"type":"object","title":"Params"},"dtype":{"type":"string","title":"Dtype","description":"Must be one of string, boolean, list[str], jsonb, int, float, categorical, url","default":"string"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"credits_per_row":{"type":"integer","title":"Credits Per Row","description":"Return the number of credits per row for this tool.","readOnly":true},"is_configured":{"type":"boolean","title":"Is Configured","description":"Check if the enrichment is configured with a valid tool.\n\nReturns:\n    bool: True if tool is configured, False otherwise","readOnly":true},"is_configuration_failed":{"type":"boolean","title":"Is Configuration Failed","description":"Check if the enrichment's configuration failed.\n\nReturns:\n    bool: True if configuration was attempted but failed","readOnly":true},"is_data_source":{"type":"boolean","title":"Is Data Source","description":"Check if the enrichment is a data source.\n\nReturns:\n    bool: True if the enrichment is a data source, False otherwise","readOnly":true}},"type":"object","required":["credits_per_row","is_configured","is_configuration_failed","is_data_source"],"title":"EnrichmentModel","description":"Enrichment model that combines both properties and chat history.\n\nThis unified model simplifies the domain representation and aligns more closely\nwith how data is stored in the database, reducing unnecessary abstractions."},"EnrichmentNameConstants":{"type":"string","enum":["Company Name","URL","Building Address","Industry","Parcel Number","Use Code","Use Description","Zoning","Improvement Value","Land Value","Parcel Owner","City","County","Location Name","Full Address","building_area_sqm","Has Solar","Is Owner","geometry","Image URL","Dummy Enrichment","FIPS","project_id","layer_id","id","Parcel Address","scity"],"title":"EnrichmentNameConstants"},"EnrichmentResponse":{"properties":{"enrichment":{"$ref":"#/components/schemas/EnrichmentModel"}},"type":"object","required":["enrichment"],"title":"EnrichmentResponse","description":"Base response schema for enrichment operations.\n\nAttributes:\n    enrichment: EnrichmentModel containing enrichment data"},"EnrichmentStartedEvent":{"properties":{"type":{"type":"string","const":"enrichment_started","title":"Type","default":"enrichment_started"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"enrichment_id":{"type":"string","format":"uuid","title":"Enrichment Id"},"field_name":{"type":"string","title":"Field Name"},"coordinator_workflow_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coordinator Workflow Id"},"launched_total":{"type":"integer","title":"Launched Total"},"rows":{"items":{"$ref":"#/components/schemas/EnrichmentStartedRow"},"type":"array","title":"Rows"}},"type":"object","required":["project_id","enrichment_id","field_name","launched_total","rows"],"title":"EnrichmentStartedEvent","description":"Fired when a kickoff launches a batch of enrichment row-workflows.\n\nThe \"started\" half of the enrichment lifecycle, symmetric to\n``EnrichmentStatusChangedEvent`` (the terminal half). Together they make the\nFE's in-flight set fully server-authoritative: it ADDS the carried rows here\nand DROPS each one on its terminal event, instead of optimistically inferring\n\"started\" from the kickoff HTTP response. That optimistic path held one entry\nper ``project_id:field_name`` and reset it on every new ``coordinator_workflow_id``,\nso concurrent per-row runs on the same column collapsed onto the latest one\n(only the most recent row showed enriching). Keying on ``coordinator_workflow_id``\nhere lets each run track independently.\n\nCarries the same coordinates the ``/in-flight`` payload exposes\n(``coordinator_workflow_id`` / ``field_name`` / per-row ``workflow_id`` +\n``feature_id``) so the live-delta path and the resume-snapshot path build\nidentical registry entries. ``launched_total`` is the fixed progress\ndenominator (immune to waved fan-out), matching ``InFlightBatchResponse``."},"EnrichmentStartedRow":{"properties":{"workflow_id":{"type":"string","title":"Workflow Id"},"feature_id":{"type":"string","title":"Feature Id"}},"type":"object","required":["workflow_id","feature_id"],"title":"EnrichmentStartedRow","description":"One (workflow, feature) pair launched by a kickoff."},"EnrichmentState":{"type":"string","enum":["unenriched","enriched","attempted","user_edited","pending"],"title":"EnrichmentState","description":"Enum representing the state of an enrichment value."},"EnrichmentStatusBatchRequest":{"properties":{"workflow_ids":{"items":{"type":"string"},"type":"array","title":"Workflow Ids"}},"type":"object","required":["workflow_ids"],"title":"EnrichmentStatusBatchRequest","description":"Request model for getting the status of multiple enrichment workflows."},"EnrichmentStatusChangedEvent":{"properties":{"type":{"type":"string","const":"enrichment_status_changed","title":"Type","default":"enrichment_status_changed"},"workflow_id":{"type":"string","title":"Workflow Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"enrichment_id":{"type":"string","format":"uuid","title":"Enrichment Id"},"feature_id":{"type":"string","title":"Feature Id"},"status":{"type":"string","enum":["SUCCESS","FAILURE"],"title":"Status"},"value":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Value"}},"type":"object","required":["workflow_id","project_id","enrichment_id","feature_id","status"],"title":"EnrichmentStatusChangedEvent","description":"Fired when one enrichment workflow reaches a terminal state.\n\nUnlike ``CreditStateChangedEvent`` this is payload-rich. It carries:\n\n- ``workflow_id`` — the client registry's key; routes the event to the\n  cell/column it belongs to.\n- ``project_id`` / ``enrichment_id`` / ``feature_id`` — the coordinates,\n  so an event for a workflow the client didn't dispatch in this session\n  (e.g. after a reload, before reconcile) can still build a registry\n  entry from the event alone.\n- ``value`` — on SUCCESS, the persisted ``EnrichRowResponse``-shaped dict\n  (``{value, reasoning, citations, state}``) built from the SAME\n  ``db_value`` written to the sandbox, so the live cell is byte-identical\n  to what a refresh re-reads. ``None`` on FAILURE (no value was written).\n\nThe terminal-status policy lives on the server (the workflow's own\nterminal state), not on the client — so the client can no longer drift a\ntransient signal into a false terminal (the bug class this replaces)."},"EnrichmentStatusListResponse":{"properties":{"statuses":{"items":{"$ref":"#/components/schemas/EnrichmentStatusResponse"},"type":"array","title":"Statuses"}},"type":"object","required":["statuses"],"title":"EnrichmentStatusListResponse","description":"Response model for returning a list of enrichment task statuses."},"EnrichmentStatusResponse":{"properties":{"workflow_id":{"type":"string","title":"Workflow Id","description":"The ID of the DBOS workflow (or legacy Celery task)."},"status":{"type":"string","title":"Status","description":"The current status of the workflow (PENDING, SUCCESS, FAILURE, etc.)."},"result":{"anyOf":[{"$ref":"#/components/schemas/EnrichRowResponse"},{"type":"null"}]},"error_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Info","description":"Error information if the workflow failed."},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At","description":"Timestamp when the workflow completed."}},"type":"object","required":["workflow_id","status"],"title":"EnrichmentStatusResponse","description":"Response schema for enrichment status endpoint.\n\nAttributes:\n    workflow_id: The ID of the DBOS workflow\n    status: Status of the enrichment workflow (PENDING, SUCCESS, FAILURE, etc.)\n    result: Response data containing enrichment value and reasoning (if successful) of type EnrichRowResponse"},"EnrichmentUpdateApprovalDetail":{"properties":{"message":{"type":"string","title":"Message"},"preview":{"$ref":"#/components/schemas/EnrichmentUpdatePreview"}},"type":"object","required":["message","preview"],"title":"EnrichmentUpdateApprovalDetail","description":"Approval preview returned when an update must re-enrich stored rows."},"EnrichmentUpdateApprovalRequiredResponse":{"properties":{"detail":{"$ref":"#/components/schemas/EnrichmentUpdateApprovalDetail"}},"type":"object","required":["detail"],"title":"EnrichmentUpdateApprovalRequiredResponse","description":"FastAPI error envelope for a user-confirmed re-enrichment."},"EnrichmentUpdateConflictResponse":{"anyOf":[{"$ref":"#/components/schemas/DiscoveryAllowanceAdmissionErrorResponse"},{"$ref":"#/components/schemas/EnrichmentUpdateApprovalRequiredResponse"}]},"EnrichmentUpdatePreview":{"properties":{"enrichmentId":{"type":"string","format":"uuid","title":"Enrichmentid"},"enrichmentName":{"type":"string","title":"Enrichmentname"},"oldConfigFingerprint":{"type":"string","title":"Oldconfigfingerprint"},"targetConfigFingerprint":{"type":"string","title":"Targetconfigfingerprint"},"selectionFingerprint":{"type":"string","title":"Selectionfingerprint"},"affectedCount":{"type":"integer","title":"Affectedcount"},"protectedCount":{"type":"integer","title":"Protectedcount","default":0},"oldDtype":{"type":"string","title":"Olddtype"},"targetDtype":{"type":"string","title":"Targetdtype"},"budgetAuthority":{"$ref":"#/components/schemas/BudgetAuthority","default":"credits"},"creditCost":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Creditcost"},"admittedCount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Admittedcount"},"admittedSelectionFingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Admittedselectionfingerprint"},"remainderCount":{"type":"integer","title":"Remaindercount","default":0},"remainderSelectionFingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Remainderselectionfingerprint"},"allowanceCode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Allowancecode"}},"type":"object","required":["enrichmentId","enrichmentName","oldConfigFingerprint","targetConfigFingerprint","selectionFingerprint","affectedCount","oldDtype","targetDtype","creditCost"],"title":"EnrichmentUpdatePreview","description":"Stable approval contract for an update that must re-run stored results."},"EnrichmentUpdates":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"tool":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tool"},"params":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Params"},"dtype":{"anyOf":[{"type":"string","enum":["string","float","boolean","list[str]","jsonb","int","url"]},{"type":"string","const":"categorical"},{"type":"string","enum":["ContactModel","TenantLeaseConcise","OwnerResidentialMailingAddress","MortgageProfile"]},{"type":"null"}],"title":"Dtype"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","title":"EnrichmentUpdates","description":"Schema for enrichment update fields.\n\nThis provides a structured representation of fields that can be updated.\nAdd specific fields here instead of using a generic Dict[str, Any]."},"EnrichmentValueBaseModel":{"properties":{"reasoning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reasoning","description":"1-2 sentence explanation of the enrichment value."},"value":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"items":{"type":"string"},"type":"array"},{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"additionalProperties":true,"type":"object"},{"type":"integer"},{"type":"null"}],"title":"Value","description":"The enrichment value."},"citations":{"anyOf":[{"items":{"$ref":"#/components/schemas/EnrichmentCitation"},"type":"array"},{"type":"null"}],"title":"Citations","description":"List of citations from web search sources that support the enrichment value if any were used."},"research_outcome":{"anyOf":[{"$ref":"#/components/schemas/ResearchOutcome"},{"type":"null"}],"description":"The producer's research-outcome self-report, when its output shape carries one. None for producers that do not report it and for payloads persisted before the field existed."},"state":{"$ref":"#/components/schemas/EnrichmentState","description":"The status of the enrichment value.","default":"unenriched"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"}},"type":"object","title":"EnrichmentValueBaseModel","description":"Enrichment value domain model."},"ErrorDetails":{"properties":{"type":{"type":"string","title":"Type"},"loc":{"items":{"anyOf":[{"type":"integer"},{"type":"string"}]},"type":"array","title":"Loc"},"msg":{"type":"string","title":"Msg"},"input":{"title":"Input"},"ctx":{"additionalProperties":true,"type":"object","title":"Ctx"},"url":{"type":"string","title":"Url"}},"type":"object","required":["type","loc","msg","input"],"title":"ErrorDetails"},"ExclusionOutcome":{"properties":{"email":{"type":"string","title":"Email"},"changed":{"type":"boolean","title":"Changed"}},"type":"object","required":["email","changed"],"title":"ExclusionOutcome"},"ExclusionStateChangedEvent":{"properties":{"type":{"type":"string","const":"exclusion_state_changed","title":"Type","default":"exclusion_state_changed"},"projectId":{"type":"string","format":"uuid","title":"Projectid"},"version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version"}},"type":"object","required":["projectId"],"title":"ExclusionStateChangedEvent","description":"Fired after a project's excluded-row set changes (bulk exclude or\nrestore commits), over the per-user channel.\n\nExclusions are an always-on server-side predicate, so the client holds no\nfilter state to patch — this event tells it the visible row set changed:\ninvalidate the exclusions query and bump the exclusions revision, which\npurges the SSR grid and re-points tile URLs. It is the only channel through\nwhich an *agent-driven* exclusion reaches an open browser (the agent's\nremoval no longer runs SQL whose ``affected_layers`` the client parses).\n\n``version`` is the project's post-bump ``excl_v`` counter (``None`` when\nRedis was unavailable for the bump); the FE treats it as opaque freshness.\ncamelCase wire shape, matching the sibling events.\n\nAdvisory only — a dropped publish degrades to staleness bounded by the next\nrefetch or reload; the durable ``row_exclusions`` table is the truth."},"ExpenseStructure":{"type":"string","enum":["nnn","modified_gross","full_service_gross","industrial_gross","other"],"title":"ExpenseStructure"},"FavoriteComparisonScope":{"type":"string","enum":["table_viewport","map_stack","navigation_neighbors","unavailable"],"title":"FavoriteComparisonScope"},"FavoritePositionSource":{"type":"string","enum":["grid_viewport","server_cursor","map_stack"],"title":"FavoritePositionSource"},"FavoriteSource":{"type":"string","enum":["table_cell","table_shortcut","detail_panel"],"title":"FavoriteSource"},"FavoriteToggleContext":{"properties":{"layer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Layer Id"},"visible_feature_ids":{"anyOf":[{"items":{"type":"string","maxLength":64,"minLength":1},"type":"array","maxItems":200},{"type":"null"}],"title":"Visible Feature Ids"},"row_position":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Row Position"},"position_source":{"anyOf":[{"$ref":"#/components/schemas/FavoritePositionSource"},{"type":"null"}]},"total_rows":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Total Rows"},"is_grouped":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Grouped"},"sort_model":{"anyOf":[{"items":{"$ref":"#/components/schemas/SortEntry"},"type":"array","maxItems":100},{"type":"null"}],"title":"Sort Model"},"filter_model":{"anyOf":[{"additionalProperties":{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Input"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},"type":"object","maxProperties":500},{"type":"null"}],"title":"Filter Model"},"show_favorites_only":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Show Favorites Only"},"search_text":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Search Text"},"geometry":{"anyOf":[{"$ref":"#/components/schemas/GeoJSONPolygon"},{"type":"null"}]},"comparison_scope":{"$ref":"#/components/schemas/FavoriteComparisonScope","default":"unavailable"},"source":{"$ref":"#/components/schemas/FavoriteSource"},"session_id":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Session Id"}},"additionalProperties":false,"type":"object","required":["source"],"title":"FavoriteToggleContext","description":"The exact first-party list context at the time of a favorite action."},"FavoriteToggleResponse":{"properties":{"favorited":{"type":"boolean","title":"Favorited"}},"type":"object","required":["favorited"],"title":"FavoriteToggleResponse","description":"The favorited state after the toggle."},"Feature":{"properties":{"id":{"type":"string","title":"Id"},"geometry":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Geometry"},"layer_id":{"type":"string","format":"uuid","title":"Layer Id"},"base_attributes":{"additionalProperties":true,"type":"object","title":"Base Attributes"},"enrichments":{"additionalProperties":true,"type":"object","title":"Enrichments"},"agent_attributes":{"additionalProperties":true,"type":"object","title":"Agent Attributes"}},"type":"object","required":["id","geometry","layer_id","base_attributes","enrichments"],"title":"Feature","description":"Flattened feature model.\n\nUses lazy validation for enrichments to keep model creation fast.\nAccess raw enrichments for performance, validated enrichments when type safety is needed."},"FeatureAddRequest":{"properties":{"type":{"type":"string","enum":["Point","LineString","Polygon","MultiPoint","MultiLineString","MultiPolygon"],"title":"Type"},"coordinates":{"items":{},"type":"array","title":"Coordinates"},"properties":{"additionalProperties":true,"type":"object","title":"Properties","default":{}},"layer_id":{"type":"string","format":"uuid","title":"Layer Id"},"source_feature_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Feature Id"}},"type":"object","required":["type","coordinates","layer_id"],"title":"FeatureAddRequest","description":"Lightweight request for adding GeoJSON features."},"FeatureAddResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"data_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Data Version"},"feature_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Feature Id"}},"type":"object","required":["success"],"title":"FeatureAddResponse","description":"Response model for adding a feature.\n\n``data_version`` is the layer's new version after a successful add (bumped\nin the same transaction). None on failure since a failed create does not\nbump. The FE uses this to rotate the tile URL's ``?v=``."},"FeatureContext":{"properties":{"feature_id":{"type":"string","minLength":1,"title":"Feature Id"},"layer_id":{"type":"string","format":"uuid","title":"Layer Id"}},"type":"object","required":["feature_id","layer_id"],"title":"FeatureContext","description":"Reference to a specific feature the user is viewing.\n\nSent when the detail view is open so the agent knows which feature\nthe user is talking about. Reused by @ mentions.\n\n`feature_id` is a string because sandbox-backed layers (place-type) use\nUUID feature ids, while CloudSQL `features.id` is bigint serialized as a\nnumeric string. Validation only enforces non-empty."},"FeatureDetailResponse":{"properties":{"properties":{"additionalProperties":true,"type":"object","title":"Properties"},"geometry":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Geometry"},"enrichments":{"additionalProperties":{"$ref":"#/components/schemas/EnrichmentValueBaseModel"},"type":"object","title":"Enrichments"}},"type":"object","required":["properties","geometry"],"title":"FeatureDetailResponse","description":"Full properties + GeoJSON geometry for a single feature.\n\nPowers the feature detail panel and ``MapboxService.flyToFeature()``.\nBase attributes live in ``properties``; enrichment wrappers live in\n``enrichments``, keyed by enrichment UUID so consumers can look them up\nby ``config.id`` without reconciling column names. The paginated\nendpoint keeps column-name-keyed wrappers in row data for AG Grid SSR."},"FeatureNoteContentRequest":{"properties":{"content":{"type":"string","maxLength":5000,"minLength":1,"title":"Content"},"source":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Source"}},"type":"object","required":["content"],"title":"FeatureNoteContentRequest","description":"Request schema for creating or updating a feature note."},"FeatureNoteResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"feature_id":{"type":"string","title":"Feature Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"content":{"type":"string","title":"Content"},"source":{"type":"string","title":"Source"},"author_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","feature_id","project_id","user_id","content","source","author_name","created_at","updated_at"],"title":"FeatureNoteResponse","description":"Response schema for a feature note."},"FeatureOverrideWorkspaceItem":{"properties":{"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"workspace_name":{"type":"string","title":"Workspace Name"},"enabled":{"type":"boolean","title":"Enabled"}},"type":"object","required":["workspace_id","workspace_name","enabled"],"title":"FeatureOverrideWorkspaceItem","description":"One workspace overriding a feature, with its current stored value."},"FeatureOverridesResponse":{"properties":{"key":{"type":"string","title":"Key"},"overrides":{"items":{"$ref":"#/components/schemas/FeatureOverrideWorkspaceItem"},"type":"array","title":"Overrides"}},"type":"object","required":["key","overrides"],"title":"FeatureOverridesResponse","description":"Workspaces that override one feature (deviate from the global default)."},"FeatureSearchResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/FeatureSearchResult"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"FeatureSearchResponse","description":"Response for GET /table/{layer_id}/search."},"FeatureSearchResult":{"properties":{"featureId":{"type":"string","title":"Featureid"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"owner":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"parcelnumb":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parcelnumb"},"matchField":{"type":"string","title":"Matchfield"}},"type":"object","required":["featureId","matchField"],"title":"FeatureSearchResult","description":"A single hit from GET /table/{layer_id}/search."},"FeatureSuggestion":{"properties":{"feature":{"$ref":"#/components/schemas/Feature"},"recommended_layer":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Recommended Layer"},"candidate_layers":{"items":{"$ref":"#/components/schemas/CandidateLayer"},"type":"array","title":"Candidate Layers"},"source_table":{"anyOf":[{"$ref":"#/components/schemas/SourceTable"},{"type":"null"}]},"source_feature_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Feature Id"},"already_in_layer":{"type":"boolean","title":"Already In Layer","default":false},"boundary_only":{"type":"boolean","title":"Boundary Only","default":false}},"type":"object","required":["feature"],"title":"FeatureSuggestion","description":"Feature suggestion for a feature.\n\n``recommended_layer`` is the project layer this feature would be added to, or\nNone when the project has no layer for its Overture table yet. In that case\n``source_table`` + ``source_feature_id`` (the Overture table and row id the\nfeature came from) let the client create a new typed layer seeded with just\nthis feature. ``candidate_layers`` lists every matching layer (``recommended_layer``\nis the head), each flagged with its own ``already_in_layer`` so the client can\noffer a picker of only the layers the feature isn't in yet. The top-level\n``already_in_layer`` is True only when the feature is in *every* matching\nlayer (nothing left to add) — the client then shows an \"Added\" state.\n\n``boundary_only`` marks a parcel whose county published a boundary that no\nattribute source covers. It is offered like any other parcel — the geometry is\nauthoritative — but adding one to a layer writes a row carrying its APN and\nnothing else, so the client says so before the user chooses. Always False for\nthe other source tables, which carry none of the parcel attribute columns."},"FeatureToggleItem":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"description":{"type":"string","title":"Description"},"enabled":{"type":"boolean","title":"Enabled"},"is_override":{"type":"boolean","title":"Is Override"},"global_default":{"type":"boolean","title":"Global Default"}},"type":"object","required":["key","label","description","enabled","is_override","global_default"],"title":"FeatureToggleItem","description":"One governable feature toggle and its effective state for a workspace.\n\n`enabled` is the resolved on/off (override ?? global ?? seed). `is_override`\nflags whether the workspace has an explicit stored value versus inheriting\nthe global default; `global_default` is what it inherits when not overridden."},"FeatureToggleUpdateRequest":{"properties":{"key":{"type":"string","minLength":1,"title":"Key"},"enabled":{"type":"boolean","title":"Enabled"}},"additionalProperties":false,"type":"object","required":["key","enabled"],"title":"FeatureToggleUpdateRequest","description":"Request to flip a single feature toggle for a workspace."},"FeatureTogglesResponse":{"properties":{"toggles":{"items":{"$ref":"#/components/schemas/FeatureToggleItem"},"type":"array","title":"Toggles"}},"type":"object","required":["toggles"],"title":"FeatureTogglesResponse","description":"All governable feature toggles for a workspace (registry + overrides)."},"FieldEnrichmentInfo":{"properties":{"total_count":{"type":"integer","title":"Total Count","description":"Original total task count for this field"},"started_at":{"type":"string","format":"date-time","title":"Started At","description":"When the first enrichment for this field was queued"}},"type":"object","required":["total_count","started_at"],"title":"FieldEnrichmentInfo","description":"Info about enrichment progress for a single field/column.\n\nDEPRECATED [MAIA-2116]: ``total_count`` is a rolling 1-hour per-field\nworkflow count, which made the FE progress denominator drift and span\nunrelated runs. Superseded by ``BatchEnrichmentInfo`` (run-scoped). Kept\nduring the FE cutover; remove once no client reads ``field_info``."},"FilePart":{"properties":{"content":{"$ref":"#/components/schemas/BinaryContent"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"file","title":"Part Kind","default":"file"}},"type":"object","required":["content"],"title":"FilePart","description":"A file response from a model."},"FilterSelectionRequest":{"properties":{"filter_spec":{"$ref":"#/components/schemas/SSRTableQueryParams"},"enrichment_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enrichment State"},"enrichment_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enrichment Name"},"fingerprint":{"type":"string","title":"Fingerprint"},"expected_count":{"type":"integer","minimum":1.0,"title":"Expected Count"}},"type":"object","required":["filter_spec","fingerprint","expected_count"],"title":"FilterSelectionRequest","description":"Snapshot-consumer payload.\n\nCaller asserts: \"when I called ``/filtered-count`` with this spec I\nsaw ``expected_count`` rows and the server returned this\n``fingerprint``; act on that selection.\" The server recomputes both\nand rejects with ``SelectionDriftResponse`` on mismatch."},"FilterSpecRequest":{"properties":{"filterModel":{"additionalProperties":{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Input"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},"type":"object","title":"Filtermodel","description":"AG Grid native filter model (Record<colId, FilterCondition>)."},"geometry":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Geometry","description":"Optional GeoJSON polygon scoping the filter."},"searchText":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext","description":"Optional free-text search applied across searchable columns."},"favoritesOnly":{"type":"boolean","title":"Favoritesonly","description":"Restrict matching rows to the user's favorites.","default":false}},"type":"object","title":"FilterSpecRequest","description":"Payload accepted by ``POST /filters``.\n\nAll four fields participate in the canonical hash that derives the\n``filter_id`` — same shape produces the same ID, idempotent under repeat\nPOST."},"FilterSpecResponse":{"properties":{"filterId":{"type":"string","format":"uuid","title":"Filterid"},"expiresAt":{"type":"string","format":"date-time","title":"Expiresat"}},"type":"object","required":["filterId","expiresAt"],"title":"FilterSpecResponse","description":"Response returned by ``POST /filters`` and the share-mode twin.\n\n``expires_at`` reflects the current sliding TTL window. Every subsequent\nconsumer read (tile request / paginated fetch / etc.) refreshes the window,\nso an active session never sees the spec expire mid-flight."},"FilteredCountResponse":{"properties":{"total":{"type":"integer","title":"Total"},"fingerprint":{"type":"string","title":"Fingerprint"}},"type":"object","required":["total","fingerprint"],"title":"FilteredCountResponse","description":"Total row count matching the current filter set, no ids materialized.\n\nUse over ``filtered-ids`` when only the count is needed — skips the sort\npass and id fetch. Backs the bulk-enrich confirm gate.\n\n``fingerprint`` is a deterministic hash of every field on\n``SSRTableQueryParams`` (minus pagination) plus the enrichment\npredicates that ride alongside; snapshot consumers like\n``/enrich_async`` echo this value back in a ``FilterSelectionRequest``\nso the server can detect client-side spec drift between count and\naction."},"FilteredIdsResponse":{"properties":{"ids":{"items":{"type":"string"},"type":"array","title":"Ids"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["ids","total"],"title":"FilteredIdsResponse","description":"Feature ids matching the current filter set, plus the unfiltered total.\n\n``total`` reflects the full match count even when ``limit`` truncates ``ids`` —\ncallers use it for \"showing X of Y\" UI and bulk-action sizing decisions."},"FindFeatureResponse":{"properties":{"suggestions":{"items":{"$ref":"#/components/schemas/FeatureSuggestion"},"type":"array","title":"Suggestions"},"out_of_county":{"type":"boolean","title":"Out Of County","default":false}},"type":"object","required":["suggestions"],"title":"FindFeatureResponse","description":"Response model for finding a feature."},"GateRequiredShareAccessResponse":{"properties":{"state":{"type":"string","const":"gate_required","title":"State"},"feature_count":{"type":"integer","minimum":0.0,"title":"Feature Count"},"geography_label":{"type":"string","title":"Geography Label"},"bounds":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"},{"type":"number"},{"type":"number"}],"type":"array","maxItems":4,"minItems":4},{"type":"null"}],"title":"Bounds"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"terms_version":{"type":"string","title":"Terms Version"},"terms_url":{"type":"string","title":"Terms Url"},"terms_text":{"type":"string","title":"Terms Text"},"domain_policy":{"type":"string","title":"Domain Policy"},"teaser_tile_template":{"type":"string","title":"Teaser Tile Template"},"teaser_source_layer":{"type":"string","title":"Teaser Source Layer"},"shared_by_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Shared By Email"}},"additionalProperties":false,"type":"object","required":["state","feature_count","geography_label","expires_at","terms_version","terms_url","terms_text","domain_policy","teaser_tile_template","teaser_source_layer"],"title":"GateRequiredShareAccessResponse","description":"Only the values that a browser may receive before viewer acceptance."},"GeoJSONPolygon":{"properties":{"type":{"type":"string","enum":["Polygon","MultiPolygon"],"title":"Type"},"coordinates":{"items":{},"type":"array","title":"Coordinates"}},"type":"object","required":["type","coordinates"],"title":"GeoJSONPolygon","description":"Narrow GeoJSON subset — matches the spatial-filter payload the\nfrontend draws. Accept Polygon and MultiPolygon only; reject Point /\nLineString / feature collections, which ``ST_Intersects`` with a bbox\nwouldn't produce meaningful results against."},"GeographyOptionsResponse":{"properties":{"states":{"items":{"$ref":"#/components/schemas/StateOption"},"type":"array","title":"States"},"counties":{"items":{"$ref":"#/components/schemas/CountyOption"},"type":"array","title":"Counties"}},"type":"object","required":["states","counties"],"title":"GeographyOptionsResponse","description":"Available geography options for workspace restriction."},"GithubReleaseResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tag":{"type":"string","title":"Tag"},"name":{"type":"string","title":"Name"},"released_at":{"type":"string","format":"date-time","title":"Released At"},"customer_section":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Section"}},"type":"object","required":["id","tag","name","released_at","customer_section"],"title":"GithubReleaseResponse"},"GlobalFeatureFlagItem":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"description":{"type":"string","title":"Description"},"global_default":{"type":"boolean","title":"Global Default"},"override_count":{"type":"integer","title":"Override Count"}},"type":"object","required":["key","label","description","global_default","override_count"],"title":"GlobalFeatureFlagItem","description":"One feature toggle's platform-wide default and override count."},"GlobalFeatureFlagsResponse":{"properties":{"flags":{"items":{"$ref":"#/components/schemas/GlobalFeatureFlagItem"},"type":"array","title":"Flags"}},"type":"object","required":["flags"],"title":"GlobalFeatureFlagsResponse","description":"Every registered feature toggle with its global default + override count."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"IcpCategoryListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"workspace_count":{"type":"integer","title":"Workspace Count"},"skill_count":{"type":"integer","title":"Skill Count"}},"type":"object","required":["id","name","workspace_count","skill_count"],"title":"IcpCategoryListItem","description":"A category plus what depends on it, for the admin management list.\n\nThe counts are what the delete guard refuses on, so showing them lets an\noperator see a category is pinned before attempting to remove it."},"IcpCategoryListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/IcpCategoryListItem"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"IcpCategoryListResponse","description":"Every ICP category staff can assign, ordered by name."},"IcpCategoryMembersRequest":{"properties":{"assign":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Assign"},"clear":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Clear"}},"additionalProperties":false,"type":"object","title":"IcpCategoryMembersRequest","description":"The membership changes to apply to a category.\n\nExplicit deltas rather than a full desired membership. A desired-set write\nreconciles against whatever the caller last saw, so a second admin saving\nfrom a form opened moments earlier silently unassigns everything the first\none added — in the destructive direction, with no conflict surfaced. Deltas\nfrom two admins merge instead.\n\n``assign`` moves a workspace onto this category from wherever it is;\n``clear`` returns it to unassigned, and is ignored for a workspace that has\nsince moved to a different category."},"IcpCategoryResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"IcpCategoryResponse","description":"One staff-administered ICP category."},"IcpCategoryWriteRequest":{"properties":{"name":{"type":"string","maxLength":60,"minLength":1,"title":"Name"}},"additionalProperties":false,"type":"object","required":["name"],"title":"IcpCategoryWriteRequest","description":"Create or rename an ICP category.\n\nNames are unique case-insensitively; a duplicate is rejected with 409."},"IdleChatRunStatus":{"properties":{"status":{"type":"string","const":"idle","title":"Status","default":"idle"}},"type":"object","title":"IdleChatRunStatus","description":"A project with no active chat run."},"ImageUrl":{"properties":{"url":{"type":"string","title":"Url"},"force_download":{"anyOf":[{"type":"boolean"},{"type":"string","const":"allow-local"}],"title":"Force Download","default":false},"vendor_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Vendor Metadata"},"kind":{"type":"string","const":"image-url","title":"Kind","default":"image-url"},"media_type":{"type":"string","title":"Media Type","description":"Return the media type of the file, based on the URL or the provided `media_type`.","readOnly":true},"identifier":{"type":"string","title":"Identifier","description":"The identifier of the file, such as a unique ID.\n\nThis identifier can be provided to the model in a message to allow it to refer to this file in a tool call argument,\nand the tool can look up the file in question by iterating over the message history and finding the matching `FileUrl`.\n\nThis identifier is only automatically passed to the model when the `FileUrl` is returned by a tool.\nIf you're passing the `FileUrl` as a user message, it's up to you to include a separate text part with the identifier,\ne.g. \"This is file <identifier>:\" preceding the `FileUrl`.\n\nIt's also included in inline-text delimiters for providers that require inlining text documents, so the model can\ndistinguish multiple files.","readOnly":true}},"type":"object","required":["url","media_type","identifier"],"title":"ImageUrl","description":"A URL to an image."},"ImportCaps":{"properties":{"address_rows":{"type":"integer","title":"Address Rows"},"layer_rows":{"type":"integer","title":"Layer Rows"}},"type":"object","required":["address_rows","layer_rows"],"title":"ImportCaps","description":"Row caps the client renders and gates on — served here so the numbers\nhave exactly one home (the server) and can't drift across surfaces."},"ImportCountyScope":{"properties":{"breakdown":{"additionalProperties":{"type":"integer"},"type":"object","title":"Breakdown"},"dominant":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dominant"},"derivable":{"type":"boolean","title":"Derivable"},"located_count":{"type":"integer","title":"Located Count"},"in_scope_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"In Scope Count"},"out_of_scope_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Out Of Scope Count"}},"type":"object","required":["breakdown","dominant","derivable","located_count"],"title":"ImportCountyScope","description":"County derivation for geometry files: per-county feature counts and the\ndominant (modal) county to pre-select. ``derivable`` is False when no\nfeature landed in any county. ``located_count`` counts rows carrying ANY\ngeometry — it can exceed ``sum(breakdown)`` when points fall outside every\ncounty, and those rows are still fenced (dropped) at upload, so clients\nmust predict fence outcomes from it, never from the breakdown sum. The\nscope counts are present only when the inspect ran against an existing\nproject (Door 2), fencing against that project's county."},"ImportDetection":{"properties":{"route":{"type":"string","enum":["address","geometry","table","both"],"title":"Route"},"address_candidates":{"items":{"type":"string"},"type":"array","title":"Address Candidates"},"header_candidates":{"items":{"type":"string"},"type":"array","title":"Header Candidates"}},"type":"object","required":["route","address_candidates","header_candidates"],"title":"ImportDetection","description":"Detected route plus the address-like columns that motivated it. The\nroute is a heuristic first offer — the card's manual override is the\nescape hatch, so a wrong guess costs one click."},"ImportInspectResponse":{"properties":{"filename":{"type":"string","title":"Filename"},"columns":{"items":{"type":"string"},"type":"array","title":"Columns"},"row_count":{"type":"integer","title":"Row Count"},"input_rows":{"type":"integer","title":"Input Rows"},"truncated":{"type":"boolean","title":"Truncated"},"caps":{"$ref":"#/components/schemas/ImportCaps"},"geometry_mode":{"type":"string","enum":["geojson","lat_lon","wkt","vector","none"],"title":"Geometry Mode"},"detection":{"$ref":"#/components/schemas/ImportDetection"},"preview_rows":{"items":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object"},"type":"array","title":"Preview Rows"},"rows":{"anyOf":[{"items":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object"},"type":"array"},{"type":"null"}],"title":"Rows"},"upload_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upload Token"},"county":{"anyOf":[{"$ref":"#/components/schemas/ImportCountyScope"},{"type":"null"}]}},"type":"object","required":["filename","columns","row_count","input_rows","truncated","caps","geometry_mode","detection","preview_rows"],"title":"ImportInspectResponse","description":"Everything the detection card and downstream flow need from one parse.\n\n``rows`` is populated only for address-eligible files at or under the\naddress cap (or after truncation consent) — geometry and plain-table\nroutes commit by re-sending the file blob, so their rows never ship.\nAll cell values are stringified; ``None`` marks a genuinely empty cell.\n\n``upload_token`` accompanies ``rows`` and redeems the SERVER's copy of that\nsame row set at commit. The client's ``rows`` drive the column mapper and\nthe resolve queries; they are never sent back as data."},"ImportJobResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"status":{"$ref":"#/components/schemas/ImportJobStatus","default":"pending"},"total_rows":{"type":"integer","title":"Total Rows","default":0},"resolved_rows":{"type":"integer","title":"Resolved Rows","default":0},"committed_rows":{"type":"integer","title":"Committed Rows","default":0},"shortfall_rows":{"type":"integer","title":"Shortfall Rows","default":0},"failure_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Reason"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["id","project_id"],"title":"ImportJobResponse","description":"One background import as the client polls and renders it.\n\nThe field list lives on :class:`ImportJobSnapshot` so this and the pushed\n``import_progress`` frame cannot describe the same row differently."},"ImportJobSnapshot":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"status":{"$ref":"#/components/schemas/ImportJobStatus","default":"pending"},"total_rows":{"type":"integer","title":"Total Rows","default":0},"resolved_rows":{"type":"integer","title":"Resolved Rows","default":0},"committed_rows":{"type":"integer","title":"Committed Rows","default":0},"shortfall_rows":{"type":"integer","title":"Shortfall Rows","default":0},"failure_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Reason"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["id","project_id"],"title":"ImportJobSnapshot","description":"Everything a client is told about an import, and nothing else.\n\nOne field list feeding both channels the client learns through — the polled\nread and the pushed progress frame. They were separate shapes once, and the\nterminal frame silently lacked the settled counts the row had written: the\nbadge reported every finished import as \"0 of N rows imported\". Adding a\nreportable field here puts it on both channels or neither.\n\nExcludes the durable-only columns (``workspace_id``, ``user_id``,\n``workflow_id``, ``working_set``) — the last is tens of KB of TOASTed JSONB\nand this shape is served from a list endpoint polled every 30s."},"ImportJobStatus":{"type":"string","enum":["pending","running","cancelling","completed","failed"],"title":"ImportJobStatus","description":"Lifecycle of one background import.\n\n- PENDING:    row inserted, workflow enqueued, no chunk resolved yet\n- RUNNING:    the workflow claimed the job and is resolving chunks\n- CANCELLING: the user asked to stop; the workflow observes this at the\n  next chunk boundary and falls through to a normal finalize. Cancel is\n  cooperative, so this is an in-flight state, not a terminal one — the\n  partial commit still has to happen.\n- COMPLETED:  finalized, whether every row resolved or only some\n- FAILED:     finalized with nothing committed, or the workflow raised"},"ImportJobsResponse":{"properties":{"jobs":{"items":{"$ref":"#/components/schemas/ImportJobResponse"},"type":"array","title":"Jobs"}},"type":"object","required":["jobs"],"title":"ImportJobsResponse","description":"The in-flight set for one user, mirroring the enrichment safety-net poll."},"ImportProgressEvent":{"properties":{"type":{"type":"string","const":"import_progress","title":"Type","default":"import_progress"},"job":{"$ref":"#/components/schemas/ImportJobSnapshot"}},"type":"object","required":["job"],"title":"ImportProgressEvent","description":"Fired as a background address import advances, and once when it settles.\n\nOne event type covers both halves of the import lifecycle — unlike enrichment,\nwhich needs a started/terminal pair because a kickoff fans out across many row\nworkflows. An import is a single job, so ``status`` distinguishes in-flight from\nterminal and the client keys every frame on the job's ``id``.\n\nThe job's ``id`` — never its ``project_id`` — is the client registry's key: a project can be\nimported into more than once, so a project-keyed frame from a previous attempt\nwould be read as progress on its replacement.\n\nCarries the job row itself rather than a hand-picked set of scalars. The\nterminal frame is the *only* thing the badge renders before it self-dismisses\n— well inside the client's 30s reconcile window — so any field the frame\nomits is a field the user never sees on a settled import. Picking fields by\nhand meant the settled counts were left off and every finished import\nreported \"0 of N rows imported\"; a nested :class:`ImportJobSnapshot` makes\nthe frame and the polled read the same shape by construction.\n\nThe nested job serializes in its **snake_case** wire shape, like\n``LayerStateChangedEvent``'s layers: the FE reads the same keys off\n``GET /import/jobs/in-flight``, so one client mapper serves both channels.\n\nAdvisory only for the fact of settling: ``import_jobs`` is the durable truth\na reload re-reads, so a dropped publish degrades to the client's 30s\nreconcile poll."},"ImportRowMatch":{"properties":{"row_index":{"type":"integer","minimum":0.0,"title":"Row Index"},"source_table":{"$ref":"#/components/schemas/SourceTable"},"feature_id":{"type":"string","title":"Feature Id"},"included":{"type":"boolean","title":"Included","default":true}},"type":"object","required":["row_index","source_table","feature_id"],"title":"ImportRowMatch","description":"One reviewed row's outcome, addressed by its position in the held upload.\n\n``row_index`` indexes the row set the token redeems — the server's own\nparse — so a match names a row rather than carrying one. ``included`` is\nthe review checkbox: an excluded row commits no feature but still rides the\nall-rows spine as an unmatched row, which is what \"all rows\" promises."},"ImportSubmitRequest":{"properties":{"upload":{"$ref":"#/components/schemas/ImportUploadSubmit"},"spine":{"type":"string","enum":["matched_only","all_rows"],"title":"Spine","default":"matched_only"},"knowledge_skill_workspace_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Knowledge Skill Workspace Id"},"layer_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Layer Name","description":"Name for the matched-features layer. In-project route only — the new-project route names its layers from the create flow. Blank or absent falls back to a name derived from the matched feature ids."}},"type":"object","required":["upload"],"title":"ImportSubmitRequest","description":"Start a background import from a held upload, into a new or existing\nproject depending on the route."},"ImportSubmitResponse":{"properties":{"project_id":{"type":"string","format":"uuid","title":"Project Id"},"import_job_id":{"type":"string","format":"uuid","title":"Import Job Id"},"county_fips":{"type":"string","title":"County Fips"}},"type":"object","required":["project_id","import_job_id","county_fips"],"title":"ImportSubmitResponse","description":"What a submit returns once the job is durably enqueued.\n\nThe project id is present for both doors — Door 1 creates the project during\nthe submit so the client can navigate to it immediately, reading as\nnot-yet-ready until the job finishes.\n\n``county_fips`` is what that immediate navigation frames the map against: the\nproject has no features until the job commits, so its county extent is the\nonly camera the view can take. Door 1 derives it from the sample; Door 2\nechoes the project's own."},"ImportUploadCommit":{"properties":{"token":{"type":"string","maxLength":128,"title":"Token"},"mapped_columns":{"items":{"type":"string"},"type":"array","maxItems":200,"title":"Mapped Columns"},"matches":{"items":{"$ref":"#/components/schemas/ImportRowMatch"},"type":"array","maxItems":1000,"minItems":1,"title":"Matches"},"dropped_row_indices":{"items":{"type":"integer"},"type":"array","maxItems":1000,"title":"Dropped Row Indices"}},"type":"object","required":["token","matches"],"title":"ImportUploadCommit","description":"The held-upload half of a commit — references, never row values.\n\nThe server re-reads the user's rows from its own inspect result via\n``token``, so the browser's copy of the file stays display-only and the\ncommit is not a trust boundary: no user-controlled dict keys, no reserved\nname collisions, no re-sanitization. ``mapped_columns`` names which held\ncolumns to carry through and is validated against the held column list."},"ImportUploadSubmit":{"properties":{"token":{"type":"string","maxLength":128,"title":"Token"},"address_columns":{"items":{"type":"string"},"type":"array","maxItems":20,"minItems":1,"title":"Address Columns"},"mapped_columns":{"items":{"type":"string"},"type":"array","maxItems":200,"title":"Mapped Columns"}},"type":"object","required":["token","address_columns"],"title":"ImportUploadSubmit","description":"The held-upload half of an ASYNC submit — no matches, by construction.\n\nThe synchronous twin (``ImportUploadCommit``) carries the client's resolved\nmatches because the browser did the resolving. Here the job resolves, so the\nclient sends only which columns compose each row's address query and which\nto carry through; a ``matches`` field would be a second, stale source for\nsomething the server is about to derive."},"InFlightTaskResponse":{"properties":{"workflow_id":{"type":"string","title":"Workflow Id","description":"The DBOS workflow ID"},"enrichment_id":{"type":"string","format":"uuid","title":"Enrichment Id","description":"The enrichment being executed"},"feature_id":{"type":"string","title":"Feature Id","description":"The feature being enriched"},"field_name":{"type":"string","title":"Field Name","description":"The enrichment field name"},"started_at":{"type":"string","format":"date-time","title":"Started At","description":"When the workflow was enqueued"},"phase":{"type":"string","enum":["queued","active"],"title":"Phase","description":"Per-cell lifecycle phase: 'queued' = ENQUEUED/DELAYED (waiting for a concurrency slot), 'active' = PENDING (dispatched and executing). Lets a cell distinguish a long queue wait from a run."},"coordinator_workflow_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coordinator Workflow Id","description":"The run/batch this task belongs to, so the FE can group resumed tasks per action (MAIA-2116). None for pre-2111 rows."},"task_type":{"type":"string","enum":["individual","column"],"title":"Task Type","description":"Type of enrichment task","default":"column"}},"type":"object","required":["workflow_id","enrichment_id","feature_id","field_name","started_at","phase"],"title":"InFlightTaskResponse","description":"Response schema for a single in-flight enrichment workflow."},"InFlightTasksResponse":{"properties":{"tasks":{"items":{"$ref":"#/components/schemas/InFlightTaskResponse"},"type":"array","title":"Tasks","description":"List of in-flight tasks for the project"},"count":{"type":"integer","title":"Count","description":"Total number of in-flight tasks"},"batches":{"items":{"$ref":"#/components/schemas/BatchEnrichmentInfo"},"type":"array","title":"Batches","description":"Run-scoped progress per enrichment action (MAIA-2116)"},"totals_by_field":{"additionalProperties":{"type":"integer"},"type":"object","title":"Totals By Field","description":"DEPRECATED (MAIA-2116): rolling per-field totals; use `batches`"},"field_info":{"additionalProperties":{"$ref":"#/components/schemas/FieldEnrichmentInfo"},"type":"object","title":"Field Info","description":"DEPRECATED (MAIA-2116): rolling per-field info; use `batches`"}},"type":"object","required":["tasks","count"],"title":"InFlightTasksResponse","description":"Response schema for listing in-flight enrichment tasks."},"InteractiveQuestionAnswer":{"properties":{"optionId":{"type":"string","title":"Optionid"},"label":{"type":"string","title":"Label"},"questionId":{"type":"string","title":"Questionid"}},"type":"object","required":["optionId","label","questionId"],"title":"InteractiveQuestionAnswer"},"InvokedSkillPayload":{"properties":{"skillId":{"type":"string","title":"Skillid"},"skillName":{"type":"string","title":"Skillname"}},"type":"object","required":["skillId","skillName"],"title":"InvokedSkillPayload","description":"The catalog skill a user turn invoked, for the inline chip."},"KnowledgeEntryCreateRequest":{"properties":{"title":{"type":"string","maxLength":120,"minLength":1,"title":"Title"},"content":{"type":"string","maxLength":100000,"minLength":1,"title":"Content"},"scope":{"$ref":"#/components/schemas/AccountKnowledgeScope"}},"type":"object","required":["title","content","scope"],"title":"KnowledgeEntryCreateRequest","description":"Request body for creating a user- or workspace-scoped entry."},"KnowledgeEntryResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"scope":{"$ref":"#/components/schemas/KnowledgeScope"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"workspace_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Workspace Id"},"project_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Project Id"},"title":{"type":"string","title":"Title"},"content":{"type":"string","title":"Content"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"is_core":{"type":"boolean","title":"Is Core","description":"Whether this is the reserved always-injected core entry (MAIA-2833).","readOnly":true}},"type":"object","required":["id","scope","title","content","created_at","updated_at","is_core"],"title":"KnowledgeEntryResponse","description":"A titled knowledge entry as returned to clients."},"KnowledgeEntryUpdateRequest":{"properties":{"title":{"type":"string","maxLength":120,"minLength":1,"title":"Title"},"content":{"type":"string","maxLength":100000,"minLength":1,"title":"Content"}},"type":"object","required":["title","content"],"title":"KnowledgeEntryUpdateRequest","description":"Request body for replacing an entry's title + content."},"KnowledgeRunCreate":{"properties":{"scope":{"$ref":"#/components/schemas/AccountKnowledgeScope"},"owner_id":{"type":"string","format":"uuid","title":"Owner Id"},"title":{"type":"string","maxLength":120,"minLength":1,"title":"Title"},"content":{"type":"string","maxLength":100000,"minLength":1,"title":"Content"}},"type":"object","required":["scope","owner_id","title","content"],"title":"KnowledgeRunCreate","description":"One entry to create: ``owner_id`` is a user id or workspace id per scope."},"KnowledgeRunDelete":{"properties":{"entry_id":{"type":"string","format":"uuid","title":"Entry Id"}},"type":"object","required":["entry_id"],"title":"KnowledgeRunDelete","description":"Delete an existing entry."},"KnowledgeRunProvenance":{"properties":{"source":{"type":"string","minLength":1,"title":"Source","default":"populate-knowledge"},"run_at":{"type":"string","format":"date-time","title":"Run At"},"meetings_through":{"type":"string","format":"date-time","title":"Meetings Through"}},"type":"object","required":["run_at","meetings_through"],"title":"KnowledgeRunProvenance","description":"Provenance stamped into every audit row a knowledge run writes.\n\n``meetings_through`` is the refresh cursor: the latest source meeting a run\ningested. A later run reads it back (``KnowledgeRunCursor``) to research\nonly newer material."},"KnowledgeRunUpdate":{"properties":{"entry_id":{"type":"string","format":"uuid","title":"Entry Id"},"title":{"type":"string","maxLength":120,"minLength":1,"title":"Title"},"content":{"type":"string","maxLength":100000,"minLength":1,"title":"Content"}},"type":"object","required":["entry_id","title","content"],"title":"KnowledgeRunUpdate","description":"Replace an existing entry's title + content."},"KnowledgeScope":{"type":"string","enum":["user","workspace","project"],"title":"KnowledgeScope","description":"Tier a knowledge entry applies to.\n\nResolution is additive and ordered ``user -> workspace -> project`` —\nprecedence is ordering only, not override (no shadowing in v1). \"System\"\nknowledge is the agent's existing system prompt — a separate, pre-existing\nmechanism that does not live in this table — so there is no ``system``\nscope here. Project scope (MAIA-2547) is ambient: paths never name a\nproject; the run's project id scopes reads and writes."},"LayerColumn":{"properties":{"id":{"type":"string","title":"Id","description":"Stable column identifier within a layer. Hashed from the layer id plus the column's kind-specific stable identity. Source and merged columns omit `key` so alias renames keep the same id; agent-derived columns include `key` to distinguish multiple computations anchored on the same source."},"key":{"type":"string","title":"Key"},"provenance":{"$ref":"#/components/schemas/ColumnProvenance"},"display_name":{"type":"string","title":"Display Name","description":"Resolved user-facing column label. Unit-agnostic — does NOT include unit tokens like `(ft)`, `(m)`, `(m²)`, or `(acres)`. The FE composes the column header as `display_name + (unit)` where `unit` is the single source of truth for the unit suffix. See MAIA-1872."},"data_type":{"anyOf":[{"$ref":"#/components/schemas/ColumnDataType"},{"type":"null"}]},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit","description":"Display-unit suffix declared by the agent at register-layer time. Single source of truth for the user-visible unit on this column — the FE composes the header as `display_name + (unit)` and renders cells as `value + unit`. Round-trips through the resolver verbatim. Numeric formatting (decimal places) is picked from a unit→format lookup; unknown units fall back to integer formatting + raw suffix so the agent can declare arbitrary unit strings without code changes. Null for non-unit columns (names, IDs, categorical text). Currency uses the `currency` data_type / semantic type, NOT this field."},"semantic_type":{"anyOf":[{"$ref":"#/components/schemas/SemanticType"},{"type":"null"}],"description":"What the column means (currency, area, percent, address_part, …) — drives FE rendering/formatting. Hydrated server-side by `compose_layer_columns` from the column's `LayerKind`. Single on-wire source of per-column semantics, replacing the old `base_attributes.column_metadata` bag. None for columns with no canonical lineage (permissive kinds, ad-hoc derived)."},"role":{"$ref":"#/components/schemas/ColumnRole","description":"Detail-panel placement signal ({stat, other}), orthogonal to `semantic_type`. `stat` columns render as headline numbers. Hydrated from the `LayerKind`; defaults to `other`.","default":"other"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Human-readable column description surfaced in the table column metadata (header tooltip). Carried from the declaration when the producer supplied one (required for `agent_derived`); otherwise hydrated server-side from canonical column metadata. A declared description always wins over canonical hydration."}},"type":"object","required":["id","key","provenance","display_name"],"title":"LayerColumn","description":"The resolved, persisted shape — what gets stored on `layers.columns`\nand surfaced to the frontend.\n\nVisibility and ordering live on the *view* (`view.layerColumnVisibility`\n+ `view.layerColumnOrder`), seeded at register-layer time from the\nagent's declared columns (declared = visible except `kind=system`).\n`LayerColumn` carries only the schema/lineage half — what the column\nIS, not how it's displayed in any one view."},"LayerDeleteResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"LayerDeleteResponse","description":"Response schema for layer delete operations.\n\nAttributes:\n    message: Success message"},"LayerEnrichmentUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"tool":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tool"},"params":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Params"},"dtype":{"anyOf":[{"type":"string","enum":["string","float","boolean","list[str]","jsonb","int","url"]},{"type":"string","const":"categorical"},{"type":"string","enum":["ContactModel","TenantLeaseConcise","OwnerResidentialMailingAddress","MortgageProfile"]},{"type":"null"}],"title":"Dtype"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"confirmation":{"anyOf":[{"$ref":"#/components/schemas/EnrichmentUpdatePreview"},{"type":"null"}]},"stable_run_key":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Stable Run Key"}},"type":"object","title":"LayerEnrichmentUpdate","description":"Backward-compatible layer PUT entry with optional re-run approval."},"LayerExtentResponse":{"properties":{"bbox":{"anyOf":[{"prefixItems":[{"type":"number"},{"type":"number"},{"type":"number"},{"type":"number"}],"type":"array","maxItems":4,"minItems":4},{"type":"null"}],"title":"Bbox"}},"type":"object","required":["bbox"],"title":"LayerExtentResponse","description":"Response model for layer extent."},"LayerModel":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"reference_layer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Reference Layer Id"},"reference_layer_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Reference Layer Ids"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"style_config":{"additionalProperties":true,"type":"object","title":"Style Config"},"feature_count":{"type":"integer","title":"Feature Count"},"total_size_bytes":{"type":"integer","title":"Total Size Bytes"},"data_version":{"type":"integer","title":"Data Version","default":0},"schema_version":{"type":"integer","title":"Schema Version","default":0},"metadata_version":{"type":"integer","title":"Metadata Version","default":0},"base_attributes":{"additionalProperties":true,"type":"object","title":"Base Attributes"},"feature_enrichments":{"items":{"$ref":"#/components/schemas/EnrichmentModel"},"type":"array","title":"Feature Enrichments"},"sandbox_relation_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sandbox Relation Name"},"running_source_table":{"anyOf":[{"$ref":"#/components/schemas/SourceTable"},{"type":"null"}],"description":"Source table when this is the canonical running resolved-feature layer for its project. None for every other layer."},"remaining_feature_capacity":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Remaining Feature Capacity","description":"Features that authenticated add flows can still append before the server-enforced per-layer limit."},"feature_capacity":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Feature Capacity","description":"Server-enforced maximum feature count for this layer.","default":250000},"render_mode":{"type":"string","enum":["detail_always","agg_at_low_zoom"],"title":"Render Mode","default":"agg_at_low_zoom"},"display_kind":{"type":"string","enum":["data","boundary"],"title":"Display Kind","description":"Whether the layer is a queryable dataset (``data``) or a styling-only overlay (``boundary``). Boundary layers paint on the map but suppress the per-layer table, column manager, and feature-detail panel — there is no per-row data worth surfacing.","default":"data"},"extent_bounds":{"anyOf":[{"$ref":"#/components/schemas/ThumbnailBounds"},{"type":"null"}],"description":"Stored unfiltered extent of the layer's geometry, computed at ingest and recomputed on geometry-changing writes. None until computed (pre-backfill rows) or when the layer has no geometry. The FE uses it for initial map framing instead of a live ST_Extent call; filtered zoom-to-features stays live."},"has_drawable_geometry":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Drawable Geometry","description":"Whether the layer holds geometry the map can draw. False marks a table-only upload; None means unrecorded — every layer created before this field, and every creation path that does not state it. Consumers must treat None as unknown, not as False."},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"columns":{"anyOf":[{"items":{"$ref":"#/components/schemas/LayerColumn"},"type":"array"},{"type":"null"}],"title":"Columns","description":"Producer-declared, resolved per-column metadata (id, key, provenance, display name, data type) — schema/lineage only. Visibility and ordering live on the view, seeded at register-layer time. None for legacy pre-cutover layers; the composer derives sensible defaults from physical introspection."},"data_restricted":{"type":"boolean","title":"Data Restricted","description":"Share-response-only signal that the layer's geometry is shown while every per-row attribute is withheld (parcel layers on anonymous share links). Always False on authenticated reads; set True solely by the shared-project layer builder. The FE renders a 'data unavailable in the public version' state in place of an empty grid.","default":false},"viz_withheld_column_keys":{"items":{"type":"string"},"type":"array","title":"Viz Withheld Column Keys","description":"Keys of columns the MVT tile refuses to emit as a classed-visualization column, computed per column by ``column_withheld_from_viz`` and stamped by ``to_authenticated_api_format``. The picker subtracts these so it offers exactly what the tile will paint; re-deriving the rule client-side from a whole-layer flag over-counts and hides ordinary columns. Empty on share responses, which render no picker."},"title_template":{"items":{"type":"string"},"type":"array","title":"Title Template","description":"Ordered column keys the FE concatenates to compose a feature's title (e.g. `[parcelnumb]`, `[primary_address_full]`). Sourced from the layer's `LayerKind`, empty for permissive kinds — the FE keeps its generic title fallback for the long tail."},"address_template":{"items":{"type":"string"},"type":"array","title":"Address Template","description":"Ordered column keys the FE concatenates to compose a feature's address line. Sourced from the layer's `LayerKind`; may reference keys that aren't typed canonical columns (city, state_abbr, …). Empty for permissive kinds."}},"type":"object","required":["id","project_id","name","style_config","feature_count","total_size_bytes","base_attributes","created_at","updated_at"],"title":"LayerModel","description":"Model for a layer."},"LayerPlan":{"properties":{"layer_name":{"type":"string","title":"Layer Name","description":"Descriptive name for this layer. For parcel and building layers, use type-first format: 'Parcels - {description}' or 'Buildings - {description}' (e.g., 'Parcels - Commercial', 'Buildings - Large Commercial'). For other layers, use plain names (e.g., 'Schools', 'Denver, CO Boundary'). Do not include spatial relationships in the name."},"description":{"type":"string","title":"Description","description":"Detailed description of what this layer contains and its purpose"},"table_name":{"type":"string","title":"Table Name","description":"Overture Maps table name to use for this layer"},"spatial_filters":{"items":{"$ref":"#/components/schemas/SpatialFilterSpec"},"type":"array","title":"Spatial Filters","description":"Spatial filters defining how this layer relates to other layers. Each filter specifies a reference layer and a spatial operation (INTERSECTS, BUFFER, DISJOINT). Empty list only for the starting geometry layer."},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color","description":"RGBA color string for this layer's default style (e.g., 'rgba(54, 162, 235, 0.5)')"},"layer_id":{"type":"string","format":"uuid","title":"Layer Id","description":"Unique identifier for this layer (database UUID)"}},"type":"object","required":["layer_name","description","table_name","layer_id"],"title":"LayerPlan","description":"A plan for creating a single layer as part of a larger spatial analysis."},"LayerStateChangedEvent":{"properties":{"type":{"type":"string","const":"layer_state_changed","title":"Type","default":"layer_state_changed"},"projectId":{"type":"string","format":"uuid","title":"Projectid"},"layers":{"items":{"$ref":"#/components/schemas/LayerModel"},"type":"array","title":"Layers","default":[]},"deletedLayerIds":{"items":{"type":"string"},"type":"array","title":"Deletedlayerids","default":[]}},"type":"object","required":["projectId"],"title":"LayerStateChangedEvent","description":"Fired after a layer metadata mutation commits (create / delete / rename /\nrestyle / recolor), over the same per-user channel — the layer sibling of\n``ViewStateChangedEvent``.\n\nPayload-rich + version-stamped: the FE applies the carried layer(s) straight\nto its React Query cache without a refetch round-trip, and uses each layer's\n``metadata_version`` to discard stale or out-of-order events. Carries only the\n*affected* layer(s) plus ``deletedLayerIds`` so the FE merges rather than\noverwrites siblings.\n\nUnlike views, the nested layers serialize in their **snake_case** wire shape —\n``LayerModel`` has no field aliases, and the FE reads the same snake_case keys\noff ``GET /projects/{id}/layers`` through ``layerMappers.fromApiModel``. So no\n``field_serializer`` is needed here; the default dump is already the wire shape."},"LayerUpdateRequest":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"style_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Style Config"},"base_attributes":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Base Attributes"},"enrichments":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/LayerEnrichmentUpdate"},"type":"object"},{"type":"null"}],"title":"Enrichments"},"column_display_name_updates":{"anyOf":[{"additionalProperties":{"type":"string","maxLength":255},"type":"object"},{"type":"null"}],"title":"Column Display Name Updates"}},"type":"object","title":"LayerUpdateRequest","description":"Request schema for updating a layer.\n\nAttributes:\n    name: Optional new name for the layer\n    style_config: Optional new style configuration\n    base_attributes: Optional new base attributes\n    enrichments: Optional enrichments update dict. Keys are enrichment IDs (as strings),\n                values are dicts with fields to update (name, description, tool, params, dtype)\n    column_display_name_updates: Optional partial rename map keyed by\n        ``LayerColumn.id``. Each entry sets that column's\n        ``display_name`` only; all other ``LayerColumn`` fields and all\n        other columns on the layer are preserved."},"LayerUpdateResponse":{"properties":{"message":{"type":"string","title":"Message"},"layer":{"$ref":"#/components/schemas/LayerModel"}},"type":"object","required":["message","layer"],"title":"LayerUpdateResponse","description":"Response schema for layer update operations.\n\nAttributes:\n    message: Success message\n    layer: Updated layer model"},"LayerUploadResponse":{"properties":{"message":{"type":"string","title":"Message"},"layer":{"$ref":"#/components/schemas/LayerModel"},"input_rows":{"type":"integer","title":"Input Rows"},"uploaded_rows":{"type":"integer","title":"Uploaded Rows"},"truncated":{"type":"boolean","title":"Truncated"},"geometry_mode":{"type":"string","title":"Geometry Mode"},"out_of_scope_rows":{"type":"integer","title":"Out Of Scope Rows","default":0}},"type":"object","required":["message","layer","input_rows","uploaded_rows","truncated","geometry_mode"],"title":"LayerUploadResponse","description":"Response schema for uploaded generic layers. ``out_of_scope_rows``\ncounts features dropped by the project-county fence — surfaced so the\nclient can report them, never silently swallowed."},"LeaseEscalationType":{"type":"string","enum":["fixed_percent","cpi","hybrid","none","other"],"title":"LeaseEscalationType"},"LegacyShareAccessResponse":{"properties":{"state":{"type":"string","const":"legacy","title":"State"}},"additionalProperties":false,"type":"object","required":["state"],"title":"LegacyShareAccessResponse"},"LoadCapabilityArgs":{"properties":{"id":{"type":"string","title":"Id","description":"The id of the capability to load."}},"type":"object","required":["id"],"title":"LoadCapabilityArgs","description":"Typed arguments for a `load_capability` tool call."},"LoadCapabilityCallPart":{"properties":{"tool_call_id":{"type":"string","title":"Tool Call Id"},"tool_name":{"type":"string","const":"load_capability","title":"Tool Name","default":"load_capability"},"args":{"anyOf":[{"type":"string"},{"$ref":"#/components/schemas/LoadCapabilityArgs"},{"type":"null"}],"title":"Args"},"tool_kind":{"type":"string","const":"capability-load","title":"Tool Kind","default":"capability-load"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"tool-call","title":"Part Kind","default":"tool-call"}},"type":"object","title":"LoadCapabilityCallPart","description":"Typed `ToolCallPart` for the `load_capability` tool."},"LoadCapabilityReturn":{"properties":{"instructions":{"type":"string","title":"Instructions"}},"type":"object","title":"LoadCapabilityReturn","description":"Typed return value for the `load_capability` tool."},"LoadCapabilityReturnPart":{"properties":{"tool_call_id":{"type":"string","title":"Tool Call Id"},"tool_name":{"type":"string","const":"load_capability","title":"Tool Name","default":"load_capability"},"content":{"$ref":"#/components/schemas/LoadCapabilityReturn"},"tool_kind":{"type":"string","const":"capability-load","title":"Tool Kind","default":"capability-load"},"metadata":{"title":"Metadata"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"outcome":{"type":"string","enum":["success","failed","denied","interrupted"],"title":"Outcome","default":"success"},"part_kind":{"type":"string","const":"tool-return","title":"Part Kind","default":"tool-return"}},"type":"object","required":["content"],"title":"LoadCapabilityReturnPart","description":"Typed `ToolReturnPart` for the `load_capability` tool."},"LocalLoginRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"password":{"type":"string","title":"Password"}},"type":"object","required":["email","password"],"title":"LocalLoginRequest","description":"Request model for AUTH_DISABLED local mock login."},"LocalTokenResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"},"user_id":{"type":"string","title":"User Id"}},"type":"object","required":["access_token","user_id"],"title":"LocalTokenResponse","description":"Response model for AUTH_DISABLED local mock login."},"MainAgentThinking":{"type":"string","enum":["auto","none","minimal","low","medium","high","xhigh","max"],"title":"MainAgentThinking","description":"Provider-native thinking choices exposed by the main-agent picker."},"MapActivitySubject":{"properties":{"kind":{"type":"string","enum":["layer","primitive"],"title":"Kind"},"layer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Layer Id"},"filter":{"anyOf":[{"$ref":"#/components/schemas/PrimitiveFilter"},{"type":"null"}]},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"feature_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Feature Count"}},"type":"object","required":["kind"],"title":"MapActivitySubject","description":"One thing a tool call is touching, in a directly paintable shape.\n\n``kind=\"layer\"`` subjects carry a project layer id and paint through the\nclient's layer machinery (layer color, handoff). ``kind=\"primitive\"``\nsubjects carry a ``PrimitiveFilter`` — the county primitive tile contract —\nand paint as a direct ``setFilter``. A subject with neither id nor filter\nis still an observation; the client falls back to its county-shape pulse."},"MapFilterModel":{"properties":{"geometries":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Geometries"},"type":{"type":"string","const":"intersects","title":"Type"}},"type":"object","required":["geometries","type"],"title":"MapFilterModel","description":"Model for a map filter (spatial filter)"},"MapFlyToEvent":{"properties":{"type":{"type":"string","const":"map_fly_to","title":"Type","default":"map_fly_to"},"projectId":{"type":"string","format":"uuid","title":"Projectid"},"bbox":{"prefixItems":[{"type":"number"},{"type":"number"},{"type":"number"},{"type":"number"}],"type":"array","maxItems":4,"minItems":4,"title":"Bbox"}},"type":"object","required":["projectId","bbox"],"title":"MapFlyToEvent","description":"Fired when the agent moves the map camera to a resolved feature, over the\nper-user channel — the reply to a \"zoom to <address/place/parcel>\" request.\n\nCarries the envelope ``bbox`` (``[minLng, minLat, maxLng, maxLat]``) of a feature\nalready in the project's data; the FE ``fitBounds`` to it. ``projectId`` gates the\nmove to the active project (the per-user stream is not project-scoped). camelCase\nwire shape, matching the sibling events.\n\nFire-and-forget / advisory: a dropped publish just means the camera doesn't move —\nthe agent's text reply still names where it went."},"MarkNothingUserFacingRequest":{"properties":{"release_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Release Ids"}},"type":"object","required":["release_ids"],"title":"MarkNothingUserFacingRequest"},"MemberRoleUpdateRequest":{"properties":{"workspace_role":{"$ref":"#/components/schemas/WorkspaceRole","description":"New role for the member: 'writer' or 'reader'"}},"type":"object","required":["workspace_role"],"title":"MemberRoleUpdateRequest","description":"Request model for updating a member's workspace role."},"MissingCounty":{"properties":{"fips":{"type":"string","title":"Fips"},"name":{"type":"string","title":"Name"}},"type":"object","required":["fips","name"],"title":"MissingCounty","description":"The source project's assigned county when the target workspace lacks it."},"MissingCountyCoverageDetail":{"properties":{"code":{"type":"string","title":"Code","default":"missing_county_coverage"},"missing_counties":{"items":{"$ref":"#/components/schemas/MissingCounty"},"type":"array","title":"Missing Counties"},"project_county_missing":{"type":"boolean","title":"Project County Missing","default":false}},"type":"object","required":["missing_counties"],"title":"MissingCountyCoverageDetail","description":"409 detail for a missing project assignment or workspace coverage."},"MissingCountyCoverageResponse":{"properties":{"detail":{"$ref":"#/components/schemas/MissingCountyCoverageDetail"}},"type":"object","required":["detail"],"title":"MissingCountyCoverageResponse","description":"Wire shape of the county-coverage 409.\n\nFastAPI serializes ``HTTPException(detail=...)`` as ``{\"detail\": ...}``, so\nthe documented response body must carry the wrapper — clients read\n``data.detail.missing_counties``."},"ModelRequest":{"properties":{"parts":{"items":{"oneOf":[{"$ref":"#/components/schemas/SystemPromptPart"},{"$ref":"#/components/schemas/UserPromptPart"},{"$ref":"#/components/schemas/SpeechPart"},{"$ref":"#/components/schemas/ToolSearchReturnPart"},{"$ref":"#/components/schemas/LoadCapabilityReturnPart"},{"$ref":"#/components/schemas/ToolReturnPart"},{"$ref":"#/components/schemas/RetryPromptPart"},{"$ref":"#/components/schemas/ToolAvailabilityDeltaPart"}]},"type":"array","title":"Parts"},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp"},"instructions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions"},"kind":{"type":"string","const":"request","title":"Kind","default":"request"},"run_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Run Id"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"},"state":{"type":"string","enum":["complete","interrupted"],"title":"State","default":"complete"}},"type":"object","required":["parts"],"title":"ModelRequest","description":"A request generated by Pydantic AI and sent to a model, e.g. a message from the Pydantic AI app to the model."},"ModelResponse":{"properties":{"parts":{"items":{"oneOf":[{"$ref":"#/components/schemas/TextPart"},{"$ref":"#/components/schemas/ToolSearchCallPart"},{"$ref":"#/components/schemas/LoadCapabilityCallPart"},{"$ref":"#/components/schemas/ToolCallPart"},{"$ref":"#/components/schemas/NativeToolSearchCallPart"},{"$ref":"#/components/schemas/NativeToolCallPart"},{"$ref":"#/components/schemas/NativeToolSearchReturnPart"},{"$ref":"#/components/schemas/NativeToolReturnPart"},{"$ref":"#/components/schemas/ThinkingPart"},{"$ref":"#/components/schemas/CompactionPart"},{"$ref":"#/components/schemas/FilePart"},{"$ref":"#/components/schemas/SpeechPart"}]},"type":"array","title":"Parts"},"usage":{"$ref":"#/components/schemas/RequestUsage"},"model_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Name"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"kind":{"type":"string","const":"response","title":"Kind","default":"response"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Url"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"provider_response_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Response Id"},"finish_reason":{"anyOf":[{"type":"string","enum":["stop","length","content_filter","tool_call","error"]},{"type":"null"}],"title":"Finish Reason"},"run_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Run Id"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"},"state":{"type":"string","enum":["complete","incomplete","suspended","interrupted"],"title":"State","default":"complete"}},"type":"object","required":["parts"],"title":"ModelResponse","description":"A response from a model, e.g. a message from the model to the Pydantic AI app."},"MortgageForeclosureNotice":{"properties":{"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"recording_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recording Date"},"auction_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auction Date"},"unpaid_balance":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Unpaid Balance"},"past_due_amount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Past Due Amount"},"current_lender_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Lender Name"}},"type":"object","title":"MortgageForeclosureNotice","description":"Pre-foreclosure filing detail; only present when a filing exists."},"MortgageInvoluntaryLien":{"properties":{"lien_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lien Type"},"document_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Document Type"},"recording_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recording Date"}},"type":"object","title":"MortgageInvoluntaryLien","description":"One involuntary lien (tax lien, judgment, mechanic's lien): existence + type."},"MortgageOpenLien":{"properties":{"loan_amount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Loan Amount"},"lender_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lender Name"},"lender_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lender Type"},"recording_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recording Date"},"due_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Due Date"},"loan_term_months":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Loan Term Months"},"loan_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Loan Type"},"financing_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Financing Type"},"ltv":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ltv"},"current_estimated_balance":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Current Estimated Balance"},"current_estimated_interest_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Current Estimated Interest Rate"},"estimated_payment_amount":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estimated Payment Amount"},"heloc_flag":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Heloc Flag"},"private_lender":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Private Lender"}},"type":"object","title":"MortgageOpenLien","description":"One currently-open mortgage against the property."},"MortgageProfileModel":{"properties":{"free_and_clear":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Free And Clear"},"open_lien_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Open Lien Count"},"total_open_lien_balance":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Open Lien Balance"},"equity_percent":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Equity Percent"},"estimated_value":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estimated Value"},"foreclosure_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Foreclosure Status"},"has_recorder_evidence":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Recorder Evidence"},"as_of":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of"},"open_liens":{"items":{"$ref":"#/components/schemas/MortgageOpenLien"},"type":"array","title":"Open Liens"},"valuation":{"anyOf":[{"$ref":"#/components/schemas/MortgageValuationSummary"},{"type":"null"}]},"foreclosure":{"anyOf":[{"$ref":"#/components/schemas/MortgageForeclosureNotice"},{"type":"null"}]},"involuntary_liens":{"items":{"$ref":"#/components/schemas/MortgageInvoluntaryLien"},"type":"array","title":"Involuntary Liens"},"recorder_evidence":{"anyOf":[{"$ref":"#/components/schemas/MortgageRecorderEvidence"},{"type":"null"}]}},"type":"object","title":"MortgageProfileModel","description":"The full mortgage & liens profile for one matched property."},"MortgageRecorderEvidence":{"properties":{"has_last_sale":{"type":"boolean","title":"Has Last Sale"},"has_mortgage_history":{"type":"boolean","title":"Has Mortgage History"},"has_any_lien":{"type":"boolean","title":"Has Any Lien"}},"type":"object","required":["has_last_sale","has_mortgage_history","has_any_lien"],"title":"MortgageRecorderEvidence","description":"County-recorder evidence booleans.\n\nInput to a county-level coverage rate, never a per-property coverage\nverdict — a never-refinanced home and an uncovered county share this\nsignature."},"MortgageValuationSummary":{"properties":{"estimated_value":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estimated Value"},"equity_percent":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Equity Percent"},"ltv":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ltv"},"equity_current_estimated_balance":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Equity Current Estimated Balance"},"confidence_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Confidence Score"},"as_of_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"As Of Date"}},"type":"object","title":"MortgageValuationSummary","description":"AVM-derived value and equity — modeled estimates, not recorded facts."},"NativeToolCallPart":{"properties":{"tool_name":{"type":"string","title":"Tool Name"},"args":{"anyOf":[{"type":"string"},{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Args"},"tool_call_id":{"type":"string","title":"Tool Call Id"},"tool_kind":{"anyOf":[{"type":"string","enum":["tool-search","capability-load"]},{"type":"null"}],"title":"Tool Kind"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"builtin-tool-call","title":"Part Kind","default":"builtin-tool-call"}},"type":"object","required":["tool_name"],"title":"NativeToolCallPart","description":"A tool call to a native tool.\n\nFor native tools with a stable cross-provider shape (currently `tool_search`), this base\nclass can be promoted to a typed subclass with a narrowed `args` `TypedDict`. See\n[`NativeToolSearchCallPart`][pydantic_ai.messages.NativeToolSearchCallPart] for the\ncanonical example.\n\nAdding a typed subclass for a future native tool (see `pydantic_ai._tool_search` for\na worked example):\n\n1. Add a sibling `pydantic_ai/_<name>.py` module that defines the cross-provider\n   `TypedDict`s, the `NativeToolCallPart` / `NativeToolReturnPart` subclasses,\n   and registers their narrowers into `_NATIVE_CALL_NARROWERS` /\n   `_NATIVE_RETURN_NARROWERS` keyed by `tool_kind`. Subclass overrides\n   `tool_kind: Literal['<emitter>']` to match the emitting\n   [`AbstractNativeTool.kind`][pydantic_ai.native_tools.AbstractNativeTool.kind],\n   and shadows `args` / `content` with a narrower type.\n2. Late-import the new module from this file (alongside the existing tool-search\n   import) so registration runs whenever `pydantic_ai.messages` is imported.\n3. Add the subclass to `ModelResponsePart`'s discriminated union and to\n   `_model_response_part_discriminator` so Pydantic deserialization auto-promotes\n   on `model_validate` / `model_validate_json`.\n\nDispatch is by `tool_kind`, not `tool_name`. This protects users whose tools happen to\nshare a name with one of ours from accidentally getting their parts promoted (and\nfailing shape validation against the typed `args`/`content`).\n\nThe `provider_details` field carries genuinely non-portable provider extras\n(e.g. Anthropic's `strategy: 'bm25' | 'regex'` for tool search). Promote a field\nto a typed slot in `args` / `content` only when at least two of OpenAI, Anthropic,\nand Google support it (cf. [issue #3885](https://github.com/pydantic/pydantic-ai/issues/3885)).\n\nMCP server tools land here with `tool_kind='mcp_server'` (label stays in\n`tool_name='mcp_server:<label>'`); typed-subclass work for MCP is tracked by\n[issue #3561](https://github.com/pydantic/pydantic-ai/issues/3561)."},"NativeToolReturnPart":{"properties":{"tool_name":{"type":"string","title":"Tool Name"},"content":{"$ref":"#/components/schemas/ToolReturnContent"},"tool_call_id":{"type":"string","title":"Tool Call Id"},"tool_kind":{"anyOf":[{"type":"string","enum":["tool-search","capability-load"]},{"type":"null"}],"title":"Tool Kind"},"metadata":{"title":"Metadata"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"outcome":{"type":"string","enum":["success","failed","denied","interrupted"],"title":"Outcome","default":"success"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"builtin-tool-return","title":"Part Kind","default":"builtin-tool-return"}},"type":"object","required":["tool_name","content"],"title":"NativeToolReturnPart","description":"A tool return message from a native tool.\n\nFor native tools with a stable cross-provider shape (currently `tool_search`), a\n`NativeToolReturnPart` may be promoted to a typed subclass like\n[`NativeToolSearchReturnPart`][pydantic_ai.messages.NativeToolSearchReturnPart]\nwith a narrowed `content` `TypedDict`. See `NativeToolCallPart` for the pattern."},"NativeToolSearchCallPart":{"properties":{"tool_name":{"type":"string","const":"tool_search","title":"Tool Name","default":"tool_search"},"args":{"anyOf":[{"type":"string"},{"$ref":"#/components/schemas/ToolSearchArgs"},{"type":"null"}],"title":"Args"},"tool_call_id":{"type":"string","title":"Tool Call Id"},"tool_kind":{"type":"string","const":"tool-search","title":"Tool Kind","default":"tool-search"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"builtin-tool-call","title":"Part Kind","default":"builtin-tool-call"}},"type":"object","title":"NativeToolSearchCallPart","description":"Typed view of a [`NativeToolCallPart`][pydantic_ai.messages.NativeToolCallPart] for tool search.\n\nUsed on the native server-side tool-search path (Anthropic BM25/regex, OpenAI\nResponses) where the provider executes the search and emits a native result.\nThe local-fallback path uses\n[`ToolSearchCallPart`][pydantic_ai.messages.ToolSearchCallPart] instead.\n\nTo detect a tool-search part regardless of execution path (native server-side\nvs. local fallback), check `part.tool_kind == 'tool-search'` — this works\nacross both call/return and both server/local variants.\n\nShadows `args` with a narrower type. The `str` variant covers the\nstreaming / partial-args case before parsing completes; once parsed,\n`args` is a [`ToolSearchArgs`][pydantic_ai.messages.ToolSearchArgs]\n`TypedDict`."},"NativeToolSearchReturnPart":{"properties":{"tool_name":{"type":"string","const":"tool_search","title":"Tool Name","default":"tool_search"},"tool_call_id":{"type":"string","title":"Tool Call Id"},"tool_kind":{"type":"string","const":"tool-search","title":"Tool Kind","default":"tool-search"},"content":{"$ref":"#/components/schemas/ToolSearchReturnContent"},"metadata":{"title":"Metadata"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"outcome":{"type":"string","enum":["success","failed","denied","interrupted"],"title":"Outcome","default":"success"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"builtin-tool-return","title":"Part Kind","default":"builtin-tool-return"}},"type":"object","required":["content"],"title":"NativeToolSearchReturnPart","description":"Typed view of a [`NativeToolReturnPart`][pydantic_ai.messages.NativeToolReturnPart] for tool search.\n\nUsed on the native server-side tool-search path (Anthropic BM25/regex, OpenAI\nResponses) where the provider executes the search and emits a native result.\nThe local-fallback path uses\n[`ToolSearchReturnPart`][pydantic_ai.messages.ToolSearchReturnPart] instead.\n\nTo detect a tool-search part regardless of execution path (native server-side\nvs. local fallback), check `part.tool_kind == 'tool-search'` — this works\nacross both call/return and both server/local variants.\n\nShadows `content` with a narrower\n[`ToolSearchReturnContent`][pydantic_ai.messages.ToolSearchReturnContent]\n`TypedDict`."},"NavigateCursorResponse":{"properties":{"prev_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prev Id"},"next_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Id"},"position":{"type":"integer","title":"Position"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["prev_id","next_id","position","total"],"title":"NavigateCursorResponse","description":"Server-side cursor result for prev/next navigation.\n\nReplaces the legacy client-side id-array cache (capped at 100k);\neach navigation invocation runs a single CTE on the live filtered\nset, so we cap-free up to whatever the filtered set actually\ncontains. ``position`` is 0-based; ``total`` is the filtered set\nsize."},"NotEnoughContext":{"properties":{"reason":{"type":"string","title":"Reason","description":"The reason why the action is not possible"}},"type":"object","required":["reason"],"title":"NotEnoughContext"},"NumberCondition":{"properties":{"filterType":{"type":"string","const":"number","title":"Filtertype","default":"number"},"type":{"type":"string","enum":["equals","notEqual","greaterThan","greaterThanOrEqual","lessThan","lessThanOrEqual","inRange","blank","notBlank","unavailable"],"title":"Type"},"filter":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Filter"},"filterTo":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Filterto"},"units":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Units"}},"type":"object","required":["type"],"title":"NumberCondition"},"NumericVizStats":{"properties":{"kind":{"type":"string","const":"numeric","title":"Kind","default":"numeric"},"breaks":{"items":{"type":"number"},"type":"array","title":"Breaks"},"min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Max"},"count":{"type":"integer","title":"Count"},"geometry_kind":{"anyOf":[{"type":"string","enum":["point","line","polygon"]},{"type":"null"}],"title":"Geometry Kind"}},"type":"object","required":["breaks","min","max","count","geometry_kind"],"title":"NumericVizStats","description":"Whole-layer stats for one numeric column, for classed map styling.\n\n``breaks`` are ascending class boundaries strictly inside ``min``/``max``,\nwhich together delimit up to five classes — as many as the column's\ndistinct values support. Quintiles when the values are well spread, the\nmidpoints between the distinct values when there are few. Empty ``breaks`` means one\nclass spanning ``min``..``max`` — no boundary could be placed, whether\nbecause there is nothing to divide or because the values are packed against\none end. ``geometry_kind`` tells the client which classed styling applies\n(graded dots for points, choropleth otherwise) — every\nlayer carries both point and fill style layers, so the client cannot\ninfer geometry from the style alone."},"OccupancyStatus":{"type":"string","enum":["leased","vacant","owner_occupied","partially_leased","unknown"],"title":"OccupancyStatus"},"OperatorControlsResponse":{"properties":{"admissions_paused":{"type":"boolean","title":"Admissions Paused"},"public_signup_enabled":{"type":"boolean","title":"Public Signup Enabled"},"seats_used":{"type":"integer","title":"Seats Used"},"seat_cap":{"type":"integer","title":"Seat Cap"}},"type":"object","required":["admissions_paused","public_signup_enabled","seats_used","seat_cap"],"title":"OperatorControlsResponse","description":"The public controls and the capacity they govern."},"OptOutState":{"type":"string","enum":["subscribed","opted_out","unknown"],"title":"OptOutState","description":"Whether a recipient still consents to product updates.\n\n``UNKNOWN`` is a real answer, not a placeholder: opt-out lives only in\nResend and a failed read must not be reported as consent. Distinct from\nexclusion, which is ours to set and ours to lift — this one never is."},"OwnerResidentialMailingAddressModel":{"properties":{"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street","description":"Street line of the residential mailing address."},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City","description":"City."},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State","description":"Two-letter state code."},"zip_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Zip Code","description":"ZIP / postal code."},"resolved_owner_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved Owner Name","description":"The person this address belongs to. For an entity owner this is the decision-maker the entity was pierced to, not the entity itself."},"owner_type":{"type":"string","enum":["individual","entity","unknown"],"title":"Owner Type","description":"Whether the parcel owner is an individual or an entity.","default":"unknown"},"is_available":{"type":"boolean","title":"Is Available","description":"True only when a reliable RESIDENTIAL mailing address was determined. False when only a business / registered-agent address was found — the caller must not persist a business address as a result."},"confidence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Confidence","description":"Qualitative confidence (e.g. high / medium / low)."},"mobile_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mobile Phone","description":"Resolved owner's mobile phone, if known."},"landline_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Landline Phone","description":"Resolved owner's landline phone, if known."},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Resolved owner's email, if known."},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company","description":"Company inferred for the resolved owner (from work email domain), if any."}},"type":"object","required":["is_available"],"title":"OwnerResidentialMailingAddressModel","description":"A resolved residential mailing address for a parcel's decision-making owner."},"OwnershipDuration":{"properties":{"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"},"reasoning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reasoning","description":"The reasoning for the ownership duration."},"sources":{"items":{"type":"string"},"type":"array","title":"Sources","description":"The sources for the ownership duration."}},"type":"object","title":"OwnershipDuration","description":"Property ownership duration representing when ownership began.\n\nUsed for property/parcel ownership (e.g., via deed records).\nCan represent exact year (min == max) or range of possible years.\nConfidence is inferred: exact year = confirmed, range = approximate."},"PDLCompany":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"size":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Size"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"founded":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Founded"},"industry":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Industry"},"location":{"anyOf":[{"$ref":"#/components/schemas/PDLLocation"},{"type":"null"}]},"linkedin_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Url"},"linkedin_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Id"},"facebook_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Facebook Url"},"twitter_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Twitter Url"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"}},"type":"object","title":"PDLCompany","description":"Company information from PDL."},"PDLEducation":{"properties":{"school":{"anyOf":[{"$ref":"#/components/schemas/PDLSchool"},{"type":"null"}]},"degrees":{"items":{"type":"string"},"type":"array","title":"Degrees"},"majors":{"items":{"type":"string"},"type":"array","title":"Majors"},"minors":{"items":{"type":"string"},"type":"array","title":"Minors"},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date"},"gpa":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Gpa"}},"type":"object","title":"PDLEducation","description":"Education information from PDL."},"PDLExperience":{"properties":{"company":{"anyOf":[{"$ref":"#/components/schemas/PDLCompany"},{"type":"null"}]},"title":{"anyOf":[{"$ref":"#/components/schemas/PDLTitle"},{"type":"null"}]},"location_names":{"items":{"type":"string"},"type":"array","title":"Location Names"},"start_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Date"},"is_primary":{"type":"boolean","title":"Is Primary","default":false}},"type":"object","title":"PDLExperience","description":"Work experience from PDL."},"PDLLocation":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"locality":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locality"},"region":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Region"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"continent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Continent"},"metro":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metro"},"geo":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geo"},"street_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street Address"},"address_line_2":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address Line 2"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"}},"type":"object","title":"PDLLocation","description":"Location information from PDL."},"PDLProfile":{"properties":{"network":{"type":"string","title":"Network"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"}},"type":"object","required":["network"],"title":"PDLProfile","description":"Social profile from PDL."},"PDLSchool":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"location":{"anyOf":[{"$ref":"#/components/schemas/PDLLocation"},{"type":"null"}]},"linkedin_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Url"},"linkedin_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Id"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain"}},"type":"object","title":"PDLSchool","description":"School information from PDL."},"PDLTitle":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"sub_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sub Role"},"levels":{"items":{"type":"string"},"type":"array","title":"Levels"},"class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Class"}},"type":"object","title":"PDLTitle","description":"Job title information from PDL."},"PaginatedFeatureRow":{"additionalProperties":true,"type":"object"},"PaginatedFeaturesResponse":{"properties":{"rows":{"items":{"$ref":"#/components/schemas/PaginatedFeatureRow"},"type":"array","title":"Rows"},"last_row":{"type":"integer","title":"Last Row"},"matched_rows":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Matched Rows"},"total_rows":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Rows"},"column_meta":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/ColumnMeta"},"type":"object"},{"type":"null"}],"title":"Column Meta"}},"type":"object","required":["rows","last_row"],"title":"PaginatedFeaturesResponse","description":"Response for the paginated sandbox query endpoint.\n\n``last_row`` is the exact filtered match count, computed alongside the\npage via a single windowed ``COUNT(*) OVER()``. AG Grid uses it to size\nthe scrollbar.\n\n``matched_rows`` and ``total_rows`` are the footer's \"X of Y\", sent\ntogether or not at all. Both are measured on one request against one\nrelation, so a client that renders them as a pair can never combine\ncounts drawn from different layers or from different moments in the\nlayer's life. They are present only on a request whose counts describe\nthe whole layer — a first page with no ``group_keys``; a later page\nrepeats a count the first already carried, and a child block counts one\ngroup. ``matched_rows`` is null on a grouped request, whose ``last_row``\ncounts groups and so has nothing comparable to ``total_rows``.\n\nThis shape is deliberately reconciled server-side: a client that\nre-derived \"is this the footer's request?\" from the request params would\nbe a second copy of that rule, free to drift from this one."},"ParcelCoverageResponse":{"properties":{"counties":{"items":{"$ref":"#/components/schemas/CoveredCounty"},"type":"array","title":"Counties"}},"type":"object","required":["counties"],"title":"ParcelCoverageResponse","description":"Every covered county, for the internal coverage choropleth."},"ParcelSourceClass":{"type":"string","enum":["authoritative","regrid","no_geometry","point_fallback"],"title":"ParcelSourceClass","description":"Geometry-provenance tier in the coverage lattice, independent of join\nquality (that's the match rates). ``REGRID`` / ``NO_GEOMETRY`` describe the\nclasses a county could be parked at, and give the coverage recorder's\ncross-county views a uniform column. ``POINT_FALLBACK`` is the disclosed\nfloor for a must-pay county: its parcels land as address points from the\nproperty-record delivery (``source_kind`` NULL — that delivery is not a\ngeometry source, and NULL keeps\nthe county invisible to the supplement/fence readers)."},"ParcelSourceKind":{"type":"string","enum":["arcgis_curated","geoparquet_native","socrata","statewide_arcgis","statewide_bulk","bq_state_export"],"title":"ParcelSourceKind","description":"Provenance of a county's parcels — which producer owns it. The first five\nare *supplement* kinds (per-county gov pulls / statewide layers), which drive\nthe supplement source set + every source fence; ``bq_state_export`` is the\ndefault 50-state BigQuery bulk (Regrid) ingest, which the runtime serves\ndirectly (not a supplement) and the fences ignore. A typo'd value would\nmis-fence and double-source, so it's CHECK-constrained to fail closed."},"PasswordResetEmailRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"PasswordResetEmailRequest","description":"Request model for sending a password reset email."},"PendingEnrichmentRef":{"properties":{"id":{"type":"string","title":"Id","description":"UUID of the skeleton enrichment row."},"name":{"type":"string","title":"Name","description":"Internal name of the enrichment."},"display_name":{"type":"string","title":"Display Name","description":"User-visible name for the enrichment."}},"type":"object","required":["id","name","display_name"],"title":"PendingEnrichmentRef","description":"Reference to a skeleton enrichment that is still being configured."},"Plan":{"properties":{"type":{"$ref":"#/components/schemas/PlanType"},"max_features_per_layer":{"type":"integer","title":"Max Features Per Layer"},"max_layers_per_project":{"type":"integer","title":"Max Layers Per Project"},"default_enrichment_credits":{"type":"integer","title":"Default Enrichment Credits"}},"type":"object","required":["type","max_features_per_layer","max_layers_per_project","default_enrichment_credits"],"title":"Plan","description":"Plan configuration including type and limits."},"PlanType":{"type":"string","enum":["beta"],"title":"PlanType","description":"Available user plan types with different feature restrictions."},"PrimitiveFilter":{"properties":{"layer":{"type":"string","title":"Layer"},"property":{"type":"string","title":"Property"},"table":{"type":"string","title":"Table"},"values":{"items":{"type":"string"},"type":"array","title":"Values"},"count":{"type":"integer","title":"Count"},"score":{"type":"number","title":"Score"}},"type":"object","required":["layer","property","table","values","count","score"],"title":"PrimitiveFilter","description":"One table's contribution to a paintable subject.\n\n``layer`` and ``property`` name a source-layer and baked property in the\ncounty primitive tile, so the client turns this straight into a Mapbox\nfilter without a second lookup. An empty ``values`` list means the whole\nsource layer: paint every feature the table bakes into the tile. ``count``\nis how many features in the county the values cover — the client sizes and\norders the paint by it, and it is also what tells an empty-but-matched\ntable apart from a missing one."},"PrimitiveMatchRequest":{"properties":{"q":{"type":"string","maxLength":400,"title":"Q"}},"type":"object","required":["q"],"title":"PrimitiveMatchRequest","description":"The prompt to resolve. POSTed as a body rather than a query string so\nthe user's chat text stays out of access logs, proxy logs, and URL-keyed\nspan attributes."},"PrimitiveMatchResponse":{"properties":{"filters":{"items":{"$ref":"#/components/schemas/PrimitiveFilter"},"type":"array","title":"Filters"},"regions":{"items":{"$ref":"#/components/schemas/PrimitiveRegion"},"type":"array","title":"Regions","default":[]},"term_count":{"type":"integer","title":"Term Count"}},"type":"object","required":["filters","term_count"],"title":"PrimitiveMatchResponse","description":"Resolved semantic filters for a prompt, best-scoring table first."},"PrimitiveRegion":{"properties":{"kind":{"type":"string","title":"Kind"},"label":{"type":"string","title":"Label"},"geometry":{"additionalProperties":true,"type":"object","title":"Geometry"}},"type":"object","required":["kind","label","geometry"],"title":"PrimitiveRegion","description":"A geometry the prompt resolved to, drawn rather than filtered.\n\nSpatial words have no tile value to filter on — \"coastal\" is a\nrelationship, not an attribute — so they come back as geometry the client\ndraws directly. ``kind`` distinguishes a derived band (``coastal``), a\nnamed area polygon (``area``), and a geocoded best-guess disc\n(``point_buffer``) so the client can style certainty honestly."},"ProjectAddressResolveManyRequest":{"properties":{"queries":{"items":{"type":"string","maxLength":256},"type":"array","maxItems":1000,"minItems":1,"title":"Queries"}},"type":"object","required":["queries"],"title":"ProjectAddressResolveManyRequest","description":"Batch resolve inside an existing project — chat paste and the Door 2\nimport review. The county is not sent — it's derived server-side from the\nproject's canonical ``county_fips`` (the client stays county-agnostic;\nderiving it from the boundary layer relation is the anti-pattern this\navoids).\n\nShares ``ADDRESS_ROW_CAP`` with the pre-project request for the reason\nstated there: the import dialog resolves through this route, so the two caps\nare one cap."},"ProjectDeleteResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"ProjectDeleteResponse","description":"Response model for project deletion endpoint\n\nAttributes:\n    message: Descriptive message about the result"},"ProjectInFlightTasks":{"properties":{"project_id":{"type":"string","format":"uuid","title":"Project Id","description":"The project ID"},"tasks":{"items":{"$ref":"#/components/schemas/InFlightTaskResponse"},"type":"array","title":"Tasks","description":"List of in-flight tasks for this project"},"count":{"type":"integer","title":"Count","description":"Number of in-flight tasks for this project"},"batches":{"items":{"$ref":"#/components/schemas/BatchEnrichmentInfo"},"type":"array","title":"Batches","description":"Run-scoped progress per enrichment action (MAIA-2116)"},"totals_by_field":{"additionalProperties":{"type":"integer"},"type":"object","title":"Totals By Field","description":"DEPRECATED (MAIA-2116): rolling per-field totals; use `batches`"},"field_info":{"additionalProperties":{"$ref":"#/components/schemas/FieldEnrichmentInfo"},"type":"object","title":"Field Info","description":"DEPRECATED (MAIA-2116): rolling per-field info; use `batches`"}},"type":"object","required":["project_id","tasks","count"],"title":"ProjectInFlightTasks","description":"In-flight tasks for a single project."},"ProjectKnowledgeEntryCreateRequest":{"properties":{"title":{"type":"string","maxLength":120,"minLength":1,"title":"Title"},"content":{"type":"string","maxLength":100000,"minLength":1,"title":"Content"}},"type":"object","required":["title","content"],"title":"ProjectKnowledgeEntryCreateRequest","description":"Request body for creating an entry at a path-bound project scope."},"ProjectKnowledgeSkillContextStatus":{"properties":{"configured_workspace_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Configured Workspace Id"},"configured_workspace_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Configured Workspace Name"},"effective_mode":{"$ref":"#/components/schemas/ContextMode"},"fallback_reason":{"anyOf":[{"$ref":"#/components/schemas/ContextFallbackReason"},{"type":"null"}]}},"type":"object","required":["configured_workspace_id","configured_workspace_name","effective_mode","fallback_reason"],"title":"ProjectKnowledgeSkillContextStatus","description":"Saved and effective workspace context for an internal project."},"ProjectListResponse":{"properties":{"projects":{"anyOf":[{"items":{"$ref":"#/components/schemas/ProjectResponse"},"type":"array"},{"type":"null"}],"title":"Projects"}},"type":"object","title":"ProjectListResponse","description":"Response model for listing all projects\n\nAttributes:\n    projects: List of projects if available"},"ProjectLockStatus":{"properties":{"is_locked":{"type":"boolean","title":"Is Locked","description":"Whether the project is currently locked."},"locked_by_user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locked By User Id","description":"User ID of the lock holder, if locked."},"locked_by_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locked By Display Name","description":"Display name of the lock holder for UI."},"locked_by_avatar_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Locked By Avatar Color","description":"Avatar color name of the lock holder for UI."},"is_current_user":{"type":"boolean","title":"Is Current User","description":"True when the current user holds the lock.","default":false},"ttl_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Ttl Seconds","description":"Remaining TTL of the lock in seconds, if locked."}},"type":"object","required":["is_locked"],"title":"ProjectLockStatus","description":"Status of the project editing lock."},"ProjectPlan":{"properties":{"plan_name":{"type":"string","title":"Plan Name","description":"Name for this analysis plan. Use 'Geography — Description' format: lead with the location, em dash, then the topic (e.g., 'Denver, CO — Owner Occupied Parcels')"},"geography":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geography","description":"The project's geography as a short human-readable label (e.g. 'Denver, CO', 'Maricopa County, AZ') — the same location that leads plan_name. Surfaced in the UI; set it whenever the analysis is tied to a place, leave null when it isn't."},"description":{"type":"string","title":"Description","description":"Overall description of what this plan accomplishes"},"layers":{"items":{"$ref":"#/components/schemas/LayerPlan"},"type":"array","title":"Layers","description":"All layers needed for this analysis, in dependency order"},"primary_layer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Primary Layer Name","description":"Name of the primary layer — the entity the user will analyze, enrich, and act on. This layer is shown by default after project creation."},"additional_project_info":{"type":"string","title":"Additional Project Info","description":"Additional context about the project including user's goals, role in company/identity, industry, and other helpful information for future context","default":""},"primary_layer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Primary Layer Id","description":"Return the layer_id of the primary layer.\n\nResolves primary_layer_name to a layer_id. Falls back to the last\nlayer for backward compatibility with plans created before this field.","readOnly":true}},"type":"object","required":["plan_name","description","layers","primary_layer_id"],"title":"ProjectPlan","description":"Tracks the current state of all layers in a project.\n\nInitially created during project setup, then kept in sync as the agent\nadds or removes layers. Used by the UI to\ndisplay a structured project overview. Not injected into agent context\nfor decision-making — agents use layer context instead."},"ProjectRenamedEvent":{"properties":{"type":{"type":"string","const":"project_renamed","title":"Type","default":"project_renamed"},"projectId":{"type":"string","format":"uuid","title":"Projectid"},"name":{"type":"string","title":"Name"},"titleSource":{"$ref":"#/components/schemas/ProjectTitleSource"}},"type":"object","required":["projectId","name","titleSource"],"title":"ProjectRenamedEvent","description":"Fired when a project's name changes server-side, over the per-user channel.\n\nThe trigger today is auto-title generation: a fire-and-forget task that\ngenerates a name several seconds into the turn, and can retry on a *later*\nmessage. By then the project is already ``ready`` and the FE's creating-project\npoller has stopped watching it, so without this event the new name only surfaces\non the next projects refetch — a manual refresh in practice.\n\nCarries the coordinates the FE needs to patch the projects-list cache in place:\n``projectId`` to locate the row, ``name`` for the display, and ``titleSource``\nso the cached row matches what a refetch would read. camelCase wire shape,\nmatching ``ViewStateChangedEvent`` / ``LayerStateChangedEvent``.\n\nAdvisory only — a dropped publish degrades to the FE's reconnect-resync."},"ProjectResponse":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","default":""},"additional_project_info":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Additional Project Info"},"status":{"$ref":"#/components/schemas/ProjectStatus","default":"pending"},"title_source":{"$ref":"#/components/schemas/ProjectTitleSource","default":"user"},"is_plan_ready":{"type":"boolean","title":"Is Plan Ready","default":false},"views":{"anyOf":[{"items":{"$ref":"#/components/schemas/ViewModel-Output"},"type":"array"},{"type":"null"}],"title":"Views"},"default_view_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default View Id"},"project_plan":{"anyOf":[{"$ref":"#/components/schemas/ProjectPlan"},{"type":"null"}]},"thumbnail_bounds":{"anyOf":[{"$ref":"#/components/schemas/ThumbnailBounds"},{"type":"null"}]},"is_sandbox":{"type":"boolean","title":"Is Sandbox","default":false},"county_fips":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"County Fips"},"visibility":{"anyOf":[{"$ref":"#/components/schemas/ProjectVisibility"},{"type":"null"}]},"is_owner":{"type":"boolean","title":"Is Owner","default":true},"can_edit":{"type":"boolean","title":"Can Edit","default":true},"owner_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Name"},"shared_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Shared By Name"},"owner_branded_as_maia":{"type":"boolean","title":"Owner Branded As Maia","default":false},"last_edited_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edited By Name"},"last_edited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Edited At"},"last_edit_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edit Description"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["id","name"],"title":"ProjectResponse","description":"API response model for a project with string IDs.\n\nAttributes:\n    id: String representation of project UUID\n    name: Display name of the project\n    description: Optional description of the project\n    status: Project lifecycle status (pending/ready/failed/archived). 'ready' replaces the old is_created=True.\n    is_plan_ready: Whether the project plan is ready for the user to create the project\n    visibility: Project visibility status (None=private, workspace_read=view only, workspace_write=editable, example=curated)\n    is_owner: Whether the requesting user owns this project\n    owner_name: Display name of the project owner"},"ProjectShareAccessMode":{"type":"string","enum":["geometry_only","gated"],"title":"ProjectShareAccessMode"},"ProjectStatus":{"type":"string","enum":["pending","ready","failed","archived"],"title":"ProjectStatus","description":"Lifecycle status for a project.\n\nReplaces the boolean ``is_created`` whose name implied \"was created\"\n(always True once inserted) but semantically meant \"is ready for the\ndashboard to show.\" Promoting to an enum lets new states (FAILED,\nARCHIVED) join without contorting the boolean.\n\n- PENDING: row inserted, sandbox resources not yet materialized\n- READY:   resources in place; visible on dashboard\n- FAILED:  build raised mid-flight (sandbox saga rollback uses\n           hard-delete instead, so this state is reserved for\n           future async build paths that can't roll back atomically)\n- ARCHIVED: user-archived; hidden by default"},"ProjectTitleSource":{"type":"string","enum":["placeholder","auto","user"],"title":"ProjectTitleSource","description":"Provenance + lifecycle for the project's name field.\n\nReplaces an em-dash string heuristic (`\" — \" not in project.name`)\nthat gated whether the sandbox auto-titler should rename a project\nfrom its skeleton name. Encoding the decision as a typed enum makes\nthe check a single comparison and prevents future titlers that\nhappen to produce em-dashes from silently disabling the branch.\n\n- PLACEHOLDER: title is initial scaffolding (sandbox skeleton's\n  \"Boulder County\", initial scaffold name); eligible to be\n  replaced by the next titler.\n- AUTO: title set by an LLM auto-titler (agent_service\n  first-message rename or project setup using the user's plan\n  name); final.\n- USER: title set by an explicit user rename via PUT\n  /projects/{id}; final."},"ProjectUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name","description":"New name for the project"},"description":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Description","description":"New description for the project"},"visibility":{"anyOf":[{"$ref":"#/components/schemas/ProjectVisibilityUpdate"},{"type":"null"}],"description":"Project visibility: 'private' (only owner), 'workspace_read' (team can view), or 'workspace_write' (team writers can edit)"}},"type":"object","title":"ProjectUpdate","description":"Request model for updating a project's basic information.\n\nAttributes:\n    name: Optional new name for the project\n    description: Optional new description for the project\n    visibility: Optional new visibility ('private', 'workspace_read', or 'workspace_write')"},"ProjectUpdateResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"},"project":{"anyOf":[{"$ref":"#/components/schemas/ProjectResponse"},{"type":"null"}]}},"type":"object","required":["success","message"],"title":"ProjectUpdateResponse","description":"Response model for project update endpoint.\n\nAttributes:\n    success: Boolean indicating if the project was updated successfully\n    message: Descriptive message about the result\n    project: Optional updated project data (only present on success)"},"ProjectVisibility":{"type":"string","enum":["example","workspace_read","workspace_write"],"title":"ProjectVisibility","description":"Visibility status for projects.\n\nNULL/None = private (default, only owner can see)\nWORKSPACE_READ = visible to all workspace members (read-only)\nWORKSPACE_WRITE = editable by workspace writers\nEXAMPLE = curated example project visible to all users"},"ProjectVisibilityUpdate":{"type":"string","enum":["private","workspace_read","workspace_write"],"title":"ProjectVisibilityUpdate","description":"User-facing visibility options for updating project visibility.\n\nSeparate from ProjectVisibility to:\n- Prevent setting visibility to 'example' via the API\n- Map 'private' to None (NULL) in the database"},"PublicSignupControlUpdate":{"properties":{"admissions_paused":{"type":"boolean","title":"Admissions Paused"},"public_signup_enabled":{"type":"boolean","title":"Public Signup Enabled"}},"additionalProperties":false,"type":"object","required":["public_signup_enabled"],"title":"PublicSignupControlUpdate"},"QueryParseItem":{"properties":{"kind":{"$ref":"#/components/schemas/QueryParseItemKind","description":"'layer' for data from core dataset, 'enrichment' for external/derived data"},"type":{"type":"string","title":"Type","description":"For layers: Overture Maps table name (e.g., 'division_area', 'building', 'place', 'segment', 'parcel'). For enrichments: enrichment tool name (e.g., 'General', 'Contacts', 'OwnerOccupied', 'TenantInfo')."},"name":{"type":"string","title":"Name","description":"Human-readable name (e.g., 'Adams County Boundary', 'Commercial Buildings', 'Solar Potential')"},"source_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Text","description":"The exact substring from the user's query that this item was identified from"}},"type":"object","required":["kind","type","name"],"title":"QueryParseItem","description":"A single item identified from a user query — either a layer or an enrichment."},"QueryParseItemKind":{"type":"string","enum":["layer","enrichment"],"title":"QueryParseItemKind","description":"Whether a parsed item is a layer (from core dataset) or an enrichment."},"QueryParseRequest":{"properties":{"query_text":{"type":"string","maxLength":20000,"minLength":1,"title":"Query Text","description":"The user's natural language query to parse"}},"type":"object","required":["query_text"],"title":"QueryParseRequest","description":"Request body for the real-time query parse endpoint."},"QueryParseResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/QueryParseItem"},"type":"array","title":"Items","description":"Layers and enrichments identified from the query"},"requirements_met":{"$ref":"#/components/schemas/RequirementsCheck","description":"Which key requirements from the query are satisfiable"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings","description":"Warnings for the user about the parsed geography."},"multi_geography_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Multi Geography Error","description":"Error when the query targets multiple separate geographies (only one is supported per project)"}},"type":"object","required":["requirements_met"],"title":"QueryParseResponse","description":"Lightweight real-time parse of a user query, used for live preview chips."},"ReadyResponse":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"ReadyResponse"},"RecipientStatus":{"type":"string","enum":["active","suspended"],"title":"RecipientStatus","description":"Whether a recipient's account is suspended, at either level.\n\n``SUSPENDED`` means the user is suspended or their workspace is — it is a\nstatement about account state, not about whether someone is still a\ncustomer, which is a fact this system never holds.\n\nPushed to Resend as a contact property, so the values are visible outside\nthis codebase and are hashed into the contact-sync fingerprint: changing one\nre-pushes every contact on the next sync.\n\nRenaming a value is safe only while segment membership stays explicit —\nthe sync adds and removes contacts by API call. A filter-based segment\nkeyed on this property would make a rename empty the audience silently."},"RecipientSummaryResponse":{"properties":{"active":{"type":"integer","title":"Active"},"suspended":{"type":"integer","title":"Suspended"},"staff":{"type":"integer","title":"Staff"},"total":{"type":"integer","title":"Total"},"excluded":{"type":"integer","title":"Excluded"}},"type":"object","required":["active","suspended","staff","total","excluded"],"title":"RecipientSummaryResponse","description":"The audience as it stands, without touching Resend.\n\nWhat the confirm dialog counts: asking Resend would mean mutating the\ncontact list just to render a number. Every count is of the non-excluded —\nthe number shown is the number a send reaches.\n\n``active``/``suspended``/``staff`` are disjoint and sum to ``total``:\nthe first two count customers by account state, and our own team is\ncounted only in ``staff``."},"RecordInteractiveAnswerResponse":{"properties":{"recorded":{"type":"boolean","title":"Recorded","description":"True iff a matching prior question was found and patched."}},"type":"object","required":["recorded"],"title":"RecordInteractiveAnswerResponse","description":"Result of persisting a feature-bound pick that skipped the chat turn."},"ReleaseEmailDigestResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"month_start":{"type":"string","format":"date","title":"Month Start"},"covers_start":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Covers Start"},"covers_end":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Covers End"},"subject":{"type":"string","title":"Subject"},"preheader":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preheader"},"body_markdown":{"type":"string","title":"Body Markdown"},"status":{"$ref":"#/components/schemas/ReleaseEmailDigestStatus"},"last_test_sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Test Sent At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent At"},"recipient_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Recipient Count"},"resend_broadcast_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resend Broadcast Id"},"internal_test_broadcast_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Internal Test Broadcast Id"},"internal_test_sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Internal Test Sent At"},"is_sent":{"type":"boolean","title":"Is Sent"},"is_locked":{"type":"boolean","title":"Is Locked"},"is_test_send_current":{"type":"boolean","title":"Is Test Send Current"}},"type":"object","required":["id","month_start","covers_start","covers_end","subject","preheader","body_markdown","status","last_test_sent_at","updated_at","sent_at","recipient_count","resend_broadcast_id","internal_test_broadcast_id","internal_test_sent_at","is_sent","is_locked","is_test_send_current"],"title":"ReleaseEmailDigestResponse"},"ReleaseEmailDigestStatus":{"type":"string","enum":["draft","sending","sent"],"title":"ReleaseEmailDigestStatus","description":"Where a digest sits between editable and shipped.\n\n``SENDING`` exists so the claim on a send can be taken *before* Resend is\ncalled: the broadcast is the irreversible step, and a status that only\nchanged after it returned would let a double click or a retry mail every\ncustomer twice."},"ReleaseEmailRecipientResponse":{"properties":{"email":{"type":"string","title":"Email"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"workspace_name":{"type":"string","title":"Workspace Name"},"status":{"$ref":"#/components/schemas/RecipientStatus"},"plan_type":{"type":"string","title":"Plan Type"},"is_excluded":{"type":"boolean","title":"Is Excluded"},"is_internal":{"type":"boolean","title":"Is Internal"},"opt_out_state":{"$ref":"#/components/schemas/OptOutState"}},"type":"object","required":["email","display_name","workspace_name","status","plan_type","is_excluded","is_internal","opt_out_state"],"title":"ReleaseEmailRecipientResponse","description":"One row of the audience, as the recipient list renders it.\n\nThe same projection the contact sync pushes to Resend — nothing here that\nResend would not also hold."},"ReleaseNoteEntryListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ReleaseNoteEntryResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"ReleaseNoteEntryListResponse","description":"One staff page plus the filtered total, computed from the same filters\nso the count can never disagree with the page."},"ReleaseNoteEntryResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"title":{"type":"string","title":"Title"},"body_markdown":{"type":"string","title":"Body Markdown"},"status":{"$ref":"#/components/schemas/ReleaseNoteEntryStatus"},"publish_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Publish At"},"week_start":{"type":"string","format":"date","title":"Week Start"},"deleted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Deleted At"}},"type":"object","required":["id","title","body_markdown","status","publish_at","week_start"],"title":"ReleaseNoteEntryResponse"},"ReleaseNoteEntryStatus":{"type":"string","enum":["draft","published"],"title":"ReleaseNoteEntryStatus"},"ReopenDigestRequest":{"properties":{"acknowledge_prior_recipients":{"type":"boolean","title":"Acknowledge Prior Recipients","default":false},"acknowledged_broadcast_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Acknowledged Broadcast Id"}},"type":"object","title":"ReopenDigestRequest","description":"Reopening a sent digest, with the double-send acknowledged.\n\nDefaults false so an omitted acknowledgement is refused rather than assumed,\nkeeping a client from reopening a digest that reached customers without the\noperator having been shown who it reached."},"ReportActionsPayload":{"properties":{"intent_id":{"type":"string","minLength":1,"title":"Intent Id","description":"Short stable id you pick for this unit of work (e.g. 'score-parcels'); reuse it to re-report the same unit on failure."},"summary":{"type":"string","minLength":1,"title":"Summary","description":"Plain-language description of the work, shown to the user in place of the raw tool steps — describe the outcome, never the SQL or table names."},"ok":{"type":"boolean","title":"Ok","description":"True for the optimistic announcement as you start; resend with the same intent_id and False if the work fails.","default":true}},"type":"object","required":["intent_id","summary"],"title":"ReportActionsPayload"},"RequestMatch":{"type":"string","enum":["confirmed","partial","contradicted","not_checked"],"title":"RequestMatch","description":"Whether a candidate names the address that was asked for.\n\nThe judgment a surface would otherwise try to recover from ``similarity``, which\ncannot carry it: a hit promoted from a street scores the street alone, so it\nreaches 1.0 while naming a different house, and the parcel row that names the\nright house scores the whole string and sinks as the user types more of it.\n\n``partial`` separates \"not finished typing\" from \"names another property\" — the\naddress comparison works on whole words, so a fragment reads as a different word\nand would otherwise be indistinguishable from a wrong address. It licenses\nshowing a candidate, never calling it exact and never pre-selecting it."},"RequestUsage":{"properties":{"input_tokens":{"type":"integer","title":"Input Tokens","default":0},"cache_write_tokens":{"type":"integer","title":"Cache Write Tokens","default":0},"cache_read_tokens":{"type":"integer","title":"Cache Read Tokens","default":0},"output_tokens":{"type":"integer","title":"Output Tokens","default":0},"input_audio_tokens":{"type":"integer","title":"Input Audio Tokens","default":0},"cache_audio_read_tokens":{"type":"integer","title":"Cache Audio Read Tokens","default":0},"output_audio_tokens":{"type":"integer","title":"Output Audio Tokens","default":0},"details":{"additionalProperties":{"type":"integer"},"type":"object","title":"Details"},"cost":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Cost"}},"type":"object","title":"RequestUsage","description":"LLM usage associated with a single request.\n\nThis is an implementation of `genai_prices.types.AbstractUsage` so it can be used to calculate the price of the\nrequest using [genai-prices](https://github.com/pydantic/genai-prices)."},"RequirementsCheck":{"properties":{"location":{"type":"boolean","title":"Location","description":"Whether the query specifies a geographic location"},"size_range":{"type":"boolean","title":"Size Range","description":"Whether any size/area criteria can be satisfied (building roof area, parcel lot size, etc.)"},"use_type":{"type":"boolean","title":"Use Type","description":"Whether property type, use type, or zoning criteria can be satisfied (from buildings, parcels, or places)"},"contextual_data":{"type":"boolean","title":"Contextual Data","description":"Whether contextual data needs (enrichments, POIs) can be satisfied"}},"type":"object","required":["location","size_range","use_type","contextual_data"],"title":"RequirementsCheck","description":"Tracks which key requirements from the query are satisfiable."},"ResearchOutcome":{"type":"string","enum":["completed","insufficient_inputs","sources_blocked","sources_failed_transient"],"title":"ResearchOutcome","description":"Why a null final is null. Only ``SOURCES_FAILED_TRANSIENT`` is retryable.\n\nShared vocabulary between the producer's structured self-report\n(``ChatResearchOutcomeMixin``) and the consumer-side classifier\n(``core/services/enrichment_research_outcome.py``), so the two stay\ndirectly comparable. Lives here rather than in the service module because\n``core/models`` is an import-linter leaf and must not import\n``core/services``."},"ResetFeatureOverridesResponse":{"properties":{"key":{"type":"string","title":"Key"},"cleared_count":{"type":"integer","title":"Cleared Count"}},"type":"object","required":["key","cleared_count"],"title":"ResetFeatureOverridesResponse","description":"Result from clearing every per-workspace override for one feature."},"ResolutionOutcome":{"type":"string","enum":["matched","not_in_dataset","not_loaded_county"],"title":"ResolutionOutcome","description":"Result classification. ``not_loaded_county`` (a real reference in a county\nthis workspace hasn't loaded) is reserved for the forward-geocoder path, the\nonly place able to confirm a reference is real and name its county."},"ResourceOperation":{"type":"string","enum":["create","update","delete"],"title":"ResourceOperation","description":"Enum for operations that can be performed on resources."},"ResourceReference":{"properties":{"resource_type":{"$ref":"#/components/schemas/ResourceType","description":"The type of resource"},"operation":{"$ref":"#/components/schemas/ResourceOperation","description":"The operation that was performed on the resource"},"resource_id":{"type":"string","title":"Resource Id","description":"The ID of the resource"},"display_name":{"type":"string","title":"Display Name","description":"Display name for the resource"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At","description":"ISO timestamp when resource was created in this chat"},"feature_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Feature Count","description":"Number of features in the created resource"},"data_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Data Version","description":"Layer data version after the operation"},"task_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Id","description":"Celery task ID for async operations like deep research"}},"type":"object","required":["resource_type","operation","resource_id","display_name"],"title":"ResourceReference","description":"Reference to a resource created or modified during chat."},"ResourceType":{"type":"string","enum":["enrichment","layer","view"],"title":"ResourceType","description":"Enum for different resource types that can be referenced in chat."},"RetellConfigResponse":{"properties":{"retell_agent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Retell Agent Id"},"retell_qualify_agent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Retell Qualify Agent Id"},"retell_from_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Retell From Number"},"retell_api_key_masked":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Retell Api Key Masked"},"retell_signing_secret_masked":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Retell Signing Secret Masked"},"auto_dial_enabled":{"type":"boolean","title":"Auto Dial Enabled","default":false},"monthly_dial_minute_cap":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Monthly Dial Minute Cap"}},"type":"object","title":"RetellConfigResponse","description":"Per-workspace Retell account config. Secrets returned as last-4\nmasked hints only — never the decrypted value."},"RetellConfigUpdateRequest":{"properties":{"retell_agent_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Retell Agent Id"},"retell_qualify_agent_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Retell Qualify Agent Id"},"retell_from_number":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Retell From Number"},"retell_api_key":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Retell Api Key"},"retell_signing_secret":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Retell Signing Secret"},"auto_dial_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Dial Enabled"},"monthly_dial_minute_cap":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Monthly Dial Minute Cap"}},"type":"object","title":"RetellConfigUpdateRequest","description":"Partial update for per-workspace Retell config (internal admin only).\n\nPass an explicit `null` to clear an override (the dispatch path then\nfalls back to env defaults). Omit a field to leave it untouched.\n\n`auto_dial_enabled` is the single gate that turns auto-dial on for the\nworkspace — there is no PostHog flag layered on top, so flipping this\nto true makes the feature visible to workspace users immediately."},"RetryPromptPart":{"properties":{"content":{"anyOf":[{"items":{"$ref":"#/components/schemas/ErrorDetails"},"type":"array"},{"type":"string"}],"title":"Content"},"tool_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tool Name"},"tool_call_id":{"type":"string","title":"Tool Call Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"part_kind":{"type":"string","const":"retry-prompt","title":"Part Kind","default":"retry-prompt"}},"type":"object","required":["content"],"title":"RetryPromptPart","description":"A message back to a model asking it to try again.\n\nThis can be sent for a number of reasons:\n\n* Pydantic validation of tool arguments failed, here content is derived from a Pydantic\n  [`ValidationError`][pydantic_core.ValidationError]\n* a tool raised a [`ModelRetry`][pydantic_ai.exceptions.ModelRetry] exception\n* no tool was found for the tool name\n* the model returned plain text when a structured response was expected\n* Pydantic validation of a structured response failed, here content is derived from a Pydantic\n  [`ValidationError`][pydantic_core.ValidationError]\n* an output validator raised a [`ModelRetry`][pydantic_ai.exceptions.ModelRetry] exception"},"RollUpOutcome":{"type":"string","enum":["created","merged","merged_into_published","merged_after_digest","no_changes"],"title":"RollUpOutcome","description":"What one week roll-up run did.\n\n``NO_CHANGES`` is a first-class outcome rather than an empty duplicate\ndraft — a re-run with nothing new must say so, not mint one.\n\nA week holds one entry, so every merge outcome names what the merge\ntouched. ``MERGED_INTO_PUBLISHED`` is separate from ``MERGED`` because the\nentry it grew is already in front of customers: the operator is editing\nlive copy, not a draft, and nothing else on the response says so.\n\n``MERGED_AFTER_DIGEST`` narrows that again to a week some digest has\nalready claimed. Claiming is what makes an entry unmailable a second time,\nso bullets appended afterwards reach no send unless somebody puts them\nthere — reported, because the alternative is losing them quietly."},"RollUpPendingRequest":{"properties":{"kind":{"$ref":"#/components/schemas/DigestPeriodKind"},"start":{"type":"string","format":"date","title":"Start"},"include_already_sent":{"type":"boolean","title":"Include Already Sent","default":false}},"type":"object","required":["kind","start"],"title":"RollUpPendingRequest"},"RollUpWeekRequest":{"properties":{"week_start":{"type":"string","format":"date","title":"Week Start"}},"type":"object","required":["week_start"],"title":"RollUpWeekRequest"},"RollUpWeekResponse":{"properties":{"outcome":{"$ref":"#/components/schemas/RollUpOutcome"},"releases_added":{"type":"integer","title":"Releases Added"},"entry":{"$ref":"#/components/schemas/ReleaseNoteEntryResponse"}},"type":"object","required":["outcome","releases_added","entry"],"title":"RollUpWeekResponse","description":"What the roll-up did, so the client can toast the truth.\n\n``no_changes`` is how a re-run with nothing new reports itself instead of\nminting an empty duplicate draft."},"RootResponse":{"properties":{"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"mock_mode":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Mock Mode"},"hint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hint"},"auth_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Status"}},"type":"object","title":"RootResponse"},"RowExclusionOutcome":{"properties":{"feature_id":{"type":"string","title":"Feature Id"},"status":{"type":"string","enum":["excluded","already_excluded","restored","not_excluded"],"title":"Status"}},"type":"object","required":["feature_id","status"],"title":"RowExclusionOutcome","description":"Per-id result of a bulk exclude/restore, in request order."},"RowExclusionRecord":{"properties":{"feature_id":{"type":"string","title":"Feature Id"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"source_layer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Source Layer Id"},"excluded_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Excluded By"},"excluded_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Excluded By Name"},"source":{"type":"string","enum":["ui","agent"],"title":"Source","default":"ui"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["feature_id","created_at"],"title":"RowExclusionRecord","description":"One Excluded-bin entry: the excluded row plus its audit provenance."},"RowGroupCol":{"properties":{"id":{"type":"string","title":"Id"},"field":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Field"},"displayName":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Displayname"}},"type":"object","required":["id"],"title":"RowGroupCol","description":"AG Grid row-group column descriptor.\n\n``id`` is required. ``field`` mirrors AG Grid's ``ColumnVO.field``, which\nis optional on the wire — valueGetter-backed columns identify themselves by\n``id`` alone. The builder reads whichever is present (``id or field``)."},"SSRTableQueryParams":{"properties":{"startRow":{"type":"integer","minimum":0.0,"title":"Startrow","default":0},"endRow":{"type":"integer","exclusiveMinimum":0.0,"title":"Endrow","default":100},"sortModel":{"anyOf":[{"items":{"$ref":"#/components/schemas/SortEntry"},"type":"array"},{"type":"null"}],"title":"Sortmodel"},"filterModel":{"anyOf":[{"additionalProperties":{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Input"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},"type":"object"},{"type":"null"}],"title":"Filtermodel"},"filterId":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Filterid"},"groupKeys":{"anyOf":[{"items":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"number"},{"type":"boolean"},{"type":"null"}]},"type":"array"},{"type":"null"}],"title":"Groupkeys"},"rowGroupCols":{"anyOf":[{"items":{"$ref":"#/components/schemas/RowGroupCol"},"type":"array"},{"type":"null"}],"title":"Rowgroupcols"},"searchText":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Searchtext"},"geometry":{"anyOf":[{"$ref":"#/components/schemas/GeoJSONPolygon"},{"type":"null"}]},"favoritesOnly":{"type":"boolean","title":"Favoritesonly","default":false}},"type":"object","title":"SSRTableQueryParams","description":"Combined query-param shape for the 5 AG-Grid SSR endpoints.\n\nAliases match AG Grid's camelCase wire format (``startRow``, ``filterModel``, …)\nso the client contract is unchanged. Handlers parse JSON-encoded query\nstrings into this model via the ``parse_ssr_query_params`` dep; any\nvalidation failure surfaces as 422 with a field path."},"SandboxProjectRequest":{"properties":{"county_fips":{"type":"string","maxLength":5,"minLength":5,"title":"County Fips","description":"5-digit US county FIPS code (e.g. '12103' for Pinellas, FL)"},"knowledge_skill_workspace_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Knowledge Skill Workspace Id"}},"type":"object","required":["county_fips"],"title":"SandboxProjectRequest","description":"Single-click county sandbox entry. Caller passes the FIPS code of a\ncounty already loaded into their workspace; server creates the project +\nboundary layer atomically."},"SandboxProjectResponse":{"properties":{"project_id":{"type":"string","format":"uuid","title":"Project Id"}},"type":"object","required":["project_id"],"title":"SandboxProjectResponse","description":"Response carrying the new project's id so the client can navigate\nstraight into it.\n\nThe boundary layer is built asynchronously on a Celery worker — its\n``layer_id`` is not known at response time. The project page polls the\nproject until ``status`` flips from ``pending`` to ``ready`` or\n``failed`` and then refetches the layer list to discover the boundary."},"SandboxWarmCountyRequest":{"properties":{"county_fips":{"type":"string","maxLength":5,"minLength":5,"title":"County Fips","description":"5-digit US county FIPS code (e.g. '12103' for Pinellas, FL)"}},"type":"object","required":["county_fips"],"title":"SandboxWarmCountyRequest","description":"Pre-warm a county boundary MV without creating a project.\n\nCalled when the user soft-selects a county in the picker so the\nboundary MV builds in parallel with prompt composition. The\nsubsequent project-create call short-circuits the slow Neon work\nbecause the MV is already materialized."},"SandboxWarmCountyResponse":{"properties":{"county_fips":{"type":"string","title":"County Fips"},"ready":{"type":"boolean","title":"Ready","default":true}},"type":"object","required":["county_fips"],"title":"SandboxWarmCountyResponse","description":"Confirms the workspace-shared county boundary MV is queryable.\n\nReturned synchronously — the response shipping means the MV exists\nin Neon. The picker is free to navigate the user into a sandbox\nproject for the same county without waiting on the create-project\nbackground task to rebuild it."},"SaveContactRequest":{"properties":{"full_name":{"type":"string","maxLength":500,"title":"Full Name"},"first_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Last Name"},"job_title":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Job Title"},"job_company_name":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Job Company Name"},"work_email":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Work Email"},"personal_email":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Personal Email"},"phone":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Phone"},"mobile_phone":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Mobile Phone"},"linkedin_url":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Linkedin Url"},"location_name":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Location Name"},"source_attribution":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Source Attribution"},"feature_id":{"type":"string","maxLength":64,"minLength":1,"title":"Feature Id"},"layer_id":{"type":"string","format":"uuid","title":"Layer Id"}},"type":"object","required":["full_name","feature_id","layer_id"],"title":"SaveContactRequest"},"SavedContactDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"full_name":{"type":"string","title":"Full Name"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"job_company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Name"},"work_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Email"},"personal_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Personal Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"mobile_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mobile Phone"},"linkedin_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Url"},"location_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Name"},"source_attribution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Attribution"},"status":{"type":"string","title":"Status"},"is_favorite":{"type":"boolean","title":"Is Favorite","default":false},"created_by":{"type":"string","format":"uuid","title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"note_count":{"type":"integer","title":"Note Count","default":0},"feature_link_count":{"type":"integer","title":"Feature Link Count","default":0},"notes":{"items":{"$ref":"#/components/schemas/SavedContactNoteResponse"},"type":"array","title":"Notes","default":[]},"feature_links":{"items":{"$ref":"#/components/schemas/SavedContactFeatureLinkResponse"},"type":"array","title":"Feature Links","default":[]}},"type":"object","required":["id","project_id","full_name","status","created_by","created_at","updated_at"],"title":"SavedContactDetailResponse"},"SavedContactFeatureLinkResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"saved_contact_id":{"type":"string","format":"uuid","title":"Saved Contact Id"},"feature_id":{"type":"string","title":"Feature Id"},"layer_id":{"type":"string","format":"uuid","title":"Layer Id"},"layer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Layer Name"}},"type":"object","required":["id","saved_contact_id","feature_id","layer_id"],"title":"SavedContactFeatureLinkResponse"},"SavedContactIdentity":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"full_name":{"type":"string","title":"Full Name"},"work_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Email"}},"type":"object","required":["id","full_name"],"title":"SavedContactIdentity"},"SavedContactListResponse":{"properties":{"contacts":{"items":{"$ref":"#/components/schemas/SavedContactResponse"},"type":"array","title":"Contacts"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["contacts","total"],"title":"SavedContactListResponse"},"SavedContactNoteResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"saved_contact_id":{"type":"string","format":"uuid","title":"Saved Contact Id"},"content":{"type":"string","title":"Content"},"created_by":{"type":"string","format":"uuid","title":"Created By"},"created_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","saved_contact_id","content","created_by","created_at"],"title":"SavedContactNoteResponse"},"SavedContactResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"full_name":{"type":"string","title":"Full Name"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"job_company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Name"},"work_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Email"},"personal_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Personal Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"mobile_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mobile Phone"},"linkedin_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Url"},"location_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Name"},"source_attribution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Attribution"},"status":{"type":"string","title":"Status"},"is_favorite":{"type":"boolean","title":"Is Favorite","default":false},"created_by":{"type":"string","format":"uuid","title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"note_count":{"type":"integer","title":"Note Count","default":0},"feature_link_count":{"type":"integer","title":"Feature Link Count","default":0}},"type":"object","required":["id","project_id","full_name","status","created_by","created_at","updated_at"],"title":"SavedContactResponse"},"ScheduleEntryRequest":{"properties":{"publish_at":{"type":"string","format":"date-time","title":"Publish At"}},"type":"object","required":["publish_at"],"title":"ScheduleEntryRequest"},"SchemaExposure":{"properties":{"enrichment_agent_response":{"anyOf":[{"$ref":"#/components/schemas/ToolResourceResponse"},{"type":"null"}],"description":"Schema type for enrichment agent responses"},"not_enough_context":{"anyOf":[{"$ref":"#/components/schemas/NotEnoughContext"},{"type":"null"}],"description":"Schema type for not enough context responses"},"create_layer_parameters_response":{"anyOf":[{"$ref":"#/components/schemas/CreateLayerSuccess"},{"type":"null"}],"description":"Schema type for create layer parameters responses"},"enrichment_value_base_model":{"anyOf":[{"$ref":"#/components/schemas/EnrichmentValueBaseModel"},{"type":"null"}],"description":"Schema type for base enrichment value model"},"enrichment_status_changed_event":{"anyOf":[{"$ref":"#/components/schemas/EnrichmentStatusChangedEvent"},{"type":"null"}],"description":"SSE event pushed to the user's channel when an enrichment workflow reaches a terminal state (replaces FE status polling)"},"view_state_changed_event":{"anyOf":[{"$ref":"#/components/schemas/ViewStateChangedEvent"},{"type":"null"}],"description":"SSE event pushed to the user's channel when a project view mutation commits; carries the affected view(s) + deletedViewIds so the FE applies the authoritative state without a refetch"},"layer_state_changed_event":{"anyOf":[{"$ref":"#/components/schemas/LayerStateChangedEvent"},{"type":"null"}],"description":"SSE event pushed to the user's channel when a layer metadata mutation commits; carries the affected layer(s) + deletedLayerIds so the FE applies the authoritative state without a refetch"},"chat_summarization_completed_event":{"anyOf":[{"$ref":"#/components/schemas/ChatSummarizationCompletedEvent"},{"type":"null"}],"description":"SSE event pushed to the user's channel when a chat's background summarize_workflow finishes persisting; the FE renders the 'summarized' divider on receipt instead of at enqueue time"},"project_renamed_event":{"anyOf":[{"$ref":"#/components/schemas/ProjectRenamedEvent"},{"type":"null"}],"description":"SSE event pushed to the user's channel when a project's name changes server-side (auto-title generation); carries projectId + name + titleSource so the FE patches the projects-list cache without a refetch"},"map_fly_to_event":{"anyOf":[{"$ref":"#/components/schemas/MapFlyToEvent"},{"type":"null"}],"description":"SSE event pushed to the user's channel when the agent moves the map camera to a resolved feature; carries projectId + bbox so the FE fitBounds to it"},"stream_chat_delta":{"anyOf":[{"$ref":"#/components/schemas/StreamChatDelta"},{"type":"null"}],"description":"Schema type for streaming chat deltas"},"stream_thinking_delta":{"anyOf":[{"$ref":"#/components/schemas/StreamThinkingDelta"},{"type":"null"}],"description":"Schema type for streaming thinking/reasoning deltas"},"stream_tool_call_start":{"anyOf":[{"$ref":"#/components/schemas/StreamToolCallStart"},{"type":"null"}],"description":"Schema type for streaming tool call start events"},"stream_tool_call_complete":{"anyOf":[{"$ref":"#/components/schemas/StreamToolCallComplete"},{"type":"null"}],"description":"Schema type for streaming tool call completion events"},"stream_chat_complete":{"anyOf":[{"$ref":"#/components/schemas/StreamChatComplete"},{"type":"null"}],"description":"Schema type for streaming chat completion with optional summarization info"},"stream_chat_error":{"anyOf":[{"$ref":"#/components/schemas/StreamChatError"},{"type":"null"}],"description":"Schema type for streaming chat errors"},"stream_chat_interrupted":{"anyOf":[{"$ref":"#/components/schemas/StreamChatInterrupted"},{"type":"null"}],"description":"Schema type for streaming chat interruption events"},"stream_web_search_status":{"anyOf":[{"$ref":"#/components/schemas/StreamWebSearchStatus"},{"type":"null"}],"description":"Schema type for web search status updates from built-in tools"},"stream_chat_user_message":{"anyOf":[{"$ref":"#/components/schemas/StreamChatUserMessage"},{"type":"null"}],"description":"First durable stream event echoing the user's prompt. A client re-attaching to an in-flight run renders the question from this event since pre-completion history doesn't carry the turn."},"stream_chat_event":{"anyOf":[{"$ref":"#/components/schemas/StreamChatDelta"},{"$ref":"#/components/schemas/StreamThinkingDelta"},{"$ref":"#/components/schemas/StreamToolCallStart"},{"$ref":"#/components/schemas/StreamToolCallComplete"},{"$ref":"#/components/schemas/StreamChatComplete"},{"$ref":"#/components/schemas/StreamChatApprovalRequired"},{"$ref":"#/components/schemas/StreamLLMProviderError"},{"$ref":"#/components/schemas/StreamChatError"},{"$ref":"#/components/schemas/StreamChatInterrupted"},{"$ref":"#/components/schemas/StreamChatRetry"},{"$ref":"#/components/schemas/StreamWebSearchStatus"},{"$ref":"#/components/schemas/StreamSummarizationStatus"},{"$ref":"#/components/schemas/StreamProjectCreated"},{"$ref":"#/components/schemas/StreamChatUserMessage"},{"$ref":"#/components/schemas/StreamChatTurnStarted"},{"$ref":"#/components/schemas/StreamChatCaughtUp"},{"$ref":"#/components/schemas/StreamMapActivity"},{"type":"null"}],"title":"Stream Chat Event","description":"Schema type for streaming chat events union"},"stream_map_activity":{"anyOf":[{"$ref":"#/components/schemas/StreamMapActivity"},{"type":"null"}],"description":"Tool-emitted truth about what the agent is touching on the map; drives the map activity overlay's phase paint"},"contact_model":{"anyOf":[{"$ref":"#/components/schemas/ContactModel"},{"type":"null"}],"description":"Schema type for contact model"},"tenant_lease_concise":{"anyOf":[{"$ref":"#/components/schemas/TenantLeaseConcise"},{"type":"null"}],"description":"Schema type for tenant lease model"},"owner_residential_mailing_address":{"anyOf":[{"$ref":"#/components/schemas/OwnerResidentialMailingAddressModel"},{"type":"null"}],"description":"Schema type for the owner residential mailing address model"},"mortgage_profile":{"anyOf":[{"$ref":"#/components/schemas/MortgageProfileModel"},{"type":"null"}],"description":"Schema type for the mortgage & liens profile model"},"invalid_query_result":{"anyOf":[{"$ref":"#/components/schemas/UnprocessableQueryResult"},{"type":"null"}],"description":"Schema type for invalid query results"},"invalid_query_reason":{"anyOf":[{"$ref":"#/components/schemas/UnprocessableQueryReason"},{"type":"null"}],"description":"Schema type for invalid query reasons enum"},"query_parse_response":{"anyOf":[{"$ref":"#/components/schemas/QueryParseResponse"},{"type":"null"}],"description":"Schema type for real-time query parse response"},"create_layer_failure":{"anyOf":[{"$ref":"#/components/schemas/CreateLayerFailure"},{"type":"null"}],"description":"Schema type for create layer failure responses"},"select_question_payload":{"anyOf":[{"$ref":"#/components/schemas/SelectQuestionPayload"},{"type":"null"}],"description":"Schema type for an agent-emitted select question payload attached to ModelResponse.metadata.interactive_question."},"confirm_question_payload":{"anyOf":[{"$ref":"#/components/schemas/ConfirmQuestionPayload"},{"type":"null"}],"description":"Schema type for an agent-emitted confirm (yes/no) question payload attached to ModelResponse.metadata.interactive_question."},"interactive_question_answer":{"anyOf":[{"$ref":"#/components/schemas/InteractiveQuestionAnswer"},{"type":"null"}],"description":"Schema type for the resolved answer to an interactive question, attached to ModelResponse.metadata.interactive_question_answer."},"skill_plan_payload":{"anyOf":[{"$ref":"#/components/schemas/SkillPlanPayload"},{"type":"null"}],"description":"Schema type for the skill_plan tool's phase-checklist payload, carried as the tool call's args in stream events and history."},"report_actions_payload":{"anyOf":[{"$ref":"#/components/schemas/ReportActionsPayload"},{"type":"null"}],"description":"Schema type for the report_actions tool's work-announcement payload, echoed as the tool result and folded into a summary line."},"stream_chat_approval_required":{"anyOf":[{"$ref":"#/components/schemas/StreamChatApprovalRequired"},{"type":"null"}],"description":"Terminal stream event for a run that ended awaiting tool approval (pending save_skill / update_skill)."},"tool_approval_request":{"anyOf":[{"$ref":"#/components/schemas/ToolApprovalRequest"},{"type":"null"}],"description":"Schema type for a pending approval-gated tool call, attached to ModelResponse.metadata.tool_approval_request."},"tool_approval_answer":{"anyOf":[{"$ref":"#/components/schemas/ToolApprovalAnswer"},{"type":"null"}],"description":"Schema type for the user's approve/decline of a pending tool call, attached to ModelResponse.metadata.tool_approval_answer."},"attribution_payload":{"anyOf":[{"$ref":"#/components/schemas/AttributionPayload"},{"type":"null"}],"description":"Schema type for the per-reply attribution receipt (ran skill / referenced knowledge), attached to ModelResponse.metadata.attribution."},"invoked_skill_payload":{"anyOf":[{"$ref":"#/components/schemas/InvokedSkillPayload"},{"type":"null"}],"description":"Schema type for the invoked-skill receipt on a user turn, attached to the user ModelRequest.metadata.invoked_skill."},"chat_attachment_payload":{"anyOf":[{"$ref":"#/components/schemas/ChatAttachmentPayload"},{"type":"null"}],"description":"Schema type for the attachment receipt on a user turn, attached to the user ModelRequest.metadata.attachment."}},"type":"object","title":"SchemaExposure","description":"Schema exposure model for all chat-related types.\nThis endpoint exists solely to expose schemas to OpenAPI/TypeScript generation.\nThese fields are never actually populated in responses."},"SelectOption":{"properties":{"id":{"type":"string","title":"Id"},"label":{"type":"string","title":"Label"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"sourceTable":{"anyOf":[{"$ref":"#/components/schemas/SourceTable"},{"type":"null"}],"description":"REQUIRED on each option built from a resolve_to_feature candidate: the candidate's source_table. Carries the feature binding so the picked option is actionable. Leave unset for non-feature options (e.g. a 'none of these' escape)."},"sourceUrl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sourceurl","description":"REQUIRED on each option built from an external-catalog candidate: the candidate's service URL. Put it here rather than in the description — the UI renders it as a named link, and a URL written into the prose is unreadable and unclickable."},"featureId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Featureid","description":"REQUIRED with sourceTable: the resolved candidate's id."}},"type":"object","required":["id","label"],"title":"SelectOption"},"SelectQuestionPayload":{"properties":{"type":{"type":"string","const":"select","title":"Type","default":"select"},"id":{"type":"string","title":"Id"},"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt"},"options":{"items":{"$ref":"#/components/schemas/SelectOption"},"type":"array","maxItems":6,"minItems":2,"title":"Options"}},"type":"object","required":["id","options"],"title":"SelectQuestionPayload"},"SelectionDriftErrorResponse":{"properties":{"detail":{"$ref":"#/components/schemas/SelectionDriftResponse"}},"type":"object","required":["detail"],"title":"SelectionDriftErrorResponse"},"SelectionDriftResponse":{"properties":{"kind":{"type":"string","enum":["fingerprint_mismatch","count_drift"],"title":"Kind"},"recomputed_count":{"type":"integer","title":"Recomputed Count"},"recomputed_fingerprint":{"type":"string","title":"Recomputed Fingerprint"}},"type":"object","required":["kind","recomputed_count","recomputed_fingerprint"],"title":"SelectionDriftResponse","description":"Body of 400 (fingerprint mismatch) and 409 (count drift) responses.\n\nClients use ``kind`` to choose UX: 400 means a client-side bug or\ntampering (refetch ``/filtered-count``, retry); 409 means data\nchanged between count and action (offer \"now N rows, continue?\" with\nthe recomputed pair)."},"SelfServeAccountState":{"type":"string","enum":["pending","waitlisted","preparing","ready","failed"],"title":"SelfServeAccountState","description":"Where a self-serve account sits between signup and a usable workspace.\n\n``PREPARING`` and ``READY`` hold a seat against the admission cap; the other\nthree do not. Setup consumes capacity from the moment it starts rather than\nwhen it finishes, so a burst of in-flight setups cannot collectively pass the\ncap. See ``SEAT_HOLDING_STATES``."},"SemanticType":{"type":"string","enum":["identifier","name","address_part","address_full","currency","area","height","count","category","zoning","date","phone","website","percent","generic"],"title":"SemanticType","description":"What a column *means* — drives FE rendering and formatting.\n\nIndependent from ``ColumnDataType`` (the storage type hint): a column can\nbe ``data_type=number, semantic_type=currency`` (parcel ``landval``) or\n``data_type=number, semantic_type=area`` (``area_acres``). The FE renderer\nkeys off ``semantic_type``, not ``data_type``.\n\nLives here (with the wire model) rather than on ``LayerKind`` because under\nthe self-describing contract this rides on ``LayerColumn`` across the wire\n— ``LayerKind`` is the backend-only producer that hydrates it."},"SetCondition":{"properties":{"filterType":{"type":"string","const":"set","title":"Filtertype","default":"set"},"values":{"items":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"array","maxItems":10000,"title":"Values"},"type":{"anyOf":[{"type":"string","const":"unavailable"},{"type":"null"}],"title":"Type"}},"type":"object","title":"SetCondition"},"SetDefaultViewRequest":{"properties":{"view_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"View Id"}},"type":"object","title":"SetDefaultViewRequest","description":"Request model for setting a project's durable default view.\n\nAttributes:\n    view_id: The view id to designate as the project default, or null to\n        clear it. A non-null id must be one of the project's current views."},"SetExclusionRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"excluded":{"type":"boolean","title":"Excluded"}},"type":"object","required":["email","excluded"],"title":"SetExclusionRequest"},"SetExclusionsBulkRequest":{"properties":{"emails":{"items":{"type":"string","format":"email"},"type":"array","maxItems":1000,"minItems":1,"title":"Emails"},"excluded":{"type":"boolean","title":"Excluded"}},"type":"object","required":["emails","excluded"],"title":"SetExclusionsBulkRequest"},"SetExclusionsBulkResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/ExclusionOutcome"},"type":"array","title":"Results"}},"type":"object","required":["results"],"title":"SetExclusionsBulkResponse"},"SetGlobalFlagDefaultRequest":{"properties":{"enabled":{"type":"boolean","title":"Enabled"}},"additionalProperties":false,"type":"object","required":["enabled"],"title":"SetGlobalFlagDefaultRequest","description":"Request to set the platform-wide default for one feature toggle."},"SetupEntryResponse":{"properties":{"account_id":{"type":"string","format":"uuid","title":"Account Id"},"email":{"type":"string","title":"Email"},"state":{"type":"string","title":"State"},"since":{"type":"string","format":"date-time","title":"Since"},"failure_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Reason"},"notified":{"type":"boolean","title":"Notified"},"delivery_failed":{"type":"boolean","title":"Delivery Failed"}},"type":"object","required":["account_id","email","state","since","notified","delivery_failed"],"title":"SetupEntryResponse"},"SetupFilter":{"type":"string","enum":["all","preparing","failed","never_told"],"title":"SetupFilter","description":"Which slice of the after-admission list to show.\n\n``NEVER_TOLD`` is not an account state — it is ``ready`` with no notice\nstamp — so this is a view over the list rather than a state filter, and is\nnamed for what the operator is looking for rather than for the column."},"SetupListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SetupEntryResponse"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"SetupListResponse"},"SetupStatusResponse":{"properties":{"status":{"type":"string","enum":["verification_pending","preparing","ready","failed","waitlisted","paused"],"title":"Status"},"profile_collected":{"type":"boolean","title":"Profile Collected","default":false}},"type":"object","required":["status"],"title":"SetupStatusResponse","description":"Where a self-serve setup stands, as the status page renders it.\n\nExactly what the UI needs and nothing internal — no workflow ids, no\nfailure reasons. ``paused`` is derived live from the operator pause flag\nat read time, never stored, so unpausing immediately changes what a\nreturning waitlisted person sees.\n\n``profile_collected`` says whether the questionnaire was ever submitted,\nso the form stays dismissed across reloads without the client storing\nanything. False on the account-less answers (``verification_pending``),\nwhere no row exists to have collected it."},"SetupTokenRedeemRequest":{"properties":{"token":{"type":"string","maxLength":256,"minLength":1,"title":"Token"},"password":{"type":"string","maxLength":256,"minLength":8,"title":"Password"}},"type":"object","required":["token","password"],"title":"SetupTokenRedeemRequest","description":"Request model for redeeming an account-setup token."},"SetupTokenRequest":{"properties":{"token":{"type":"string","maxLength":256,"minLength":1,"title":"Token"}},"type":"object","required":["token"],"title":"SetupTokenRequest","description":"Request model for inspecting an account-setup token.\n\nThe token rides in the body, never the path or query: every request's URL\nis recorded by the logging middleware, Logfire's FastAPI instrumentation,\nand Cloud Run's access log, so a token in the URL would be persisted in\nplaintext telemetry — the exact exposure hashing it in the database\nprevents."},"SetupTokenStatusResponse":{"properties":{"status":{"type":"string","enum":["valid","expired","used","unknown"],"title":"Status"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"}},"type":"object","required":["status"],"title":"SetupTokenStatusResponse","description":"Non-consuming check of an account-setup token.\n\n``email`` is present only when ``status`` is ``valid`` — an invalid token\nmust not reveal which account it belonged to."},"ShareAcceptanceRejectedResponse":{"properties":{"detail":{"type":"string","title":"Detail"},"code":{"type":"string","const":"terms_changed","title":"Code"}},"type":"object","required":["detail","code"],"title":"ShareAcceptanceRejectedResponse","description":"409 body when the submitted terms version is no longer served.\n\n``code`` is the discriminator the client branches on; ``detail`` is the\nsentence an older bundle displays verbatim, so it stays a string."},"ShareAcceptanceRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"terms_version":{"type":"string","maxLength":100,"minLength":1,"title":"Terms Version"},"accepted":{"type":"boolean","const":true,"title":"Accepted"},"idempotency_key":{"type":"string","format":"uuid","title":"Idempotency Key"}},"type":"object","required":["email","terms_version","accepted","idempotency_key"],"title":"ShareAcceptanceRequest","description":"Unknown keys are ignored on purpose: a browser still running the\npre-2026-08-25 bundle posts the retired identity fields alongside a stale\n``terms_version``, and it must reach the 409 that tells it to re-accept\nrather than a 422 about fields it cannot stop sending."},"ShareAcceptanceResponse":{"properties":{"accepted":{"type":"boolean","const":true,"title":"Accepted","default":true}},"type":"object","title":"ShareAcceptanceResponse"},"ShareInfoResponse":{"properties":{"is_shared":{"type":"boolean","title":"Is Shared"},"share":{"anyOf":[{"$ref":"#/components/schemas/ShareLinkResponse"},{"type":"null"}]},"workspace_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace Name"},"workspace_member_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Workspace Member Count"},"workspace_visibility":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace Visibility"},"restricted_layer_names":{"items":{"type":"string"},"type":"array","title":"Restricted Layer Names"},"pending_access_mode":{"$ref":"#/components/schemas/ProjectShareAccessMode","default":"gated"}},"type":"object","required":["is_shared"],"title":"ShareInfoResponse","description":"Response for GET share info.\n\nThree possible states:\n- Never shared: is_shared=False, share=None\n- Previously shared (revoked): is_shared=False, share={is_active: False, ...}\n- Currently shared: is_shared=True, share={is_active: True, ...}\n\nOptional workspace context (for share dialog):\n- workspace_name, workspace_member_count, workspace_visibility\n\n`pending_access_mode` is the mode a link created right now would carry. The\ncreator-facing gate controls (duration, domain policy, viewer register) only\nexist for a gated link, so the dialog reads this rather than deriving the\nproject's parcel content itself."},"ShareLinkCreateRequest":{"properties":{"duration_days":{"type":"integer","maximum":30.0,"minimum":1.0,"title":"Duration Days","default":14},"consumer_domain_override":{"type":"boolean","title":"Consumer Domain Override","default":false}},"type":"object","title":"ShareLinkCreateRequest"},"ShareLinkResponse":{"properties":{"share_url":{"type":"string","title":"Share Url"},"share_token":{"type":"string","title":"Share Token"},"is_active":{"type":"boolean","title":"Is Active"},"view_count":{"type":"integer","title":"View Count"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"access_mode":{"$ref":"#/components/schemas/ProjectShareAccessMode"},"duration_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Days"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"consumer_domain_override":{"type":"boolean","title":"Consumer Domain Override","default":false}},"type":"object","required":["share_url","share_token","is_active","view_count","access_mode"],"title":"ShareLinkResponse","description":"Response containing share link details for a project owner."},"ShareRevokeResponse":{"properties":{"success":{"type":"boolean","title":"Success"}},"type":"object","required":["success"],"title":"ShareRevokeResponse","description":"Response for DELETE (revoke) share link."},"ShareViewResponse":{"properties":{"success":{"type":"boolean","title":"Success"}},"type":"object","required":["success"],"title":"ShareViewResponse","description":"Response for POST view tracking on a share link."},"ShareViewerPageResponse":{"properties":{"viewers":{"items":{"$ref":"#/components/schemas/ShareViewerResponse"},"type":"array","title":"Viewers"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["viewers"],"title":"ShareViewerPageResponse"},"ShareViewerResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"full_name":{"type":"string","title":"Full Name"},"business_name":{"type":"string","title":"Business Name"},"email":{"type":"string","format":"email","title":"Email"},"cell_phone":{"type":"string","title":"Cell Phone"},"accepted_at":{"type":"string","format":"date-time","title":"Accepted At"},"verification_status":{"type":"string","enum":["self_attested","verified"],"title":"Verification Status"},"consumer_domain_override":{"type":"boolean","title":"Consumer Domain Override"},"via_current_link":{"type":"boolean","title":"Via Current Link"}},"type":"object","required":["id","full_name","business_name","email","cell_phone","accepted_at","verification_status","consumer_domain_override","via_current_link"],"title":"ShareViewerResponse","description":"``full_name``, ``business_name`` and ``cell_phone`` are transitional.\n\nThe web bundle deployed before terms version 2026-08-25 interpolates them\ninto the viewer register; while that bundle can still be open, the API keeps\nserving them (empty for email-only acceptances) so an open tab renders\nblanks rather than ``undefined``. Remove them once the current bundle is the\nonly one in service — MAIA-4122 carries the removal criteria, and the test\nthat pins their presence is deleted with them."},"SharedEnrichmentListResponse":{"properties":{"enrichments":{"items":{"$ref":"#/components/schemas/SharedEnrichmentModel"},"type":"array","title":"Enrichments"}},"type":"object","required":["enrichments"],"title":"SharedEnrichmentListResponse"},"SharedEnrichmentModel":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"layer_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Layer Id"},"is_data_source":{"type":"boolean","title":"Is Data Source","default":false},"is_configured":{"type":"boolean","title":"Is Configured","default":true},"is_configuration_failed":{"type":"boolean","title":"Is Configuration Failed","default":false},"dtype":{"type":"string","title":"Dtype","default":""},"params":{"additionalProperties":true,"type":"object","title":"Params"}},"type":"object","required":["id","name"],"title":"SharedEnrichmentModel","description":"Slim enrichment model for public share access.\n\nExposes only the fields needed for column mapping in the table UI.\n`params` is filtered down to display-only keys (see\nSHARED_ENRICHMENT_PARAM_KEYS) so categorical chips and color scales render\ncorrectly; proprietary prompt text, tool identifiers, and task IDs remain\nexcluded. `tool` and `description` are likewise omitted."},"SharedLayerModel":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"project_id":{"type":"string","format":"uuid","title":"Project Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"style_config":{"additionalProperties":{"type":"string"},"type":"object","title":"Style Config"},"base_attributes":{"additionalProperties":{"type":"string"},"type":"object","title":"Base Attributes"},"columns":{"items":{"$ref":"#/components/schemas/LayerColumn"},"type":"array","title":"Columns"},"title_template":{"items":{"type":"string"},"type":"array","title":"Title Template"},"address_template":{"items":{"type":"string"},"type":"array","title":"Address Template"},"data_version":{"type":"integer","title":"Data Version","default":0},"metadata_version":{"type":"integer","title":"Metadata Version","default":0},"tile_source_layer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tile Source Layer"},"render_mode":{"type":"string","enum":["detail_always","agg_at_low_zoom"],"title":"Render Mode","default":"agg_at_low_zoom"},"display_kind":{"type":"string","enum":["data","boundary"],"title":"Display Kind","default":"data"},"data_restricted":{"type":"boolean","title":"Data Restricted","default":false},"has_drawable_geometry":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Drawable Geometry"}},"additionalProperties":false,"type":"object","required":["id","project_id","name"],"title":"SharedLayerModel","description":"Positive layer-metadata contract for public share responses."},"SharedProjectResponse":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"default_view_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default View Id"},"thumbnail_bounds":{"anyOf":[{"$ref":"#/components/schemas/ThumbnailBounds"},{"type":"null"}]},"is_sandbox":{"type":"boolean","title":"Is Sandbox","default":false},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","name"],"title":"SharedProjectResponse","description":"API response model for a shared project (public, no auth).\n\nExposes only the fields needed for read-only viewing. Intentionally omits\ninternal fields like user_id, project_plan, visibility, is_plan_ready,\nand additional_project_info."},"SignupAvailabilityResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled"}},"type":"object","required":["enabled"],"title":"SignupAvailabilityResponse","description":"Whether public self-serve signup is currently open.\n\nA pre-flight read for the signup page, so the form never mints a Firebase\nidentity for a surface that will refuse it. Advisory only — the POST\nroutes stay the authoritative gate."},"SignupProfileRequest":{"properties":{"use_case":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Use Case"},"property_types":{"items":{"type":"string","maxLength":200},"type":"array","maxItems":20,"title":"Property Types"},"role":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Role"}},"type":"object","title":"SignupProfileRequest","description":"The optional getting-to-know-you answers from the status page.\n\nValues are the chosen option's label, or the free text typed under\n\"Other\" — deliberately not a server-side enum. The option lists live in\nthe client beside the form, and a copied list here would refuse exactly\nthe answers \"Other\" exists to accept. Lengths and the list size are\nbounded so the surface cannot store arbitrary payloads."},"SignupResponse":{"properties":{"status":{"type":"string","enum":["admitted","waitlisted","preparing","verification_required","already_registered"],"title":"Status"},"account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Account Id"}},"type":"object","required":["status"],"title":"SignupResponse","description":"Where a signup ended up.\n\n``account_id`` is absent for the two outcomes that create no account —\nan address that already has one, and one still waiting on its verification\nlink."},"SkillCreateRequest":{"properties":{"scope":{"$ref":"#/components/schemas/SkillScope"},"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"description":{"type":"string","maxLength":400,"minLength":1,"title":"Description"},"body":{"type":"string","maxLength":32000,"minLength":1,"title":"Body"},"is_starter":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Starter","description":"Whether the skill is a new-project starter. Omit for the default: a workflow-type workspace skill defaults to a starter, other types and user skills do not. Only workspace skills may be starters."},"skill_type":{"anyOf":[{"$ref":"#/components/schemas/SkillType"},{"type":"null"}],"description":"What kind of work the skill encodes. Omit to default to 'workflow'. Only workflow-type workspace skills default into the starter gallery."},"supersedes_skill_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Supersedes Skill Id","description":"Set when customizing an existing MAIA/workspace skill: the id of the starter this copy supersedes. That original is hidden from the gallery and the agent's routing catalog in this copy's favor."}},"type":"object","required":["scope","name","description","body"],"title":"SkillCreateRequest","description":"Request body for creating a user- or workspace-scoped skill."},"SkillPlanPayload":{"properties":{"skill_name":{"type":"string","maxLength":200,"title":"Skill Name","description":"Name of the skill being executed, as shown to the user."},"phases":{"items":{"$ref":"#/components/schemas/SkillPlanPhase"},"type":"array","maxItems":50,"title":"Phases","description":"The complete, ordered phase list for this skill run — resend the FULL list with updated statuses on every call, not a diff."}},"type":"object","required":["skill_name","phases"],"title":"SkillPlanPayload"},"SkillPlanPhase":{"properties":{"label":{"type":"string","maxLength":200,"title":"Label","description":"Short user-facing phase name, e.g. 'Filter parcels by zoning'."},"status":{"$ref":"#/components/schemas/SkillPlanPhaseStatus","description":"pending | in_progress | completed | skipped"}},"type":"object","required":["label","status"],"title":"SkillPlanPhase"},"SkillPlanPhaseStatus":{"type":"string","enum":["pending","in_progress","completed","skipped"],"title":"SkillPlanPhaseStatus"},"SkillResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"scope":{"$ref":"#/components/schemas/SkillScope"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"workspace_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Workspace Id"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"body":{"type":"string","title":"Body"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"is_starter":{"type":"boolean","title":"Is Starter","description":"Whether this skill surfaces as a first-run starter in the new-project gallery. System (Ready-made by MAIA) and workspace-scoped skills may be starters; user-scoped skills are never starters.","default":false},"skill_type":{"$ref":"#/components/schemas/SkillType","description":"What kind of work the skill encodes: a whole 'workflow', an 'enrichment' configuration, or a single 'agent_column'. Only workflow skills default into the new-project starter gallery.","default":"workflow"},"supersedes_skill_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Supersedes Skill Id","description":"If set, the MAIA/workspace starter this skill was customized from; that original is hidden from this caller's starter gallery and the agent's routing catalog in favor of this skill."}},"type":"object","required":["id","scope","name","description","body","created_at","updated_at"],"title":"SkillResponse","description":"A skill as returned to clients (full record, including body)."},"SkillScope":{"type":"string","enum":["user","workspace","system"],"title":"SkillScope","description":"Tier a skill applies to.\n\nUnlike knowledge entries, skills add a ``system`` scope:\nglobally-available skills that are read-only through the public\nservice/API and writable only via the internal admin override,\nplus the in-code create-skill playbook registry. ``user`` skills are owned by\na single user, ``workspace`` skills by a workspace, ``system`` skills by\nneither."},"SkillType":{"type":"string","enum":["workflow","enrichment","agent_column"],"title":"SkillType","description":"What kind of work a skill encodes (MAIA-2976).\n\n``workflow`` skills run end-to-end from a blank project (the IOS skill) and\nare the only kind that defaults into the new-project starter gallery;\n``enrichment`` skills produce a derived configuration/value (usable IOS\nacreage) and ``agent_column`` skills build a single agent-derived column\n(owner assemblages) against an existing project's data."},"SkillUpdateRequest":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"description":{"type":"string","maxLength":400,"minLength":1,"title":"Description"},"body":{"type":"string","maxLength":32000,"minLength":1,"title":"Body"},"is_starter":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Starter","description":"Set the skill's starter status. Omit to leave it unchanged. Only workspace skills may be starters."},"skill_type":{"anyOf":[{"$ref":"#/components/schemas/SkillType"},{"type":"null"}],"description":"Reclassify the skill's type. Omit to leave it unchanged."}},"type":"object","required":["name","description","body"],"title":"SkillUpdateRequest","description":"Request body for replacing a skill's name + description + body."},"SortEntry":{"properties":{"colId":{"type":"string","title":"Colid"},"sort":{"type":"string","enum":["asc","desc"],"title":"Sort"},"sortMode":{"anyOf":[{"type":"string","enum":["default","null_push","count"]},{"type":"null"}],"title":"Sortmode","default":"default"}},"type":"object","required":["colId","sort"],"title":"SortEntry","description":"AG Grid sort descriptor. Accepts camelCase wire format (``colId``,\n``sortMode``) and also the snake_case equivalents used by internal\nPython callers."},"SourceTable":{"type":"string","enum":["parcel","building","place","address","school"],"title":"SourceTable","description":"The table a resolved feature lives in — what a caller pulls its data from,\nand the feature's kind. A text match in the ``address``, ``place`` or ``school``\ntable resolves (point-in-feature) to a ``parcel``/``building``; a ``parcel``\nattribute match resolves to the parcel itself."},"SpatialFilterSpec":{"properties":{"reference_layer_name":{"type":"string","title":"Reference Layer Name","description":"Name of the layer to filter against"},"spatial_operation":{"$ref":"#/components/schemas/SpatialOperation","description":"Spatial operation to apply (INTERSECTS, BUFFER, DISJOINT)"}},"type":"object","required":["reference_layer_name","spatial_operation"],"title":"SpatialFilterSpec","description":"A single spatial filter that references another layer with a spatial operation.\n\nUsed in layer plans to specify how a layer relates spatially to other layers.\nReplaces the old pattern of separate geographic_bounds_layer_id + reference_layer_name."},"SpatialOperation":{"properties":{"operation":{"$ref":"#/components/schemas/SpatialOperationType","description":"Type of PostGIS spatial operation to perform"},"distance_meters":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance Meters","description":"Distance in meters for buffer operations"}},"type":"object","required":["operation"],"title":"SpatialOperation"},"SpatialOperationType":{"type":"string","enum":["intersects","buffer","disjoint"],"title":"SpatialOperationType"},"SpeechPart":{"properties":{"speaker":{"type":"string","enum":["user","assistant"],"title":"Speaker"},"transcript":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transcript"},"audio":{"anyOf":[{"$ref":"#/components/schemas/BinaryContent"},{"type":"null"}]},"interrupted_at_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Interrupted At Ms"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"speech","title":"Part Kind","default":"speech"}},"type":"object","required":["speaker"],"title":"SpeechPart","description":"Spoken audio exchanged during a realtime session, paired with its transcript.\n\nThis part is a member of both [`ModelRequestPart`][pydantic_ai.messages.ModelRequestPart] and\n[`ModelResponsePart`][pydantic_ai.messages.ModelResponsePart], distinguished by `speaker`:\nin `ModelRequest.parts` the speaker is always `'user'`; in `ModelResponse.parts` it is always\n`'assistant'`. This invariant is enforced at runtime when a message is constructed.\n\nStandard (non-realtime) models can't consume this part directly; when history containing it is\nused in an agent run, [`Model.prepare_messages`][pydantic_ai.models.Model.prepare_messages]\nconverts user-speaker parts to [`UserPromptPart`][pydantic_ai.messages.UserPromptPart]s and\nassistant-speaker parts to [`TextPart`][pydantic_ai.messages.TextPart]s."},"StartCampaignRequest":{"properties":{"contact_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Contact Ids"},"name":{"anyOf":[{"type":"string","maxLength":120,"minLength":1},{"type":"null"}],"title":"Name"},"transfer_destination_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Transfer Destination Id"},"transfer_destination_override":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Transfer Destination Override"}},"type":"object","required":["contact_ids"],"title":"StartCampaignRequest"},"StartDialRequest":{"properties":{"transfer_destination_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Transfer Destination Id"},"transfer_destination_override":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Transfer Destination Override"}},"type":"object","title":"StartDialRequest"},"StateOption":{"properties":{"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"}},"type":"object","required":["code","name"],"title":"StateOption","description":"A US state available for geography restriction."},"StreamChatApprovalRequired":{"properties":{"last_edit_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edit Description","description":"Human-readable description of what was changed, derived from tools called."},"last_edited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Edited At","description":"Timestamp of when the project edit was recorded."},"last_edited_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edited By Name","description":"Display name of the user who made the edit."},"type":{"type":"string","const":"approval_required","title":"Type","default":"approval_required"},"display":{"type":"string","const":"completion","title":"Display","default":"completion"},"new_messages":{"items":{"oneOf":[{"$ref":"#/components/schemas/ModelRequest"},{"$ref":"#/components/schemas/ModelResponse"}],"discriminator":{"propertyName":"kind","mapping":{"request":"#/components/schemas/ModelRequest","response":"#/components/schemas/ModelResponse"}}},"type":"array","title":"New Messages","description":"Persisted turn messages, including the pending tool call."},"project_id":{"type":"string","title":"Project Id","description":"Project ID the chat is associated with."},"approval":{"$ref":"#/components/schemas/ToolApprovalRequest","description":"The pending tool call awaiting the user's approve/decline."}},"type":"object","required":["new_messages","project_id","approval"],"title":"StreamChatApprovalRequired","description":"Terminal event for a run that ended awaiting tool approval (MAIA-2220).\n\nThe agent issued a ``requires_approval`` tool call (``save_skill`` /\n``update_skill``) and the run ended as a pending ``DeferredToolRequests``.\nThe turn is persisted (including the pending call + its\n``tool_approval_request`` metadata) before this frame is emitted, so the\nlive client renders the approval card from ``new_messages`` exactly as a\nreload would. ``display: completion`` is the fail-safe: a consumer that\ndoesn't know this discriminant still finalizes the turn's messages\n(per stream-terminal-events-carry-consumer-decision-state)."},"StreamChatCaughtUp":{"properties":{"type":{"type":"string","const":"caught_up","title":"Type","default":"caught_up"},"display":{"type":"string","const":"internal","title":"Display","default":"internal"}},"type":"object","title":"StreamChatCaughtUp","description":"A resumed reader has drained the persisted backlog; frames after this\nare live output.\n\nSynthesized per-connection by the resume path at the replay/live boundary —\nnever written to the durable stream, so it cannot itself be replayed. Before\nthis frame, replayed text may belong to an already-invalidated model attempt\n(a ``retry`` frame later in the backlog voids it), so the client must hold\nit; after this frame, deltas are ordinary live output and paint like the\nsend path. Non-terminal, no payload; clients that don't recognize the type\nignore it and keep holding until a terminal."},"StreamChatComplete":{"properties":{"last_edit_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edit Description","description":"Human-readable description of what was changed, derived from tools called."},"last_edited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Edited At","description":"Timestamp of when the project edit was recorded."},"last_edited_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edited By Name","description":"Display name of the user who made the edit."},"type":{"type":"string","const":"complete","title":"Type","default":"complete"},"display":{"type":"string","const":"completion","title":"Display","default":"completion"},"new_messages":{"items":{"oneOf":[{"$ref":"#/components/schemas/ModelRequest"},{"$ref":"#/components/schemas/ModelResponse"}],"discriminator":{"propertyName":"kind","mapping":{"request":"#/components/schemas/ModelRequest","response":"#/components/schemas/ModelResponse"}}},"type":"array","title":"New Messages","description":"Final complete messages from the agent run."},"summarization_task_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summarization Task Id","description":"Celery task ID if chat summarization was triggered due to token limit."},"total_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Tokens","description":"Total tokens that triggered summarization, if applicable."},"project_id":{"type":"string","title":"Project Id","description":"Project ID the chat is associated with."},"structured_output":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Structured Output","description":"Structured output from the agent, if output_type was specified."},"pending_enrichments":{"anyOf":[{"items":{"$ref":"#/components/schemas/PendingEnrichmentRef"},"type":"array"},{"type":"null"}],"title":"Pending Enrichments","description":"Skeleton enrichments created during initial project setup that are still being configured by the background task. Carried on the complete event so the live client can render pending enrichment cards immediately."}},"type":"object","required":["new_messages","project_id"],"title":"StreamChatComplete","description":"Schema for streaming chat completion event."},"StreamChatDelta":{"properties":{"type":{"type":"string","const":"delta","title":"Type","default":"delta"},"display":{"type":"string","const":"prose","title":"Display","default":"prose"},"content":{"type":"string","title":"Content","description":"Incremental content from the agent."}},"type":"object","required":["content"],"title":"StreamChatDelta","description":"Schema for streaming chat content deltas."},"StreamChatError":{"properties":{"last_edit_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edit Description","description":"Human-readable description of what was changed, derived from tools called."},"last_edited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Edited At","description":"Timestamp of when the project edit was recorded."},"last_edited_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edited By Name","description":"Display name of the user who made the edit."},"type":{"type":"string","const":"error","title":"Type","default":"error"},"display":{"type":"string","const":"internal","title":"Display","default":"internal"},"error":{"type":"string","title":"Error","description":"Error message."},"code":{"$ref":"#/components/schemas/StreamErrorCode","description":"Stable error taxonomy for client retry/branching logic.","default":"internal"},"partial_result":{"type":"boolean","title":"Partial Result","description":"True when the workflow persisted a finalized partial turn before emitting this terminal (cooperative monitor stop). A resumed reader can't render replayed tool events, so it reloads history instead of treating this frame as fully rendered. False for generic errors and reader-synthesized hard-cancel terminals, where nothing new was persisted.","default":false},"continuable":{"type":"boolean","title":"Continuable","description":"True only when the failed turn left a partial the agent can resume from (the same condition that sets chats.last_turn_continuable). Distinct from partial_result: a monitor stop (timeout/lock-lost) persists a partial but is NOT continuable. The FE gates the Continue affordance on this, never on partial_result.","default":false},"new_messages":{"items":{"oneOf":[{"$ref":"#/components/schemas/ModelRequest"},{"$ref":"#/components/schemas/ModelResponse"}],"discriminator":{"propertyName":"kind","mapping":{"request":"#/components/schemas/ModelRequest","response":"#/components/schemas/ModelResponse"}}},"type":"array","title":"New Messages","description":"The persisted partial turn, surfaced and instruction-filtered. Populated with partial_result=True (a cooperative monitor stop or a terminal model failure that had already completed work), so the live client renders the stopped turn without leaving leaked <thinking> prose; empty otherwise."}},"type":"object","required":["error"],"title":"StreamChatError","description":"Schema for general streaming chat error event."},"StreamChatInterrupted":{"properties":{"last_edit_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edit Description","description":"Human-readable description of what was changed, derived from tools called."},"last_edited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Edited At","description":"Timestamp of when the project edit was recorded."},"last_edited_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edited By Name","description":"Display name of the user who made the edit."},"type":{"type":"string","const":"interrupted","title":"Type","default":"interrupted"},"display":{"type":"string","const":"internal","title":"Display","default":"internal"},"reason":{"type":"string","title":"Reason","description":"Human-readable interruption copy for display surfaces."},"project_id":{"type":"string","title":"Project Id","description":"The project ID."},"stop_reason":{"$ref":"#/components/schemas/ChatStopReason","description":"Machine discriminant for why the run stopped. Clients branch on this, never on the display copy in `reason`."},"partial_result":{"type":"boolean","title":"Partial Result","description":"Whether a finalized partial turn was persisted before this terminal. Required, no default: every emitter declares persistence state explicitly, and only the workflow's cooperative finalize — which persists before emitting — may set True."},"new_messages":{"items":{"oneOf":[{"$ref":"#/components/schemas/ModelRequest"},{"$ref":"#/components/schemas/ModelResponse"}],"discriminator":{"propertyName":"kind","mapping":{"request":"#/components/schemas/ModelRequest","response":"#/components/schemas/ModelResponse"}}},"type":"array","title":"New Messages","description":"The persisted partial turn, surfaced and instruction-filtered. Populated only by the cooperative finalize (which persists before emitting); empty for reader-synthesized hard-cancel terminals."}},"type":"object","required":["reason","project_id","stop_reason","partial_result"],"title":"StreamChatInterrupted","description":"Schema for chat interruption event.\n\n``new_messages`` carries the persisted partial (surfaced) so the live client\nrenders a stopped turn exactly as a reload would — routing any leaked\n``<thinking>`` reasoning to the thinking display instead of leaving it as raw\nchat prose. Empty when no partial was persisted (a hard-cancel synthesis),\nso no partial turn is fabricated."},"StreamChatRetry":{"properties":{"type":{"type":"string","const":"retry","title":"Type","default":"retry"},"display":{"type":"string","const":"internal","title":"Display","default":"internal"},"attempt":{"type":"integer","title":"Attempt","description":"1-based model-call attempt now streaming (2 = first retry)."}},"type":"object","required":["attempt"],"title":"StreamChatRetry","description":"A dead model stream is being transparently retried (MAIA-2254).\n\nEmitted mid-stream when a transient transport failure (or stall) killed\nthe in-flight model response and a fresh attempt is starting. The client\nmust discard the in-flight assistant segment accumulated since the last\ncompleted tool boundary — the retry re-generates it — and may show a\ntransient \"retrying\" state. Non-terminal: the turn continues with the\nfresh attempt's deltas, or ends with the usual error frame if the retry\nalso dies."},"StreamChatTurnStarted":{"properties":{"type":{"type":"string","const":"turn_started","title":"Type","default":"turn_started"},"display":{"type":"string","const":"internal","title":"Display","default":"internal"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp","description":"Turn start, stamped from the request-receipt anchor when the workflow first writes this event (falling back to the write instant for inputs persisted by an older release); durable-stream replay preserves the original value."}},"type":"object","title":"StreamChatTurnStarted","description":"The promptless counterpart to ``StreamChatUserMessage``'s anchor.\n\nA continue-turn / tool-approval run carries no user message, so no echo is\nwritten and a reconnecting client would otherwise have no turn-start\ninstant — its elapsed-time display restarts at the reconnect. This frame is\nemitted as the FIRST durable stream event exactly when the echo is not\n(one anchor carrier per run) and carries only the timestamp. The live\nsender already anchored at submit and ignores it; clients that don't\nrecognize the type ignore it."},"StreamChatUserMessage":{"properties":{"type":{"type":"string","const":"user_message","title":"Type","default":"user_message"},"display":{"type":"string","const":"internal","title":"Display","default":"internal"},"content":{"type":"string","title":"Content","description":"The user's prompt text for this turn."},"attachment":{"anyOf":[{"$ref":"#/components/schemas/ChatAttachmentPayload"},{"type":"null"}],"description":"The document attached to this turn, so a reconnecting client re-renders its attachment pill. Load-bearing for a document-only turn, whose content is empty."},"timestamp":{"type":"string","format":"date-time","title":"Timestamp","description":"Turn start, stamped from the request-receipt anchor when the workflow first writes this event (falling back to the write instant for inputs persisted by an older release); durable-stream replay preserves the original value, so a reconnecting client anchors its elapsed-time display to the true start instead of the reconnect instant."},"invoked_skill":{"anyOf":[{"$ref":"#/components/schemas/InvokedSkillPayload"},{"type":"null"}],"description":"The catalog skill this turn invoked, as the SAME payload the persisted history metadata carries — one client-side reader for both surfaces, so a replayed bubble keeps its skill pill."}},"type":"object","required":["content"],"title":"StreamChatUserMessage","description":"The acting user's prompt, emitted as the FIRST durable stream event.\n\nThe live sender already rendered its own message optimistically, so it\nignores this echo. A client that *reconnects* to an in-flight run (page\nrefresh mid-stream) has no optimistic bubble — it replays the durable stream\nfrom offset 0 and renders the question from this event, then the deltas that\nfollow. This makes the stream the single source of truth for an in-progress\nturn (persisted history only carries completed turns)."},"StreamErrorCode":{"type":"string","enum":["db_unavailable","agent_failure","internal","run_in_progress","not_continuable","attachment_unavailable","discovery_allowance_exhausted","discovery_allowance_unavailable"],"title":"StreamErrorCode","description":"Stable taxonomy for generic stream errors.\n\nClients branch on `code` for retry / toast / surface decisions; the\nfree-form `error` message remains the user-visible string. Add\nnew codes here when a new error class needs distinct client handling."},"StreamLLMProviderError":{"properties":{"last_edit_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edit Description","description":"Human-readable description of what was changed, derived from tools called."},"last_edited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Edited At","description":"Timestamp of when the project edit was recorded."},"last_edited_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Edited By Name","description":"Display name of the user who made the edit."},"type":{"type":"string","const":"llm_provider_error","title":"Type","default":"llm_provider_error"},"display":{"type":"string","const":"internal","title":"Display","default":"internal"},"error_type":{"type":"string","enum":["overload","rate_limit","api_error"],"title":"Error Type","description":"Specific type of LLM provider error"},"error":{"type":"string","title":"Error","description":"User-friendly error message."},"provider":{"type":"string","title":"Provider","description":"LLM provider that caused the error (e.g., 'anthropic', 'openai')"},"status_code":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Status Code","description":"HTTP status code if available"},"retry_suggested":{"type":"boolean","title":"Retry Suggested","description":"Whether the user should retry","default":true},"partial_result":{"type":"boolean","title":"Partial Result","description":"True when the workflow persisted a finalized partial turn before emitting this terminal (a terminal model failure that had already completed tool work). A refresh-resumed reader reloads persisted history instead of treating this frame as fully rendered.","default":false},"continuable":{"type":"boolean","title":"Continuable","description":"True only when the failed turn left a partial the agent can resume from (the same condition that sets chats.last_turn_continuable). Distinct from partial_result: a turn can persist a partial yet not be continuable (e.g. a cooperative/monitor stop). The FE gates the Continue affordance on this, never on partial_result.","default":false},"new_messages":{"items":{"oneOf":[{"$ref":"#/components/schemas/ModelRequest"},{"$ref":"#/components/schemas/ModelResponse"}],"discriminator":{"propertyName":"kind","mapping":{"request":"#/components/schemas/ModelRequest","response":"#/components/schemas/ModelResponse"}}},"type":"array","title":"New Messages","description":"The persisted partial turn, surfaced and instruction-filtered. Populated with partial_result=True (a terminal model failure that had already completed work), so the live client renders the failed turn without leaving leaked <thinking> prose; empty otherwise."}},"type":"object","required":["error_type","error","provider"],"title":"StreamLLMProviderError","description":"Schema for LLM provider-specific errors.\n\nA terminal model failure that already committed work finalizes on this frame\nrather than downgrading to a generic error — keeping the honest \"providers\nresponding slowly\" provider taxonomy. The stamp + ``partial_result`` fields\nare additive (``partial_result`` defaults False, stamp fields default None),\nso the generic provider-error construction\n(``categorize_chat_stream_exception_to_frame``) is unchanged."},"StreamMapActivity":{"properties":{"type":{"type":"string","const":"map_activity","title":"Type","default":"map_activity"},"display":{"type":"string","const":"internal","title":"Display","default":"internal"},"tool_call_id":{"type":"string","title":"Tool Call Id","description":"Tool call this activity belongs to."},"action":{"type":"string","enum":["scan","write","create_layer","restyle","delete_layer"],"title":"Action"},"subjects":{"items":{"$ref":"#/components/schemas/MapActivitySubject"},"type":"array","title":"Subjects"},"bbox":{"anyOf":[{"items":{"type":"number"},"type":"array"},{"type":"null"}],"title":"Bbox","description":"[w, s, e, n] extent of the touched data."},"seq":{"type":"integer","title":"Seq","default":0}},"type":"object","required":["tool_call_id","action"],"title":"StreamMapActivity","description":"What the agent's current tool call is actually touching on the map.\n\nEmitted by tools themselves (not the run-event translator), keyed to the\ntool call so the client can upgrade that phase's guessed paint to truth.\nWritten to the durable chat stream, so it replays on resume like any other\nevent. Multiple emissions per tool call are ordered by ``seq``; a later\n``seq`` supersedes an earlier one for the same call."},"StreamProjectCreated":{"properties":{"type":{"type":"string","const":"project_created","title":"Type","default":"project_created"},"display":{"type":"string","const":"internal","title":"Display","default":"internal"},"project_id":{"type":"string","title":"Project Id","description":"The newly created project ID."},"project_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Name","description":"Auto-generated project title, if available."}},"type":"object","required":["project_id"],"title":"StreamProjectCreated","description":"Schema for project creation event, sent at stream start."},"StreamSummarizationStatus":{"properties":{"type":{"type":"string","const":"summarization_status","title":"Type","default":"summarization_status"},"display":{"type":"string","const":"internal","title":"Display","default":"internal"},"message":{"type":"string","title":"Message","description":"User-facing description of the wait."}},"type":"object","required":["message"],"title":"StreamSummarizationStatus","description":"A follow-up send is waiting out the prior turn's summary finalization.\n\nEmitted once, before the send path starts polling for the summary child's\nslot release, so the client can show an accurate working state instead of\nsilence. Non-terminal: the turn either proceeds into the normal stream or\nends with a typed ``StreamChatError`` if the window outlives the wait."},"StreamThinkingDelta":{"properties":{"type":{"type":"string","const":"thinking_delta","title":"Type","default":"thinking_delta"},"display":{"type":"string","const":"thinking","title":"Display","default":"thinking"},"content":{"type":"string","title":"Content","description":"Incremental thinking/reasoning content from the agent."}},"type":"object","required":["content"],"title":"StreamThinkingDelta","description":"Schema for streaming thinking/reasoning content deltas."},"StreamToolCallComplete":{"properties":{"type":{"type":"string","const":"tool_call_complete","title":"Type","default":"tool_call_complete"},"display":{"type":"string","const":"tool_call_result","title":"Display","default":"tool_call_result"},"tool_name":{"type":"string","title":"Tool Name","description":"Name of the tool that was called."},"tool_call_id":{"type":"string","title":"Tool Call Id","description":"Unique identifier for this tool call."},"result":{"title":"Result","description":"Result returned by the tool."},"outcome":{"type":"string","enum":["success","failed","denied","interrupted"],"title":"Outcome","description":"Mirrors pydantic-ai's ToolReturnPart.outcome so the client can suppress success affordances for denied or interrupted calls.","default":"success"}},"type":"object","required":["tool_name","tool_call_id","result"],"title":"StreamToolCallComplete","description":"Schema for when a tool call completes."},"StreamToolCallStart":{"properties":{"type":{"type":"string","const":"tool_call_start","title":"Type","default":"tool_call_start"},"display":{"type":"string","const":"tool_call_start","title":"Display","default":"tool_call_start"},"tool_name":{"type":"string","title":"Tool Name","description":"Name of the tool being called."},"tool_call_id":{"type":"string","title":"Tool Call Id","description":"Unique identifier for this tool call."},"args":{"additionalProperties":true,"type":"object","title":"Args","description":"Arguments passed to the tool."}},"type":"object","required":["tool_name","tool_call_id","args"],"title":"StreamToolCallStart","description":"Schema for when a tool call begins."},"StreamWebSearchStatus":{"properties":{"type":{"type":"string","const":"web_search_status","title":"Type","default":"web_search_status"},"display":{"type":"string","const":"internal","title":"Display","default":"internal"},"status":{"type":"string","title":"Status","description":"Status of the web search operation."},"tool_call_id":{"type":"string","title":"Tool Call Id","description":"Unique identifier for this tool call."},"content":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Content","description":"Additional status data if available."}},"type":"object","required":["status","tool_call_id"],"title":"StreamWebSearchStatus","description":"Schema for web search status updates from built-in tools."},"SyncResponse":{"properties":{"synced_release_count":{"type":"integer","title":"Synced Release Count"}},"type":"object","required":["synced_release_count"],"title":"SyncResponse"},"SystemPromptPart":{"properties":{"content":{"type":"string","title":"Content"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"dynamic_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dynamic Ref"},"part_kind":{"type":"string","const":"system-prompt","title":"Part Kind","default":"system-prompt"}},"type":"object","required":["content"],"title":"SystemPromptPart","description":"A system prompt, generally written by the application developer.\n\nThis gives the model context and guidance on how to respond."},"TenantLeaseConcise":{"properties":{"tenant_legal_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tenant Legal Name","description":"Tenant legal name or primary occupant name."},"lease_start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Lease Start Date","description":"Lease commencement / tenant move-in date (if known)."},"lease_end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Lease End Date","description":"Lease expiration date for the current in-place term."},"in_place_rent_psf_yr":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"In Place Rent Psf Yr","description":"$ / SF / Year current in-place base rent (net of abatements if possible)."},"expense_structure":{"anyOf":[{"$ref":"#/components/schemas/ExpenseStructure"},{"type":"null"}],"description":"Expense pass-through structure (NNN, modified gross, etc.)."},"escalation_type":{"anyOf":[{"$ref":"#/components/schemas/LeaseEscalationType"},{"type":"null"}],"description":"How base rent escalates (fixed %, CPI, hybrid, none)."},"occupancy_status":{"anyOf":[{"$ref":"#/components/schemas/OccupancyStatus"},{"type":"null"}],"description":"Leased / Vacant / Owner-occupied / Partial / Unknown — good single filter."},"num_tenants":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Num Tenants","description":"Number of distinct tenants in the building (1 = single-tenant)."},"delinquency_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Delinquency Status","description":"Description of the tenant's delinquency status."},"as_of":{"type":"string","format":"date-time","title":"As Of","description":"UTC timestamp when this record was compiled/last updated."}},"type":"object","title":"TenantLeaseConcise","description":"Concise tenant / lease model optimized for REIT screens.\nIncludes a small set of critical fields and computed helpers\n(lease duration, months remaining, rent delta). Use `to_dict()`\nto include derived values in output."},"TenureRange":{"properties":{"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"},"reasoning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reasoning","description":"The reasoning for the tenure range."},"sources":{"items":{"type":"string"},"type":"array","title":"Sources","description":"The sources for the tenure range."}},"type":"object","title":"TenureRange","description":"Job tenure range representing when someone started at their current position/company.\n\nUsed for employment duration (e.g., via PDL data).\nCan represent exact year (min == max) or range of possible years.\nConfidence is inferred: exact year = confirmed, range = approximate."},"TermsAcceptanceRequest":{"properties":{"terms_version":{"type":"string","minLength":1,"title":"Terms Version"}},"type":"object","required":["terms_version"],"title":"TermsAcceptanceRequest","description":"The version the client displayed at the moment of the click."},"TermsAcceptanceResponse":{"properties":{"terms_version":{"type":"string","title":"Terms Version"}},"type":"object","required":["terms_version"],"title":"TermsAcceptanceResponse","description":"The version actually recorded, echoed from server config."},"TextCondition":{"properties":{"filterType":{"type":"string","const":"text","title":"Filtertype","default":"text"},"type":{"type":"string","enum":["contains","notContains","equals","notEqual","startsWith","endsWith","blank","notBlank","unavailable"],"title":"Type"},"filter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filter"}},"type":"object","required":["type"],"title":"TextCondition"},"TextContent":{"properties":{"content":{"type":"string","title":"Content"},"metadata":{"title":"Metadata"},"kind":{"type":"string","const":"text-content","title":"Kind","default":"text-content"}},"type":"object","required":["content"],"title":"TextContent","description":"String content that is tagged with additional metadata.\n\nThis is useful for including metadata that can be accessed programmatically by the application, but is not sent to the LLM."},"TextPart":{"properties":{"content":{"type":"string","title":"Content"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"text","title":"Part Kind","default":"text"}},"type":"object","required":["content"],"title":"TextPart","description":"A plain text response from a model."},"ThinkingPart":{"properties":{"content":{"type":"string","title":"Content"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"signature":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signature"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"thinking","title":"Part Kind","default":"thinking"}},"type":"object","required":["content"],"title":"ThinkingPart","description":"A thinking response from a model."},"ThumbnailBounds":{"properties":{"min_lon":{"type":"number","title":"Min Lon"},"min_lat":{"type":"number","title":"Min Lat"},"max_lon":{"type":"number","title":"Max Lon"},"max_lat":{"type":"number","title":"Max Lat"}},"type":"object","required":["min_lon","min_lat","max_lon","max_lat"],"title":"ThumbnailBounds","description":"Bounding box for project thumbnail map rendering.\n\nRepresents the geographic extent of project features for generating\nstatic map thumbnails via Mapbox."},"ToolApprovalAnswer":{"properties":{"toolCallId":{"type":"string","title":"Toolcallid"},"approved":{"type":"boolean","title":"Approved"},"message":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Message"}},"type":"object","required":["toolCallId","approved"],"title":"ToolApprovalAnswer","description":"The user's approve/decline for a pending tool call.\n\n``message`` is wire-forward-compat: no UI affordance sends it yet (the\ncard is approve/decline only), but the denial seam already threads it\ninto the synthesized ToolDenied as context for a future decline-reason\ninput. Capped because it persists into chat history and rides every\nsubsequent model call."},"ToolApprovalRequest":{"properties":{"toolCallId":{"type":"string","title":"Toolcallid"},"toolName":{"type":"string","title":"Toolname"},"args":{"additionalProperties":true,"type":"object","title":"Args"},"details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Details"}},"type":"object","required":["toolCallId","toolName","args"],"title":"ToolApprovalRequest","description":"The pending approval-gated tool call, as persisted for card rendering."},"ToolAvailabilityDeltaPart":{"properties":{"tools_added":{"items":{"type":"string"},"type":"array","title":"Tools Added"},"tool_call_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tool Call Id"},"part_kind":{"type":"string","const":"tool-availability-delta","title":"Part Kind","default":"tool-availability-delta"}},"type":"object","title":"ToolAvailabilityDeltaPart","description":"Records that the set of tools available to the model changed at this point.\n\nAdditions only. Withdrawing a tool is not supported yet, because no provider can be told about one\nwithout also invalidating the prompt cache this part exists to protect: Anthropic rejects a\nreference to a tool the request doesn't declare, so a withdrawn tool has to leave the `tools`\narray, and that is itself the invalidation. The name says *availability* rather than *addition* so\nremovals can join once they can be done cache-safely — see\nhttps://github.com/pydantic/pydantic-ai/issues/6985."},"ToolCallPart":{"properties":{"tool_name":{"type":"string","title":"Tool Name"},"args":{"anyOf":[{"type":"string"},{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Args"},"tool_call_id":{"type":"string","title":"Tool Call Id"},"tool_kind":{"anyOf":[{"type":"string","enum":["tool-search","capability-load"]},{"type":"null"}],"title":"Tool Kind"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"tool-call","title":"Part Kind","default":"tool-call"}},"type":"object","required":["tool_name"],"title":"ToolCallPart","description":"A tool call from a model."},"ToolResourceResponse":{"properties":{"message":{"type":"string","title":"Message","description":"Response to prompt and description of the changes made."},"resources":{"items":{"$ref":"#/components/schemas/ResourceReference"},"type":"array","title":"Resources","description":"List of resources created or modified by the tool."}},"type":"object","required":["message"],"title":"ToolResourceResponse","description":"Generic response model for tool/agent outputs.\n\nStructured response that includes a message and any resource references\ncreated or modified by the tool."},"ToolReturnContent":{"oneOf":[{},{"additionalProperties":{"$ref":"#/components/schemas/ToolReturnContent"},"type":"object"},{"items":{"$ref":"#/components/schemas/ToolReturnContent"},"type":"array"}]},"ToolReturnPart":{"properties":{"tool_name":{"type":"string","title":"Tool Name"},"content":{"$ref":"#/components/schemas/ToolReturnContent"},"tool_call_id":{"type":"string","title":"Tool Call Id"},"tool_kind":{"anyOf":[{"type":"string","enum":["tool-search","capability-load"]},{"type":"null"}],"title":"Tool Kind"},"metadata":{"title":"Metadata"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"outcome":{"type":"string","enum":["success","failed","denied","interrupted"],"title":"Outcome","default":"success"},"part_kind":{"type":"string","const":"tool-return","title":"Part Kind","default":"tool-return"}},"type":"object","required":["tool_name","content"],"title":"ToolReturnPart","description":"A tool return message, this encodes the result of running a tool."},"ToolSearchArgs":{"properties":{"queries":{"items":{"type":"string"},"type":"array","title":"Queries"}},"type":"object","required":["queries"],"title":"ToolSearchArgs","description":"Typed arguments for a tool-search call.\n\nCarried on\n[`NativeToolSearchCallPart.args`][pydantic_ai.messages.NativeToolSearchCallPart.args]\n(native server-side path) and\n[`ToolSearchCallPart.args`][pydantic_ai.messages.ToolSearchCallPart.args]\n(local-fallback path) as the canonical cross-provider shape. Each adapter\nnormalizes its provider's wire format into this shape on parse, and rebuilds the\nwire format from this shape on emit."},"ToolSearchCallPart":{"properties":{"tool_name":{"type":"string","const":"search_tools","title":"Tool Name","default":"search_tools"},"args":{"anyOf":[{"type":"string"},{"$ref":"#/components/schemas/ToolSearchArgs"},{"type":"null"}],"title":"Args"},"tool_call_id":{"type":"string","title":"Tool Call Id"},"tool_kind":{"type":"string","const":"tool-search","title":"Tool Kind","default":"tool-search"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"provider_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Name"},"provider_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Details"},"part_kind":{"type":"string","const":"tool-call","title":"Part Kind","default":"tool-call"}},"type":"object","title":"ToolSearchCallPart","description":"Typed view of a [`ToolCallPart`][pydantic_ai.messages.ToolCallPart] for the local `search_tools` function call.\n\nUsed on the local-fallback path (and as the synthetic-injection target on\nnon-native providers receiving cross-provider history). The native server-side\npath uses\n[`NativeToolSearchCallPart`][pydantic_ai.messages.NativeToolSearchCallPart]\ninstead.\n\nTo detect a tool-search part regardless of execution path (native server-side\nvs. local fallback), check `part.tool_kind == 'tool-search'` — this works\nacross both call/return and both server/local variants.\n\nShadows `args` with the canonical typed shape. The `str` variant covers the\nstreaming / partial-args case before parsing completes; once parsed,\n`args` is a [`ToolSearchArgs`][pydantic_ai.messages.ToolSearchArgs]\n`TypedDict`."},"ToolSearchMatch":{"properties":{"name":{"type":"string","title":"Name"}},"type":"object","required":["name"],"title":"ToolSearchMatch","description":"A single match in a tool-search result."},"ToolSearchReturnContent":{"properties":{"discovered_tools":{"items":{"$ref":"#/components/schemas/ToolSearchMatch"},"type":"array","title":"Discovered Tools"},"message":{"type":"string","title":"Message"}},"type":"object","required":["discovered_tools"],"title":"ToolSearchReturnContent","description":"Typed return value of the framework-managed tool-search builtin.\n\nCarried on\n[`NativeToolSearchReturnPart.content`][pydantic_ai.messages.NativeToolSearchReturnPart.content]\n(native server-side path) and\n[`ToolSearchReturnPart.content`][pydantic_ai.messages.ToolSearchReturnPart.content]\n(local-fallback path) as the canonical cross-provider shape."},"ToolSearchReturnPart":{"properties":{"tool_name":{"type":"string","const":"search_tools","title":"Tool Name","default":"search_tools"},"tool_call_id":{"type":"string","title":"Tool Call Id"},"tool_kind":{"type":"string","const":"tool-search","title":"Tool Kind","default":"tool-search"},"content":{"$ref":"#/components/schemas/ToolSearchReturnContent"},"metadata":{"title":"Metadata"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"outcome":{"type":"string","enum":["success","failed","denied","interrupted"],"title":"Outcome","default":"success"},"part_kind":{"type":"string","const":"tool-return","title":"Part Kind","default":"tool-return"}},"type":"object","required":["content"],"title":"ToolSearchReturnPart","description":"Typed view of a [`ToolReturnPart`][pydantic_ai.messages.ToolReturnPart] for the local `search_tools` function return.\n\nUsed on the local-fallback path (and as the synthetic-injection target on\nnon-native providers receiving cross-provider history). The native server-side\npath uses\n[`NativeToolSearchReturnPart`][pydantic_ai.messages.NativeToolSearchReturnPart]\ninstead.\n\nTo detect a tool-search part regardless of execution path (native server-side\nvs. local fallback), check `part.tool_kind == 'tool-search'` — this works\nacross both call/return and both server/local variants.\n\nShadows `content` with a narrower\n[`ToolSearchReturnContent`][pydantic_ai.messages.ToolSearchReturnContent]\n`TypedDict`."},"TransferDestinationCreateRequest":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"e164":{"type":"string","maxLength":32,"minLength":1,"title":"E164"},"is_default":{"type":"boolean","title":"Is Default","default":false}},"type":"object","required":["name","e164"],"title":"TransferDestinationCreateRequest"},"TransferDestinationListResponse":{"properties":{"destinations":{"items":{"$ref":"#/components/schemas/TransferDestinationResponse"},"type":"array","title":"Destinations"}},"type":"object","required":["destinations"],"title":"TransferDestinationListResponse"},"TransferDestinationResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"e164":{"type":"string","title":"E164"},"is_default":{"type":"boolean","title":"Is Default"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","e164","is_default","created_at","updated_at"],"title":"TransferDestinationResponse"},"TransferDestinationUpdateRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120,"minLength":1},{"type":"null"}],"title":"Name"},"is_default":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Default"}},"type":"object","title":"TransferDestinationUpdateRequest","description":"Partial update — omitted fields are left untouched."},"TriageWeekResponse":{"properties":{"week_start":{"type":"string","format":"date","title":"Week Start"},"releases":{"items":{"$ref":"#/components/schemas/GithubReleaseResponse"},"type":"array","title":"Releases"}},"type":"object","required":["week_start","releases"],"title":"TriageWeekResponse"},"UnknownChatRunStatus":{"properties":{"status":{"type":"string","const":"unknown","title":"Status","default":"unknown"}},"type":"object","title":"UnknownChatRunStatus","description":"A chat run whose state cannot be read authoritatively."},"UnprocessableQueryReason":{"type":"string","enum":["out_of_scope","too_vague","geographic_restrictions","execution_blocked"],"title":"UnprocessableQueryReason"},"UnprocessableQueryResult":{"properties":{"reason":{"$ref":"#/components/schemas/UnprocessableQueryReason","description":"Why the query cannot be processed"},"message":{"type":"string","title":"Message","description":"User-friendly explanation of why the query cannot be processed. Format rules: - Use third-person, declarative statements (NOT first-person like \"I can't\" or \"I don't understand\")\n- Do NOT ask questions (no \"Did you mean...?\" or \"Can you specify...?\")\n- Be concise and actionable - explain what's needed for a valid query"},"suggestions":{"items":{"type":"string"},"type":"array","title":"Suggestions","description":"Optional list of example valid queries the user could try"},"requirements_met":{"anyOf":[{"$ref":"#/components/schemas/RequirementsCheck"},{"type":"null"}],"description":"Which requirements from the query are satisfied, even if the overall query is invalid"}},"type":"object","required":["reason","message"],"title":"UnprocessableQueryResult","description":"Result returned when a query cannot be processed — invalid input, system limitation, or execution blocker."},"UpdateContactNoteRequest":{"properties":{"content":{"type":"string","maxLength":5000,"minLength":1,"title":"Content"}},"type":"object","required":["content"],"title":"UpdateContactNoteRequest"},"UpdateContactRequest":{"properties":{"full_name":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Full Name"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"job_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Title"},"job_company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Company Name"},"work_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Work Email"},"personal_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Personal Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"mobile_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mobile Phone"},"linkedin_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Url"},"location_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Name"},"status":{"anyOf":[{"type":"string","enum":["not_contacted","contacted","contact_failed"]},{"type":"null"}],"title":"Status"},"is_favorite":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Favorite"}},"type":"object","title":"UpdateContactRequest"},"UpdateContactStatusRequest":{"properties":{"status":{"type":"string","enum":["not_contacted","contacted","contact_failed"],"title":"Status"}},"type":"object","required":["status"],"title":"UpdateContactStatusRequest"},"UpdateDigestRequest":{"properties":{"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject"},"preheader":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Preheader"},"body_markdown":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Markdown"}},"type":"object","title":"UpdateDigestRequest","description":"A partial edit, where omitting a field and nulling it differ.\n\nOnly the keys actually present in the request body are written, so sending\n``preheader: null`` clears the preview line while leaving the key out keeps\nwhatever is on file."},"UpdateEnrichmentRequest":{"properties":{"updates":{"$ref":"#/components/schemas/EnrichmentUpdates","examples":[{"name":"New Name"}]},"confirmation":{"anyOf":[{"$ref":"#/components/schemas/EnrichmentUpdatePreview"},{"type":"null"}]},"stable_run_key":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Stable Run Key"}},"type":"object","required":["updates"],"title":"UpdateEnrichmentRequest","description":"Request schema for updating an enrichment.\n\nAttributes:\n    updates: Structured updates for the enrichment"},"UpdateEntryRequest":{"properties":{"title":{"type":"string","title":"Title"},"body_markdown":{"type":"string","title":"Body Markdown"}},"type":"object","required":["title","body_markdown"],"title":"UpdateEntryRequest"},"UpdateOperatorControlsRequest":{"anyOf":[{"$ref":"#/components/schemas/AdmissionsPausedControlUpdate"},{"$ref":"#/components/schemas/PublicSignupControlUpdate"}],"title":"UpdateOperatorControlsRequest","description":"The supplied controls change; omitted controls stay unchanged.\n\nAn operator must state at least one switch. Explicit null is rejected rather\nthan read as omission, while explicit false remains a write."},"UploadedFile":{"properties":{"file_id":{"type":"string","title":"File Id"},"provider_name":{"type":"string","enum":["anthropic","openai","google","google-cloud","google-gla","google-vertex","bedrock","xai"],"title":"Provider Name"},"vendor_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Vendor Metadata"},"kind":{"type":"string","const":"uploaded-file","title":"Kind","default":"uploaded-file"},"media_type":{"type":"string","title":"Media Type","description":"Return the media type of the file, inferred from `file_id` if not explicitly provided.\n\nNote: Inference relies on the file extension in `file_id`.\nFor opaque file IDs (e.g., `'file-abc123'`), the media type will default to `'application/octet-stream'`.\nInference relies on Python's `mimetypes` module, whose results may vary across platforms.\n\nRequired by some providers (e.g., Bedrock) for certain file types.","readOnly":true},"identifier":{"type":"string","title":"Identifier","description":"The identifier of the file, such as a unique ID.\n\nThis identifier can be provided to the model in a message to allow it to refer to this file in a tool call argument,\nand the tool can look up the file in question by iterating over the message history and finding the matching `UploadedFile`.\n\nThis identifier is only automatically passed to the model when the `UploadedFile` is returned by a tool.\nIf you're passing the `UploadedFile` as a user message, it's up to you to include a separate text part with the identifier,\ne.g. \"This is file <identifier>:\" preceding the `UploadedFile`.","readOnly":true}},"type":"object","required":["file_id","provider_name","media_type","identifier"],"title":"UploadedFile","description":"A reference to a file uploaded to a provider's file storage by ID.\n\nThis allows referencing files that have been uploaded via provider-specific file APIs\nrather than providing the file content directly.\n\nSupported by:\n\n- [`AnthropicModel`][pydantic_ai.models.anthropic.AnthropicModel]\n- [`OpenAIChatModel`][pydantic_ai.models.openai.OpenAIChatModel]\n- [`OpenAIResponsesModel`][pydantic_ai.models.openai.OpenAIResponsesModel]\n- [`BedrockConverseModel`][pydantic_ai.models.bedrock.BedrockConverseModel]\n- [`GoogleModel`][pydantic_ai.models.google.GoogleModel] (Gemini API: [Files API](https://ai.google.dev/gemini-api/docs/files) URIs, Google Cloud: GCS `gs://` URIs)\n- [`XaiModel`][pydantic_ai.models.xai.XaiModel]"},"UserExistsResponse":{"properties":{"exists":{"type":"boolean","title":"Exists"},"has_password":{"type":"boolean","title":"Has Password"}},"type":"object","required":["exists","has_password"],"title":"UserExistsResponse","description":"Response model for checking if a user exists."},"UserProfile":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","format":"email","title":"Email"},"username":{"type":"string","title":"Username"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"workspace_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Workspace Name"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"avatar_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Color"},"has_completed_onboarding":{"type":"boolean","title":"Has Completed Onboarding","default":false},"plan_type":{"$ref":"#/components/schemas/PlanType","default":"beta"},"allowed_geographies":{"items":{"type":"string"},"type":"array","title":"Allowed Geographies"},"available_enrichment_credits":{"type":"integer","title":"Available Enrichment Credits"},"used_enrichment_credits":{"type":"integer","title":"Used Enrichment Credits"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Active At"},"is_internal":{"type":"boolean","title":"Is Internal","default":false},"is_suspended":{"type":"boolean","title":"Is Suspended","default":false},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"workspace_role":{"$ref":"#/components/schemas/WorkspaceRole","default":"writer"},"is_workspace_admin":{"type":"boolean","title":"Is Workspace Admin","default":false},"workspace_member_count":{"type":"integer","title":"Workspace Member Count","default":1},"column_preferences":{"anyOf":[{"additionalProperties":{"additionalProperties":{"type":"boolean"},"type":"object"},"type":"object"},{"type":"null"}],"title":"Column Preferences"},"feature_toggles":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Feature Toggles"},"terms_acceptance_required":{"type":"boolean","title":"Terms Acceptance Required","default":false},"terms_version":{"type":"string","title":"Terms Version","default":""},"terms_url":{"type":"string","title":"Terms Url","default":""},"plan":{"$ref":"#/components/schemas/Plan","description":"Get plan configuration for this user's plan type.","readOnly":true},"available_geographies":{"items":{"type":"string"},"type":"array","title":"Available Geographies","description":"Get FIPS codes of counties this user can query.\n\nSourced from `workspace_counties` via `enrich_profile_with_workspace_data`,\nwhich reads the repository's access predicate — data present in the\nworkspace's branch and not suspended. That covers a county loaded for\nthis workspace and one that arrived with its branch alike. Empty list\nmeans the workspace has no county data yet.","readOnly":true}},"type":"object","required":["id","email","username","available_enrichment_credits","used_enrichment_credits","workspace_id","plan","available_geographies"],"title":"UserProfile","description":"Data Transfer Object for database User entity.\n\nThis represents a user stored in the database with enrichment credits,\ndistinct from the Firebase User model used for authentication."},"UserProfileUpdateRequest":{"properties":{"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"avatar_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Color"},"has_completed_onboarding":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Completed Onboarding"},"column_preferences":{"anyOf":[{"additionalProperties":{"additionalProperties":{"type":"boolean"},"type":"object"},"type":"object"},{"type":"null"}],"title":"Column Preferences"}},"type":"object","title":"UserProfileUpdateRequest","description":"Request model for updating user profile information."},"UserProfileUpdateResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message"}},"type":"object","required":["success","message"],"title":"UserProfileUpdateResponse","description":"Response model for user profile update."},"UserPromptPart":{"properties":{"content":{"anyOf":[{"type":"string"},{"items":{"anyOf":[{"type":"string"},{"$ref":"#/components/schemas/TextContent"},{"oneOf":[{"$ref":"#/components/schemas/ImageUrl"},{"$ref":"#/components/schemas/AudioUrl"},{"$ref":"#/components/schemas/DocumentUrl"},{"$ref":"#/components/schemas/VideoUrl"},{"$ref":"#/components/schemas/BinaryContent"},{"$ref":"#/components/schemas/UploadedFile"}],"discriminator":{"propertyName":"kind","mapping":{"audio-url":"#/components/schemas/AudioUrl","binary":"#/components/schemas/BinaryContent","document-url":"#/components/schemas/DocumentUrl","image-url":"#/components/schemas/ImageUrl","uploaded-file":"#/components/schemas/UploadedFile","video-url":"#/components/schemas/VideoUrl"}}},{"$ref":"#/components/schemas/CachePoint"}]},"type":"array"}],"title":"Content"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"part_kind":{"type":"string","const":"user-prompt","title":"Part Kind","default":"user-prompt"}},"type":"object","required":["content"],"title":"UserPromptPart","description":"A user prompt, generally written by the end user.\n\nContent comes from the `user_prompt` parameter of [`Agent.run`][pydantic_ai.agent.AbstractAgent.run],\n[`Agent.run_sync`][pydantic_ai.agent.AbstractAgent.run_sync], and [`Agent.run_stream`][pydantic_ai.agent.AbstractAgent.run_stream]."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VideoUrl":{"properties":{"url":{"type":"string","title":"Url"},"force_download":{"anyOf":[{"type":"boolean"},{"type":"string","const":"allow-local"}],"title":"Force Download","default":false},"vendor_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Vendor Metadata"},"kind":{"type":"string","const":"video-url","title":"Kind","default":"video-url"},"media_type":{"type":"string","title":"Media Type","description":"Return the media type of the file, based on the URL or the provided `media_type`.","readOnly":true},"identifier":{"type":"string","title":"Identifier","description":"The identifier of the file, such as a unique ID.\n\nThis identifier can be provided to the model in a message to allow it to refer to this file in a tool call argument,\nand the tool can look up the file in question by iterating over the message history and finding the matching `FileUrl`.\n\nThis identifier is only automatically passed to the model when the `FileUrl` is returned by a tool.\nIf you're passing the `FileUrl` as a user message, it's up to you to include a separate text part with the identifier,\ne.g. \"This is file <identifier>:\" preceding the `FileUrl`.\n\nIt's also included in inline-text delimiters for providers that require inlining text documents, so the model can\ndistinguish multiple files.","readOnly":true}},"type":"object","required":["url","media_type","identifier"],"title":"VideoUrl","description":"A URL to a video."},"ViewCreateRequest":{"properties":{"view":{"$ref":"#/components/schemas/ViewModel-Input"}},"type":"object","required":["view"],"title":"ViewCreateRequest","description":"Request model for creating a new view.\n\nAttributes:\n    view: The view to create"},"ViewCreateResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"view":{"$ref":"#/components/schemas/ViewModel-Output"}},"type":"object","required":["success","view"],"title":"ViewCreateResponse","description":"Response model for creating a new view.\n\nAttributes:\n    success: Boolean indicating if the creation was successful\n    view: The created view model"},"ViewDeleteResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message","default":"View deleted successfully"}},"type":"object","required":["success"],"title":"ViewDeleteResponse","description":"Response model for deleting a view.\n\nAttributes:\n    success: Boolean indicating if the deletion was successful\n    message: Optional message providing additional information"},"ViewModel-Input":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"layerFilters":{"additionalProperties":{"additionalProperties":{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Input"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},"type":"object"},"type":"object","title":"Layerfilters"},"mapFilters":{"anyOf":[{"$ref":"#/components/schemas/MapFilterModel"},{"type":"null"}]},"layerColumnVisibility":{"additionalProperties":{"additionalProperties":{"type":"boolean"},"type":"object"},"type":"object","title":"Layercolumnvisibility"},"layerColumnOrder":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object","title":"Layercolumnorder"},"layerColumnPinned":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object","title":"Layercolumnpinned"},"layerColumnSort":{"additionalProperties":{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array"},"type":"object","title":"Layercolumnsort"},"layerColumnWidths":{"additionalProperties":{"additionalProperties":{"type":"integer"},"type":"object"},"type":"object","title":"Layercolumnwidths"},"layerGroupByColumn":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","title":"Layergroupbycolumn"},"layerVisibility":{"anyOf":[{"additionalProperties":{"type":"boolean"},"type":"object"},{"type":"null"}],"title":"Layervisibility"},"layerViz":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Layerviz"},"basemap":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Basemap"},"currentLayerId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currentlayerid"},"isEditable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Iseditable"},"showFavoritesOnly":{"type":"boolean","title":"Showfavoritesonly","default":false},"version":{"type":"integer","title":"Version","default":0}},"type":"object","required":["id","name"],"title":"ViewModel","description":"Model for a view"},"ViewModel-Output":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"layerFilters":{"additionalProperties":{"additionalProperties":{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Output"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},"type":"object"},"type":"object","title":"Layerfilters"},"mapFilters":{"anyOf":[{"$ref":"#/components/schemas/MapFilterModel"},{"type":"null"}]},"layerColumnVisibility":{"additionalProperties":{"additionalProperties":{"type":"boolean"},"type":"object"},"type":"object","title":"Layercolumnvisibility"},"layerColumnOrder":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object","title":"Layercolumnorder"},"layerColumnPinned":{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object","title":"Layercolumnpinned"},"layerColumnSort":{"additionalProperties":{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array"},"type":"object","title":"Layercolumnsort"},"layerColumnWidths":{"additionalProperties":{"additionalProperties":{"type":"integer"},"type":"object"},"type":"object","title":"Layercolumnwidths"},"layerGroupByColumn":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","title":"Layergroupbycolumn"},"layerVisibility":{"anyOf":[{"additionalProperties":{"type":"boolean"},"type":"object"},{"type":"null"}],"title":"Layervisibility"},"layerViz":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Layerviz"},"basemap":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Basemap"},"currentLayerId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currentlayerid"},"isEditable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Iseditable"},"showFavoritesOnly":{"type":"boolean","title":"Showfavoritesonly","default":false},"version":{"type":"integer","title":"Version","default":0}},"type":"object","required":["id","name"],"title":"ViewModel","description":"Model for a view"},"ViewOfferPreview":{"properties":{"proposedName":{"type":"string","title":"Proposedname","description":"The name the View will be saved under if the user accepts."},"summary":{"type":"string","title":"Summary","description":"One line stating what will be saved — the filters/slice that define the current set (e.g. 'Region = West, Status = Active'). Shown to the user in the offer card so they know what they're saving."}},"type":"object","required":["proposedName","summary"],"title":"ViewOfferPreview"},"ViewStateChangedEvent":{"properties":{"type":{"type":"string","const":"view_state_changed","title":"Type","default":"view_state_changed"},"projectId":{"type":"string","format":"uuid","title":"Projectid"},"views":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Views"},"deletedViewIds":{"items":{"type":"string"},"type":"array","title":"Deletedviewids","default":[]}},"type":"object","required":["projectId","views"],"title":"ViewStateChangedEvent","description":"Fired after a project view mutation commits (create / update / filter /\ndelete / column change), over the same per-user channel.\n\nPayload-rich + version-stamped, mirroring ``EnrichmentStatusChangedEvent``:\nthe FE applies the carried view(s) straight to its React Query cache without\na refetch round-trip, and uses each view's ``version`` to discard stale or\nout-of-order events. Carries only the *affected* view(s) plus ``deletedViewIds``\n(not the full list) so the FE merges rather than overwrites siblings.\n\nFields are camelCase so the SSE endpoint can forward ``model_dump_json``\nverbatim and the FE reads the same keys it reads off ``/views``."},"ViewUpdateModel":{"properties":{"id":{"type":"string","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"layerFilters":{"anyOf":[{"additionalProperties":{"additionalProperties":{"oneOf":[{"$ref":"#/components/schemas/CompoundFilter-Input"},{"oneOf":[{"$ref":"#/components/schemas/TextCondition"},{"$ref":"#/components/schemas/NumberCondition"},{"$ref":"#/components/schemas/SetCondition"},{"$ref":"#/components/schemas/DateCondition"},{"$ref":"#/components/schemas/BooleanCondition"}],"discriminator":{"propertyName":"filterType","mapping":{"boolean":"#/components/schemas/BooleanCondition","date":"#/components/schemas/DateCondition","number":"#/components/schemas/NumberCondition","set":"#/components/schemas/SetCondition","text":"#/components/schemas/TextCondition"}}}]},"type":"object"},"type":"object"},{"type":"null"}],"title":"Layerfilters"},"mapFilters":{"anyOf":[{"$ref":"#/components/schemas/MapFilterModel"},{"type":"null"}]},"layerColumnVisibility":{"anyOf":[{"additionalProperties":{"additionalProperties":{"type":"boolean"},"type":"object"},"type":"object"},{"type":"null"}],"title":"Layercolumnvisibility"},"layerColumnOrder":{"anyOf":[{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object"},{"type":"null"}],"title":"Layercolumnorder"},"layerColumnPinned":{"anyOf":[{"additionalProperties":{"items":{"type":"string"},"type":"array"},"type":"object"},{"type":"null"}],"title":"Layercolumnpinned"},"layerColumnSort":{"anyOf":[{"additionalProperties":{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array"},"type":"object"},{"type":"null"}],"title":"Layercolumnsort"},"layerColumnWidths":{"anyOf":[{"additionalProperties":{"additionalProperties":{"type":"integer"},"type":"object"},"type":"object"},{"type":"null"}],"title":"Layercolumnwidths"},"layerGroupByColumn":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Layergroupbycolumn"},"layerVisibility":{"anyOf":[{"additionalProperties":{"type":"boolean"},"type":"object"},{"type":"null"}],"title":"Layervisibility"},"layerViz":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Layerviz"},"basemap":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Basemap"},"currentLayerId":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currentlayerid"},"isEditable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Iseditable"},"showFavoritesOnly":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Showfavoritesonly"}},"type":"object","required":["id"],"title":"ViewUpdateModel","description":"Model for partial view updates - all fields optional except id."},"ViewUpdateRequest":{"properties":{"view":{"$ref":"#/components/schemas/ViewUpdateModel"},"expected_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expected Version"}},"type":"object","required":["view"],"title":"ViewUpdateRequest","description":"Request model for updating a single view with partial updates.\n\nAttributes:\n    view: Partial view data with only the fields to update\n    expected_version: The view ``version`` the client's edit is based on.\n        When set, the write is compare-and-set: a stale base raises 409\n        instead of silently overwriting a newer same-view edit."},"ViewUpdateResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"view":{"$ref":"#/components/schemas/ViewModel-Output"}},"type":"object","required":["success","view"],"title":"ViewUpdateResponse","description":"Response model for updating a single view.\n\nAttributes:\n    success: Boolean indicating if the update was successful\n    view: The updated view model"},"ViewsGetResponse":{"properties":{"views":{"items":{"$ref":"#/components/schemas/ViewModel-Output"},"type":"array","title":"Views"}},"type":"object","required":["views"],"title":"ViewsGetResponse","description":"Response model for getting project views.\n\nAttributes:\n    views: List of view models"},"ViewsReorderRequest":{"properties":{"view_ids":{"items":{"type":"string"},"type":"array","title":"View Ids"}},"type":"object","required":["view_ids"],"title":"ViewsReorderRequest","description":"Request model for reordering a project's views.\n\nAttributes:\n    view_ids: The full ordered list of view ids; must be an exact\n        permutation of the project's current view ids."},"ViewsReorderResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"views":{"items":{"$ref":"#/components/schemas/ViewModel-Output"},"type":"array","title":"Views"}},"type":"object","required":["success","views"],"title":"ViewsReorderResponse","description":"Response model for reordering a project's views.\n\nAttributes:\n    success: Boolean indicating if the reorder was successful\n    views: The views in their new order"},"VizCategory":{"properties":{"value":{"type":"string","title":"Value"},"label":{"type":"string","title":"Label"},"count":{"type":"integer","title":"Count"},"color_index":{"type":"integer","title":"Color Index"}},"type":"object","required":["value","label","count","color_index"],"title":"VizCategory","description":"One class of a categorical map visualization.\n\n``value`` is the column's ``::text`` serialization, which is the domain a\ntile property lands in after Mapbox ``to-string`` — the paint expression's\n``match`` arms compare against it directly, so the two sides must agree.\n``label`` is user-facing (\"Yes\"/\"No\" for boolean). ``color_index`` is a\npalette slot keyed on the category value rather than its rank, so a\ncategory keeps its hue while counts shuffle underneath it (an enrichment\nfilling in reorders the ranking continuously)."},"WaitlistEntryResponse":{"properties":{"account_id":{"type":"string","format":"uuid","title":"Account Id"},"email":{"type":"string","title":"Email"},"waiting_since":{"type":"string","format":"date-time","title":"Waiting Since"}},"type":"object","required":["account_id","email","waiting_since"],"title":"WaitlistEntryResponse"},"WaitlistPageResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/WaitlistEntryResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"offset":{"type":"integer","title":"Offset"}},"type":"object","required":["items","total","limit","offset"],"title":"WaitlistPageResponse"},"WaitlistSort":{"type":"string","enum":["longest_wait","newest","email"],"title":"WaitlistSort","description":"How an operator wants the waitlist ordered.\n\nA closed vocabulary rather than a column name from the caller: the sort\nreaches an ORDER BY, so accepting free text would let the wire choose what\nthe database sorts on."},"WorkspaceCountyLoadStatus":{"type":"string","enum":["provisioning","pending","loading","succeeded","failed","canceled","inherited"],"title":"WorkspaceCountyLoadStatus","description":"Load status for a workspace-county pair.\n\nLifecycle: ``provisioning`` (initial — set by workspace standup before the\nNeon project is ready) → ``pending`` (set by ``provision_workspace_op``\nafter schema apply succeeds; the pickup sensor's gate value) →\n``loading`` (set by ``sandbox_load`` when it starts writing for one\ncounty) → ``succeeded`` | ``failed`` (terminal, set by the asset's\ntry/finally). ``provisioning`` and the mid-load ``loading`` were\npreviously the same value; MAIA-2309 split them so the lifecycle reads\nliterally instead of overloading ``loading`` across two phases.\n\n``canceled`` is the admin-initiated terminal state: an in-flight\n(pending/loading) row canceled before the load finished. The Dagster\nstamps are status-guarded so a canceled row is never resurrected by a\nrun that was already queued; retry via the reload seam re-queues it.\n\n``inherited`` sits outside that lifecycle: the county's data arrived with\nthe workspace's Neon branch and no load ever ran for this workspace. A\nself-serve workspace is a copy-on-write fork of a prepared parent, so its\ncounties are queryable the moment the branch exists. The distinction from\n``succeeded`` is what a future refresh needs — re-forking from a refreshed\nparent carries inherited counties for free and drops separately loaded\nones, and without the distinction a refresh either reloads everything or\nsilently loses the one-offs.\n\nA producer writing this status should stamp ``data_loaded_at`` with the\nfork time in the same statement. Access does not depend on it — the reload\nseam backstops a missing value with ``now()``, so an unstamped inherited row\nkeeps its access through a refresh — but the backstop records when someone\nfirst refreshed the county rather than when its data actually arrived, and\nthat column is what a later refresh reads to tell inherited data from data\nloaded afterwards."},"WorkspaceCountyResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"workspace_id":{"type":"string","format":"uuid","title":"Workspace Id"},"state":{"type":"string","title":"State"},"county_fips":{"type":"string","title":"County Fips"},"county_name":{"type":"string","title":"County Name"},"load_status":{"$ref":"#/components/schemas/WorkspaceCountyLoadStatus"},"dagster_run_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dagster Run Id"},"requested_at":{"type":"string","format":"date-time","title":"Requested At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"suspended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Suspended At"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"}},"type":"object","required":["id","workspace_id","state","county_fips","county_name","load_status","dagster_run_id","requested_at","completed_at","suspended_at","error_message"],"title":"WorkspaceCountyResponse","description":"A workspace's per-county sandbox-load state.\n\n``county_name`` is the TIGER LSAD form (e.g. ``\"Los Angeles County\"``);\nsourced from ``tiger_county.name`` via\n``WorkspaceCountyRepository.get_loaded_fips_to_name_map`` at the endpoint\nlayer (the domain ``WorkspaceCounty`` doesn't carry the name)."},"WorkspaceCountySelection":{"properties":{"state_fips":{"type":"string","maxLength":2,"minLength":2,"pattern":"^\\d{2}$","title":"State Fips"},"county_fips":{"type":"string","maxLength":3,"minLength":3,"pattern":"^\\d{3}$","title":"County Fips"}},"additionalProperties":false,"type":"object","required":["state_fips","county_fips"],"title":"WorkspaceCountySelection","description":"One county selection — FIPS-shape only.\n\nUsed by the append-county and workspace-provisioning request bodies.\nCallers supply ``state_fips`` (2-digit) + ``county_fips`` (3-digit) only.\n``extra=\"forbid\"`` rejects callers still constructing slug-shape kwargs\nwith 422 rather than silently dropping the slug pair.\n\nThe handler resolves the FIPS pair to a USPS state code before calling\nthe service (the ``workspace_counties.state`` column is USPS, not\nnumeric FIPS)."},"WorkspaceMemberResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"email":{"type":"string","title":"Email"},"workspace_role":{"$ref":"#/components/schemas/WorkspaceRole"},"is_workspace_admin":{"type":"boolean","title":"Is Workspace Admin"},"avatar_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Color"},"used_enrichment_credits":{"type":"integer","title":"Used Enrichment Credits","default":0},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"last_active_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Active At"}},"type":"object","required":["id","email","workspace_role","is_workspace_admin"],"title":"WorkspaceMemberResponse","description":"Response model for a workspace member."},"WorkspaceMembersResponse":{"properties":{"members":{"items":{"$ref":"#/components/schemas/WorkspaceMemberResponse"},"type":"array","title":"Members"}},"type":"object","required":["members"],"title":"WorkspaceMembersResponse","description":"Response model for listing workspace members."},"WorkspaceResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"avatar_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Color"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"budget_authority":{"$ref":"#/components/schemas/BudgetAuthority"},"credit_balance":{"anyOf":[{"$ref":"#/components/schemas/CreditBalance"},{"type":"null"}]},"member_count":{"type":"integer","title":"Member Count"},"dial_agent_settings":{"anyOf":[{"$ref":"#/components/schemas/DialAgentSettings"},{"type":"null"}]},"auto_dial_enabled":{"type":"boolean","title":"Auto Dial Enabled","default":false},"feature_toggles":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Feature Toggles","default":{}},"workspace_type":{"$ref":"#/components/schemas/WorkspaceType"},"discovery_allowance":{"anyOf":[{"$ref":"#/components/schemas/DiscoveryAllowanceCustomerProjection"},{"type":"null"}]}},"type":"object","required":["id","name","budget_authority","credit_balance","member_count","workspace_type"],"title":"WorkspaceResponse","description":"Response model for workspace details."},"WorkspaceRole":{"type":"string","enum":["writer","reader"],"title":"WorkspaceRole","description":"Role within a workspace determining permission level.\n\nWRITER = can edit workspace_write projects\nREADER = can only view workspace projects"},"WorkspaceType":{"type":"string","enum":["standard","discovery"],"title":"WorkspaceType"},"WorkspaceUpdateRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name","description":"New name for the workspace"},"avatar_color":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Avatar Color","description":"Avatar color name for the workspace. Set to null to remove."}},"type":"object","title":"WorkspaceUpdateRequest","description":"Request model for updating workspace settings.\n\nAll fields are optional -- only provided fields are updated."}},"securitySchemes":{"FirebaseAuthMiddleware":{"type":"http","scheme":"bearer"}}}}