{"components":{"parameters":{"AlertId":{"description":"The alert id, as returned in the `id` field of an alert.","in":"path","name":"alert_id","required":true,"schema":{"format":"uuid","type":"string"}},"DataSubscriptionId":{"description":"The data product id, as returned in the `id` field of a data subscription.","in":"path","name":"data_subscription_id","required":true,"schema":{"format":"uuid","type":"string"}},"DocketId":{"description":"The docket id, as returned in the `id` field of a docket search result.","in":"path","name":"docket_id","required":true,"schema":{"format":"uuid","type":"string"}},"DocketNameQuery":{"description":"The publisher's own name for the docket, which for docket-shaped types is its number, e.g. `R.20-05-003`. This is `Docket.name`, not `Docket.id`. Case and punctuation are ignored when matching.\n","in":"query","name":"name","required":true,"schema":{"minLength":1,"type":"string"}},"DocumentId":{"description":"The document id, as returned in the `id` field of a search result or citation.","in":"path","name":"document_id","required":true,"schema":{"format":"uuid","type":"string"}},"Expand":{"description":"Comma-separated list of extra fields to include. Supported values: `summary`.\n","in":"query","name":"expand","required":false,"schema":{"type":"string"}},"NotificationId":{"description":"The notification id, as returned in the `id` field of an alert notification.","in":"path","name":"notification_id","required":true,"schema":{"format":"uuid","type":"string"}},"PublisherIdFilter":{"description":"Narrow `publisher_filing_types` to one publisher. The normalized `items` are cross-publisher and are returned in full either way.\n","in":"query","name":"publisher_id","required":false,"schema":{"type":"string"}},"PublisherRefQuery":{"description":"A publisher id, as returned in the `id` field of `GET /publishers`. Publisher names are not accepted here; resolve one to its id against `GET /publishers` first.\n","in":"query","name":"publisher","required":true,"schema":{"pattern":"^[1-9][0-9]*$","type":"string"}},"QueryId":{"in":"path","name":"query_id","required":true,"schema":{"format":"uuid","type":"string"}}},"schemas":{"Alert":{"allOf":[{"$ref":"#/components/schemas/AlertSummary"},{"additionalProperties":false,"properties":{"query_id":{"description":"The stored query the alert re-runs. Read its question and constraints with `GET /queries/{query_id}`. Each run records its own queries, which are a notification's `queries`.\n","format":"uuid","type":"string"},"schedule":{"allOf":[{"$ref":"#/components/schemas/AlertSchedule"}],"description":"How often the alert runs."}},"required":["schedule","query_id"],"type":"object"}]},"AlertListResponse":{"additionalProperties":false,"properties":{"items":{"description":"The caller's alerts, most recently created first.","items":{"$ref":"#/components/schemas/AlertSummary"},"type":"array"}},"required":["items"],"type":"object"},"AlertNotification":{"additionalProperties":false,"properties":{"alert_id":{"description":"The alert that delivered this notification. Pass it as `alert_id` to `GET /alerts/{alert_id}`.\n","format":"uuid","type":"string"},"created_at":{"description":"When the alert delivered this notification.","format":"date-time","type":"string"},"document_ids":{"description":"The documents this delivery's queries found, deduplicated across them, newest query first. A rollup of the same ids on `queries`, for callers that only want to know what turned up. Fetch them with `POST /documents`. A query still waiting on its response contributes nothing, so read `queries` to tell an empty result from an unfinished run.\n","items":{"format":"uuid","type":"string"},"type":"array"},"id":{"description":"This notification's own id; the `alert_id` beside it is the alert that delivered it. Pass this to `GET /alerts/notifications/{notification_id}`.\n","format":"uuid","type":"string"},"queries":{"description":"The queries this run created, newest first, each with what it answered. Every query the run created is listed, answered or not, so a notification is readable without fetching anything else. Each run makes its own queries, distinct from the alert's stored `query_id`.\n","items":{"$ref":"#/components/schemas/AlertNotificationQuery"},"type":"array"}},"required":["id","alert_id","created_at","queries","document_ids"],"type":"object"},"AlertNotificationListResponse":{"additionalProperties":false,"properties":{"items":{"description":"The alert's most recent notifications, newest first.","items":{"$ref":"#/components/schemas/AlertNotification"},"type":"array"}},"required":["items"],"type":"object"},"AlertNotificationPageResponse":{"additionalProperties":false,"properties":{"items":{"description":"The caller's notifications, newest first.","items":{"$ref":"#/components/schemas/AlertNotification"},"type":"array"},"next_page":{"description":"Pass as `page` for the next page, or null when this is the last one. `limit` and `exclude_empty` are read from each request, so repeat them to keep a walk consistent.\n","minimum":1,"nullable":true,"type":"integer"},"prev_page":{"description":"Pass as `page` for the previous page, or null when at the start of the feed.\n","minimum":1,"nullable":true,"type":"integer"}},"required":["items"],"type":"object"},"AlertNotificationQuery":{"additionalProperties":false,"properties":{"query_id":{"description":"One query this run created. Read its question and constraints with `GET /queries/{query_id}`.\n","format":"uuid","type":"string"},"response":{"allOf":[{"$ref":"#/components/schemas/QueryResponse"}],"description":"What this query answered, in the same shape `GET /queries/{query_id}/response` returns, or null when it has no stored response yet. Null means the run has not finished this query; a response with `status: NO_RESULTS` means it finished and matched nothing. Read the prose by concatenating the `LiteralText` components.\n","nullable":true}},"required":["query_id","response"],"type":"object"},"AlertSchedule":{"description":"How often the alert runs. `DAILY` runs every day, `WEEKDAYS` Monday through Friday, and each remaining value runs once a week on that day.\n","enum":["DAILY","WEEKDAYS","MONDAYS","TUESDAYS","WEDNESDAYS","THURSDAYS","FRIDAYS","SATURDAYS","SUNDAYS"],"type":"string"},"AlertSummary":{"additionalProperties":false,"properties":{"created_at":{"format":"date-time","type":"string"},"enabled":{"description":"Whether the alert emails on its schedule. A disabled alert still records notifications, and they still appear in the notification listings; it stops emailing them, not running.\n","type":"boolean"},"id":{"format":"uuid","type":"string"},"name":{"description":"The alert's name, also the subject line of its notification emails.","minLength":1,"type":"string"},"send_alert_on_no_new_documents":{"description":"Whether a run that found no new documents still emails. The notification is recorded either way; this only controls the email. It also exempts the alert from `exclude_empty` on the notification listings.\n","type":"boolean"}},"required":["id","name","enabled","send_alert_on_no_new_documents","created_at"],"type":"object"},"Citation":{"additionalProperties":false,"description":"A source reference sitting at the point in the text it annotates.\n","properties":{"component_type":{"enum":["CITATION"],"type":"string"},"document_id":{"description":"The cited document; resolve to metadata via `POST /documents`.","format":"uuid","type":"string"},"page_numbers":{"$ref":"#/components/schemas/PageRange","nullable":true}},"required":["document_id","component_type"],"type":"object"},"CreateQueryRequest":{"additionalProperties":false,"properties":{"constraints":{"$ref":"#/components/schemas/SearchConstraintsExpr","description":"Required, and must narrow the query: every constraint set in the expression needs at least one non-empty field (e.g. `docket_ids`, `publisher_ids`, etc.).  Queries over the whole corpus are not supported, so `{}` is rejected with a 400.  If the question names dockets, resolve them with `POST /search/dockets` and pass their ids in `docket_ids`. Prefer the narrowest constraint set that still contains the answer. Accuracy degrades once the matched set grows large, because the run reads a bounded, ranked selection rather than every match (see `runQuery`). Size the set first with `POST /search/documents` using the same constraints and read `approximate_total_count`.\n"},"question":{"description":"The natural-language question to answer over the constrained documents.","minLength":1,"type":"string"},"reference_time":{"description":"The reference time used as \"today\" when interpreting the question (e.g. \"last quarter\"). Defaults to the query's creation time when omitted.\n","format":"date-time","nullable":true,"type":"string"},"response_schema":{"additionalProperties":true,"description":"JSON Schema describing the desired structured output; running the query returns `structured_output` conforming to it. To attach source citations to any object in your schema, add a property named `citations` to that object: the run populates it with an array of `{ document_id, page_numbers }` objects, where `document_id` resolves to document metadata via `POST /documents`.\n","type":"object"},"sort":{"$ref":"#/components/schemas/SearchSortType"},"target":{"$ref":"#/components/schemas/QueryTarget"}},"required":["question","constraints"],"type":"object"},"DataProductStatus":{"description":"The data product's publication lifecycle status.","enum":["PUBLISHED","UNPUBLISHED","DISCONTINUED"],"type":"string"},"DataSubscription":{"additionalProperties":false,"properties":{"description":{"nullable":true,"type":"string"},"id":{"description":"The data product this subscription refers to.","format":"uuid","type":"string"},"is_subscribed":{"description":"Whether this account can access the product's data. Only subscribed products can be downloaded.\n","type":"boolean"},"item_description":{"description":"What a single item in this product represents (e.g. \"filing\").","type":"string"},"item_plural_description":{"type":"string"},"latest_release":{"allOf":[{"$ref":"#/components/schemas/DataSubscriptionRelease"}],"description":"The most recent release, or null if the product has never been released.","nullable":true},"name":{"type":"string"},"status":{"$ref":"#/components/schemas/DataProductStatus"}},"required":["id","name","status","is_subscribed","item_description","item_plural_description"],"type":"object"},"DataSubscriptionChange":{"additionalProperties":false,"properties":{"notes":{"type":"string"},"status":{"description":"Human-readable label for the kind of change (e.g. \"Added\", \"Updated\").","type":"string"},"subject":{"description":"The item this change applies to.","type":"string"}},"required":["subject","status","notes"],"type":"object"},"DataSubscriptionChangeLogResponse":{"additionalProperties":false,"properties":{"releases":{"description":"Change logs per release, newest first.","items":{"$ref":"#/components/schemas/DataSubscriptionReleaseChangeLog"},"type":"array"}},"required":["releases"],"type":"object"},"DataSubscriptionDetail":{"additionalProperties":false,"properties":{"data_subscription":{"$ref":"#/components/schemas/DataSubscription"},"release_summary":{"$ref":"#/components/schemas/DataSubscriptionReleaseSummary"}},"required":["data_subscription","release_summary"],"type":"object"},"DataSubscriptionListResponse":{"additionalProperties":false,"properties":{"items":{"items":{"$ref":"#/components/schemas/DataSubscription"},"type":"array"}},"required":["items"],"type":"object"},"DataSubscriptionRelease":{"additionalProperties":false,"properties":{"description":{"type":"string"},"id":{"format":"uuid","type":"string"},"name":{"type":"string"},"released_at":{"description":"When this release was published, as an RFC 3339 / ISO 8601 timestamp with an explicit UTC offset (e.g. `2024-06-01T00:00:00+00:00`).\n","format":"date-time","type":"string"},"total_items":{"description":"Number of items in this release.","minimum":0,"type":"integer"}},"required":["id","released_at","name","description","total_items"],"type":"object"},"DataSubscriptionReleaseChangeLog":{"additionalProperties":false,"properties":{"changes":{"items":{"$ref":"#/components/schemas/DataSubscriptionChange"},"type":"array"},"summary":{"$ref":"#/components/schemas/DataSubscriptionReleaseSummary"}},"required":["summary","changes"],"type":"object"},"DataSubscriptionReleaseSummary":{"additionalProperties":false,"properties":{"capacity_description":{"type":"string"},"items_added":{"description":"Items added since the previous release.","minimum":0,"type":"integer"},"items_removed":{"description":"Items removed since the previous release.","minimum":0,"type":"integer"},"items_updated":{"description":"Existing items updated since the previous release.","minimum":0,"type":"integer"},"long_form_description":{"nullable":true,"type":"string"},"release_id":{"format":"uuid","type":"string"},"released_at":{"description":"When this release was published, as an RFC 3339 / ISO 8601 timestamp with an explicit UTC offset (e.g. `2024-06-01T00:00:00+00:00`).\n","format":"date-time","type":"string"},"total_items":{"description":"Total number of items in this release.","minimum":0,"type":"integer"}},"required":["release_id","released_at","total_items","items_added","items_removed","items_updated","capacity_description"],"type":"object"},"Docket":{"additionalProperties":false,"description":"A proceeding, filing series or other grouping a publisher files documents under. Carries two identifiers that are easy to confuse: see \"Identifiers\" in the API description.\n","properties":{"companies":{"description":"Companies or parties named on the docket (e.g. the filing utility), where the publisher records them.\n","nullable":true,"type":"string"},"description":{"description":"The publisher's own prose description of the docket, where it publishes one.","nullable":true,"type":"string"},"docket_type":{"description":"The kind of docket (e.g. Rate Case, PUC Docket, IRP).","type":"string"},"document_count":{"description":"Number of documents in the docket.","nullable":true,"type":"integer"},"end_year":{"description":"Year the docket closed. Null for an open docket, and also when simply unrecorded.","nullable":true,"type":"integer"},"filing_date":{"anyOf":[{"format":"date-time","type":"string"},{"format":"date","type":"string"}],"description":"When the docket was filed. Passed through in whatever precision the publisher supplies, so it can be a date or a timestamp.\n","nullable":true},"id":{"description":"Halcyon's identifier for this docket, and the only one the API accepts as an id: it is what `/dockets/{docket_id}` takes and what every `docket_ids` constraint holds. It is **not** the publisher's docket number, which is `name`.\n","format":"uuid","type":"string"},"industry":{"description":"The industry or industries the docket concerns (e.g. \"Electric\", \"Gas\"), comma-separated when there are several. Not normalized across publishers.\n","nullable":true,"type":"string"},"latest_publication_date":{"description":"Publication date of the most recent document in the docket. Use it to tell active dockets from dormant ones.\n","format":"date-time","nullable":true,"type":"string"},"metadata":{"description":"Publisher-specific metadata fields, in the publisher's own order. Null doesn't imply no metadata exists; only some endpoints return metadata.\n","items":{"$ref":"#/components/schemas/DocketMetadataField"},"nullable":true,"type":"array"},"name":{"description":"The publisher's own name for this docket. For docket-shaped `docket_type`s this is the docket number as the publisher writes it, e.g. `R.20-05-003`; for others it is a facility or committee name. Unique only within a publisher and `docket_type`, so it does not identify a docket on its own. Resolve one to an `id` with `GET /dockets?publisher=&name=`.\n","minLength":1,"type":"string"},"proceeding_type":{"description":"The publisher's own classification of the proceeding (e.g. a case type or purpose code). Distinct from `docket_type`, and not normalized across publishers.\n","nullable":true,"type":"string"},"publisher":{"description":"The publisher's full name, matching `name` in `GET /publishers`. Null when upstream has no publisher recorded for the docket.\n","nullable":true,"type":"string"},"start_year":{"description":"Year the docket opened, where the publisher records one.","nullable":true,"type":"integer"},"status":{"description":"The docket's status in the publisher's own wording (e.g. \"Open\", \"CLOSED\"). Not normalized to a fixed set of values.\n","nullable":true,"type":"string"},"summary":{"description":"Present only on `GET /dockets/{docket_id}` with `expand=summary`; always null elsewhere. An ordered run of components in the same shape as `Document.summary`: `LiteralText` fragments interleaved with `Citation` markers whose `document_id`s resolve via `POST /documents`.\n","items":{"$ref":"#/components/schemas/QueryResponseComponent"},"nullable":true,"type":"array"}},"required":["id","name","docket_type"],"type":"object"},"DocketListResponse":{"additionalProperties":false,"description":"Dockets matching a publisher's own name for them. That name is unique only within a publisher and docket type, so more than one docket can share it.\n","properties":{"items":{"description":"The matching dockets, with `metadata` populated, and `document_count` and `summary` null. Empty when the publisher has no docket with this name.\n","items":{"$ref":"#/components/schemas/Docket"},"type":"array"}},"required":["items"],"type":"object"},"DocketMetadataField":{"additionalProperties":false,"description":"One publisher-specific metadata field on a docket. Which fields a docket carries depends on its publisher, so treat the set as open-ended: match on `key` rather than on position, and expect keys you don't recognize. Fields the publisher left empty are omitted entirely.\n","properties":{"key":{"description":"Machine-readable name for the field, e.g. `matter_status`.","minLength":1,"type":"string"},"label":{"description":"Human-readable name for the field, e.g. `Matter status`.","minLength":1,"type":"string"},"value":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"description":"The value: a string, or an array of strings for multi-valued fields such as parties. Dates and timestamps are ISO 8601.\n"}},"required":["key","label","value"],"type":"object"},"DocketSearchRequest":{"additionalProperties":false,"description":"Request body for docket search. Same as `SearchRequest` but without `sort`, which is not supported when searching dockets.\n","properties":{"constraints":{"$ref":"#/components/schemas/SearchConstraintsExpr"},"limit":{"default":25,"description":"Maximum number of results to return. Capped at 100; use `offset` to page.","maximum":100,"minimum":1,"type":"integer"},"offset":{"default":0,"description":"Number of results to skip. Combine with `limit` to page through matches.","minimum":0,"type":"integer"}},"required":["constraints"],"type":"object"},"DocketSearchResponse":{"additionalProperties":false,"properties":{"approximate_total_count":{"description":"Approximate total number of matches across all pages. Use it to gauge result-set size and drive paging; it is an estimate, not an exact count.\n","minimum":0,"type":"integer"},"items":{"description":"The dockets on this page. May be shorter than `page_matched_count` when a matched id could not be resolved; such ids are omitted.\n","items":{"$ref":"#/components/schemas/Docket"},"type":"array"},"next_offset":{"description":"`offset` to request the next page, or null when there are no more pages.","minimum":0,"nullable":true,"type":"integer"},"page_matched_count":{"description":"Number of search hits on this page. See `items` for why the array may be shorter.","minimum":0,"type":"integer"},"prev_offset":{"description":"`offset` to request the previous page, or null when on the first page.","minimum":0,"nullable":true,"type":"integer"}},"required":["items","approximate_total_count","page_matched_count"],"type":"object"},"Document":{"additionalProperties":false,"properties":{"app_url":{"description":"Link to the document's page in the Halcyon web app.","format":"uri","type":"string"},"docket_ids":{"description":"Halcyon docket ids (`Docket.id`), not publisher docket numbers. A document can belong to several dockets or to none, so this can be empty. Resolve one with `GET /dockets/{docket_id}`.\n","items":{"format":"uuid","type":"string"},"type":"array"},"filing_type":{"description":"The publisher's own label for this filing, e.g. `Order`. This is the raw label, so to find more documents like this one, filter on `publisher_filing_type_ids`, not `filing_type_ids`.\n","nullable":true,"type":"string"},"id":{"description":"Halcyon's identifier for this document. It is what `/documents/{document_id}` takes, what `document_ids` holds, and what a `Citation` points at.\n","format":"uuid","type":"string"},"publication_date":{"description":"When the publisher published the document. This is what `published_after` / `published_before` filter on and what the `NEWEST` and `OLDEST` sorts order by.\n","format":"date-time","nullable":true,"type":"string"},"publisher":{"description":"The publisher's full name, matching `name` in `GET /publishers`. Nullable: a document is not owned by a publisher, and some have none recorded.\n","nullable":true,"type":"string"},"summary":{"description":"Present only on `GET /documents/{document_id}` with `expand=summary`; always null elsewhere. An ordered run of components: `LiteralText` fragments interleaved with `Citation` markers. Concatenate the `LiteralText` values for plain prose; each `Citation` sits at the point in the text it annotates and carries the source `document_id` (resolve via `POST /documents`) and page range.\n","items":{"$ref":"#/components/schemas/QueryResponseComponent"},"nullable":true,"type":"array"},"title":{"description":"The document's title as published.","minLength":1,"type":"string"},"topic_names":{"description":"Names of the topics this document matches, computed per read rather than stored. Null means none matched. Topic names are unique, so to constrain a search on one, resolve it to an id with `GET /topics` and pass that as `topic_ids`.\n","items":{"minLength":1,"type":"string"},"nullable":true,"type":"array"},"total_pages":{"description":"Page count, where the source format has one. Null for formats that do not, and when it has not been extracted.\n","nullable":true,"type":"integer"},"type":{"description":"Source file type (e.g. PDF, DOCX, HTML).","type":"string"}},"required":["id","title","type","app_url"],"type":"object"},"DocumentSearchResponse":{"additionalProperties":false,"properties":{"approximate_total_count":{"description":"Approximate total number of matches across all pages. Use it to gauge result-set size and drive paging; it is an estimate, so do not rely on it as an exact count.\n","minimum":0,"type":"integer"},"items":{"description":"The hydrated documents on this page. May be shorter than `page_matched_count` when a matched id could not be resolved.\n","items":{"$ref":"#/components/schemas/Document"},"type":"array"},"next_offset":{"description":"`offset` to request the next page, or null when there are no more pages.\n","minimum":0,"nullable":true,"type":"integer"},"page_matched_count":{"description":"Number of search hits on this page (before hydration). See `items` for why the returned array may be shorter.\n","minimum":0,"type":"integer"},"prev_offset":{"description":"`offset` to request the previous page, or null when on the first page.\n","minimum":0,"nullable":true,"type":"integer"}},"required":["items","approximate_total_count","page_matched_count"],"type":"object"},"DocumentsRequest":{"additionalProperties":false,"properties":{"document_ids":{"description":"Ids to fetch. At most 100 per request.","items":{"format":"uuid","type":"string"},"maxItems":100,"minItems":1,"type":"array"}},"required":["document_ids"],"type":"object"},"FilingType":{"additionalProperties":false,"description":"A normalized, cross-publisher filing type, usable as the `filing_type_ids` constraint. Different publishers' own names for the same kind of filing collapse onto one of these.\n","properties":{"id":{"type":"string"},"name":{"minLength":1,"type":"string"}},"required":["id","name"],"type":"object"},"FilingTypesResponse":{"additionalProperties":false,"properties":{"items":{"description":"The normalized, cross-publisher filing types.","items":{"$ref":"#/components/schemas/FilingType"},"type":"array"},"publisher_filing_types":{"description":"Per-publisher filing types, narrowed to one publisher when `publisher_id` is supplied. Only types carrying at least ten documents are listed.\n","items":{"$ref":"#/components/schemas/PublisherFilingType"},"type":"array"}},"required":["items","publisher_filing_types"],"type":"object"},"LiteralText":{"additionalProperties":false,"properties":{"component_type":{"enum":["LITERAL_TEXT"],"type":"string"},"value":{"minLength":1,"type":"string"}},"required":["value","component_type"],"type":"object"},"PageRange":{"additionalProperties":false,"properties":{"end_page":{"type":"integer"},"start_page":{"type":"integer"}},"required":["start_page","end_page"],"type":"object"},"PingResponse":{"additionalProperties":false,"properties":{"account_id":{"description":"The account resolved from the API key.","format":"uuid","type":"string"},"user_id":{"description":"The user resolved from the API key.","format":"uuid","type":"string"}},"required":["account_id","user_id"],"type":"object"},"Publisher":{"additionalProperties":false,"description":"A source Halcyon collects from. Its `id` is what the `publisher_ids` constraint takes, and what the `publisher` parameter of `GET /dockets` accepts.\n","properties":{"has_dockets":{"description":"Whether this publisher organizes filings into dockets. Docket search and docket lookup return nothing for a publisher where this is false.\n","nullable":true,"type":"boolean"},"id":{"type":"string"},"name":{"description":"The publisher's full name, e.g. `California Public Utilities Commission`.","minLength":1,"type":"string"},"state":{"description":"The US state this publisher regulates, where it is state-level.","nullable":true,"type":"string"},"type":{"description":"The kind of body this is, e.g. `Utility Commission`, `RTO/ISO`, `Federal Regulator`.\n","nullable":true,"type":"string"}},"required":["id","name"],"type":"object"},"PublisherFilingType":{"additionalProperties":false,"description":"One publisher's own name for a filing type, usable as the `publisher_filing_type_ids` constraint. Ids are drawn from a different set than `FilingType` ids and the two are not interchangeable.\n","properties":{"filing_type_id":{"description":"The normalized `FilingType` this collapses onto, when it has one. Filter on this instead to match the equivalent filings across every publisher.\n","nullable":true,"type":"string"},"id":{"type":"string"},"name":{"description":"The publisher's own label, e.g. `Ruling`.","minLength":1,"type":"string"},"publisher_id":{"description":"The publisher this filing type belongs to.","type":"string"}},"required":["id","name","publisher_id"],"type":"object"},"PublishersResponse":{"additionalProperties":false,"properties":{"items":{"items":{"$ref":"#/components/schemas/Publisher"},"type":"array"}},"required":["items"],"type":"object"},"Query":{"additionalProperties":false,"properties":{"constraints":{"$ref":"#/components/schemas/SearchConstraintsExpr"},"created_at":{"description":"When the query was created. Null in the `POST /queries` response; populated once re-fetched.","format":"date-time","type":"string"},"id":{"format":"uuid","type":"string"},"question":{"minLength":1,"type":"string"},"target":{"$ref":"#/components/schemas/QueryTarget"}},"required":["id","question","constraints"],"type":"object"},"QueryListResponse":{"additionalProperties":false,"properties":{"items":{"items":{"$ref":"#/components/schemas/Query"},"type":"array"},"next_offset":{"description":"`offset` to request the next page. There is no total count, so this is set whenever the current page came back full and may still be null on the last full page (the following page turns out empty).\n","minimum":0,"nullable":true,"type":"integer"},"prev_offset":{"description":"`offset` to request the previous page, or null when on the first page.","minimum":0,"nullable":true,"type":"integer"}},"required":["items"],"type":"object"},"QueryResponse":{"additionalProperties":false,"properties":{"components":{"description":"The answer as an ordered `LiteralText` & `Citation` run, populated when the query has no `response_schema` (otherwise the answer is in `structured_output`). Null on `NO_RESULTS`.\n","items":{"$ref":"#/components/schemas/QueryResponseComponent"},"nullable":true,"type":"array"},"created_at":{"format":"date-time","nullable":true,"type":"string"},"document_ids":{"description":"The documents the run read to produce this answer, which is a superset of the ones it went on to cite. Resolve them to metadata with `POST /documents`.\n","items":{"format":"uuid","type":"string"},"type":"array"},"id":{"description":"This response's own id, identifying one run of the query. A query keeps every response it has produced: running it again with `POST /queries/{query_id}/run` stores a new response with a new id, and `GET /queries/{query_id}/response` returns the newest. Compare it to tell a response you have already read from a fresh one.\n","format":"uuid","type":"string"},"query_id":{"description":"The query this answers. Read its question and constraints with `GET /queries/{query_id}`.\n","format":"uuid","type":"string"},"status":{"$ref":"#/components/schemas/QueryStatus"},"structured_output":{"additionalProperties":true,"description":"The structured answer, conforming to the query's `response_schema`. Null on `NO_RESULTS`. Any citations are embedded within it (see `CreateQueryRequest.response_schema`).\n","nullable":true,"type":"object"}},"required":["id","query_id","status","document_ids"],"type":"object"},"QueryResponseComponent":{"description":"One element of an ordered text & citation run. Either a `LiteralText` prose fragment or a `Citation` marker, discriminated by `component_type`.\n","discriminator":{"mapping":{"CITATION":"#/components/schemas/Citation","LITERAL_TEXT":"#/components/schemas/LiteralText"},"propertyName":"component_type"},"oneOf":[{"$ref":"#/components/schemas/LiteralText"},{"$ref":"#/components/schemas/Citation"}],"type":"object"},"QueryStatus":{"description":"Outcome of the run. `NO_RESULTS` means no documents matched the query's constraints, so no output was produced and `structured_output` is null.\n","enum":["COMPLETED","NO_RESULTS"],"type":"string"},"QueryTarget":{"description":"What the query's generated constraints target. `documents` (the default) generates document-level constraints; `dockets` generates docket-level constraints.\n","enum":["documents","dockets"],"type":"string"},"SearchConstraints":{"additionalProperties":false,"description":"Flat constraints applied to a search or query. Each field is optional, but at least one must be set to a non-empty value; `{}` is not a valid constraint set. Fields combine as a conjunction (a document must satisfy every constraint present). Within a single field, the listed values combine as a disjunction. Discover valid ids via `/publishers`, `/filing-types`, `/topics`, and `/search/dockets`. To combine constraint sets with `OR` or `NOT`, nest them in a `SearchConstraintsExpr`.\n","minProperties":1,"properties":{"all_of_phrases":{"description":"Exact phrases that must all appear in a document (AND). Each entry matches a contiguous run of words, in order. Matching is case-insensitive, and punctuation and extra whitespace between words are ignored. Words are matched by stem, so regular inflections match: `\"batteries\"` and `\"battery\"` return the same set, for example.\n","items":{"minLength":1,"type":"string"},"type":"array"},"any_of_phrases":{"description":"Exact phrases where at least one must appear in a document (OR). Individual phrase matching rules are the same as `all_of_phrases`.\n","items":{"minLength":1,"type":"string"},"type":"array"},"docket_ids":{"description":"Halcyon docket ids (`Docket.id`), **not** publisher docket numbers. A docket number such as `R.20-05-003` is rejected here; resolve it to an id first with `GET /dockets?publisher=&name=`.\n","items":{"format":"uuid","type":"string"},"type":"array"},"document_ids":{"description":"Restrict the query or search to these documents. For a query run this is a filter on the candidate set, not a directive to read each listed document in full: if you list more than a run can cover, only a ranked subset informs the answer. Pass the smallest set that contains what you need.\n","items":{"format":"uuid","type":"string"},"type":"array"},"filing_type_ids":{"description":"Normalized, cross-publisher filing-type ids. Discover them in the `items` of `GET /filing-types`.\n","items":{"type":"string"},"type":"array"},"published_after":{"description":"Keep documents published at or after this instant, by `publication_date`.","format":"date-time","nullable":true,"type":"string"},"published_before":{"description":"Keep documents published at or before this instant, by `publication_date`.","format":"date-time","nullable":true,"type":"string"},"publisher_filing_type_ids":{"description":"Ids of one publisher's own filing types, matching that publisher's label exactly rather than its normalized equivalent across publishers. Discover them in the `publisher_filing_types` of `GET /filing-types`. These ids are not interchangeable with `filing_type_ids`.\n","items":{"type":"string"},"type":"array"},"publisher_ids":{"description":"Publisher ids, as returned in the `id` field of `GET /publishers`.","items":{"type":"string"},"type":"array"},"topic_ids":{"description":"Topic ids, as returned in the `id` field of `GET /topics`.","items":{"type":"string"},"type":"array"}},"type":"object"},"SearchConstraintsAnd":{"additionalProperties":false,"description":"Matches documents satisfying both `left` and `right`.","properties":{"expression_type":{"const":"AND","type":"string"},"left":{"$ref":"#/components/schemas/SearchConstraintsExpr"},"right":{"$ref":"#/components/schemas/SearchConstraintsExpr"}},"required":["expression_type","left","right"],"type":"object"},"SearchConstraintsExpr":{"description":"A boolean expression over constraints. A flat `SearchConstraints` object is a leaf, so the simple form `{\"publisher_ids\": [\"42\"]}` remains valid everywhere an expression is accepted. To express alternatives or exclusions, use an `AND`, `OR` or `NOT` node (identified by `expression_type`) whose operands are themselves expressions, e.g. `{\"expression_type\": \"OR\", \"left\": {\"topic_ids\": [\"7\"]}, \"right\": {\"docket_ids\": [\"...\"]}}`.\n","oneOf":[{"$ref":"#/components/schemas/SearchConstraints"},{"$ref":"#/components/schemas/SearchConstraintsAnd"},{"$ref":"#/components/schemas/SearchConstraintsOr"},{"$ref":"#/components/schemas/SearchConstraintsNot"}]},"SearchConstraintsNot":{"additionalProperties":false,"description":"Matches documents that do not satisfy `arg`.","properties":{"arg":{"$ref":"#/components/schemas/SearchConstraintsExpr"},"expression_type":{"const":"NOT","type":"string"}},"required":["expression_type","arg"],"type":"object"},"SearchConstraintsOr":{"additionalProperties":false,"description":"Matches documents satisfying either `left` or `right`.","properties":{"expression_type":{"const":"OR","type":"string"},"left":{"$ref":"#/components/schemas/SearchConstraintsExpr"},"right":{"$ref":"#/components/schemas/SearchConstraintsExpr"}},"required":["expression_type","left","right"],"type":"object"},"SearchRequest":{"additionalProperties":false,"properties":{"constraints":{"$ref":"#/components/schemas/SearchConstraintsExpr"},"limit":{"default":25,"description":"Maximum number of results to return. Capped at 100; use `offset` to page.","maximum":100,"minimum":1,"type":"integer"},"offset":{"default":0,"description":"Number of results to skip. Combine with `limit` to page through matches.","minimum":0,"type":"integer"},"sort":{"$ref":"#/components/schemas/SearchSortType"}},"required":["constraints"],"type":"object"},"SearchSortType":{"description":"Sort order for search results. Defaults to `NEWEST` when omitted.","enum":["NEWEST","OLDEST","LONGEST","SHORTEST"],"type":"string"},"Topic":{"additionalProperties":false,"properties":{"description":{"nullable":true,"type":"string"},"id":{"type":"string"},"name":{"minLength":1,"type":"string"}},"required":["id","name"],"type":"object"}},"securitySchemes":{"ApiKeyAuth":{"description":"Halcyon API key passed in the X-API-Key header.","in":"header","name":"X-API-Key","type":"apiKey"}}},"info":{"contact":{"email":"support@halcyon.io"},"description":"Public, API-key-authenticated HTTP API for external/machine clients.\nEvery request authenticates with the `X-API-Key` header (`sk_...`).\n\nInterested? [Click Here.](https://qg0yq.share.hsforms.com/2ZYumqbtnRpGtmmoKhjUkwg)\n\n**Recommended workflow**\n\n1. Discover constrainable values with `GET /publishers`, `GET /filing-types`\n   and `GET /topics`.\n2. Iterate your constraints against `POST /search/documents`, watching\n   `approximate_total_count`, until the matched set is small enough to read\n   in full.\n3. Create the query (`POST /queries`) over that narrowed set and run it\n   (`POST /queries/{query_id}/run`).\n\nA run answers from a bounded, ranked selection rather than the entire matched\nset, so narrowing until the set is small is what keeps answers complete. See\n`runQuery` for how a run selects what it reads.\n\n**Identifiers**\n\nDockets carry two identifiers, and mixing them up is the most common first\nmistake against this API.\n\n- **`Docket.id`** is Halcyon's identifier: a UUID, stable, and unique across\n  every publisher. It is the only thing the API accepts as an id. Every\n  `docket_ids` constraint, `Document.docket_ids`, and the\n  `GET /dockets/{docket_id}` path all take this.\n- **`Docket.name`** is the publisher's own name for the docket. For\n  docket-shaped types it is the docket number as the publisher writes it, such\n  as `R.20-05-003`. It is not unique on its own: two publishers can use the\n  same number, and within one publisher two docket types can share one. It is\n  never accepted as an id.\n\nIn this domain \"docket ID\" colloquially means the publisher's number, so if you\nhave a `R.20-05-003`, that is a `name`. Resolve it to a `Docket.id` with\n`GET /dockets?publisher=&name=`, then constrain on that id.\n\nDocuments have only one identifier, `Document.id` which is also a Halcyon UUID.\n\n**Versioning**\n\nEvery path starts with the version, such as `/v1`. Within a version we only\nadd endpoints, optional request fields and parameters, response fields, and\nresponse enum values, or relax validation. Ignore fields you don't recognize\nand treat every enum as open. Anything that could break an integration ships\nin a new version.\n\nWhen a new version ships, the previous one is deprecated and kept for at\nleast 30 days. Its operations are marked in these docs, and their responses\ncarry a `Deprecation` header ([RFC 9745](https://www.rfc-editor.org/rfc/rfc9745))\nwith the deprecation date and a `Sunset` header ([RFC 8594](https://www.rfc-editor.org/rfc/rfc8594))\nwith the earliest removal date. Every change is listed in the\n[changelog](/changelog).\n","title":"halcyon-public-api","version":"0.2.0"},"openapi":"3.1.0","paths":{"/alerts":{"get":{"description":"An alert is a stored query on a schedule: it re-runs, and notifies the caller when new documents match. Each entry here is a summary; fetch one with `GET /alerts/{alert_id}` for its schedule and the query behind it.\n","operationId":"listAlerts","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertListResponse"}}},"description":"The caller's alerts."}},"summary":"List the caller's alerts, most recently created first.","tags":["Alerts"]}},"/alerts/notifications":{"get":{"description":"Each notification is one delivery of an alert: the queries that ran for it, what they answered, and the documents they found. Pooled across the caller's alerts in every account they are a member of, newest first. Narrow to a single alert with `GET /alerts/{alert_id}/notifications`, or read one by id with `GET /alerts/notifications/{notification_id}`.\nWalk the feed with `page`, following the previous response's `next_page` until it comes back null. The feed is live, so a notification delivered mid-walk can shift later pages; resolve ids you care about individually rather than assuming a page is stable.\n","operationId":"listAlertNotificationsFeed","parameters":[{"description":"Which page of the feed to return, counting from 1 at the newest notification. Take it from the previous response's `next_page` or `prev_page`.\n","in":"query","name":"page","required":false,"schema":{"default":1,"minimum":1,"type":"integer"}},{"description":"Maximum number of notifications per page, newest first. Capped at 100. Every notification carries its answers, so a wide page is a large response.\n","in":"query","name":"limit","required":false,"schema":{"default":25,"maximum":100,"minimum":1,"type":"integer"}},{"description":"Drop deliveries that found no new documents. On by default: an alert records a delivery on every run, so most of them found nothing, and leaving them in means paging through answers that say so. Pass false for the complete record of every run.\nAlerts set to `send_alert_on_no_new_documents` are exempt, since their empty deliveries are the point. A delivery whose queries have not answered yet is kept too, because whether it was empty is not yet known.\n","in":"query","name":"exclude_empty","required":false,"schema":{"default":true,"type":"boolean"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertNotificationPageResponse"}}},"description":"A page of the caller's alert notifications."},"400":{"description":"The request is invalid."}},"summary":"List the caller's alert notifications, newest first.","tags":["Alerts"]}},"/alerts/notifications/{notification_id}":{"get":{"description":"Reads a single delivery by the `id` a notification listing returned. Notifications stay readable this way once the page they arrived in has moved on, so ids taken from the feed keep resolving.\nA notification carries what its queries found, here as in the listings, so this is the single-delivery read rather than a fuller one.\n","operationId":"getAlertNotification","parameters":[{"$ref":"#/components/parameters/NotificationId"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertNotification"}}},"description":"The notification."},"404":{"description":"No such notification, or it is not visible to this caller."}},"summary":"Get an alert notification by id.","tags":["Alerts"]}},"/alerts/{alert_id}":{"get":{"description":"One alert in full: everything `GET /alerts` lists, plus the schedule it runs on and the query it re-runs. For what the alert has actually delivered, read `GET /alerts/{alert_id}/notifications`.\n","operationId":"getAlert","parameters":[{"$ref":"#/components/parameters/AlertId"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Alert"}}},"description":"The alert."},"404":{"description":"No such alert, or it is not visible to this caller."}},"summary":"Get an alert by id.","tags":["Alerts"]}},"/alerts/{alert_id}/notifications":{"get":{"description":"Each notification is one delivery of the alert: the queries that ran for it, what they answered, and the documents they found. This returns the alert's most recent notifications only, up to `limit`, and is not paged. For the caller's full history, walk `GET /alerts/notifications`, which is pooled across every alert and carries the alert id on each entry.\n","operationId":"listAlertNotifications","parameters":[{"$ref":"#/components/parameters/AlertId"},{"description":"Maximum number of notifications to return, newest first. Capped at 100. Every notification carries its answers, so asking for many is a large response.\n","in":"query","name":"limit","required":false,"schema":{"default":25,"maximum":100,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertNotificationListResponse"}}},"description":"The alert's most recent notifications."},"400":{"description":"The request is invalid."},"404":{"description":"No such alert, or it is not visible to this caller."}},"summary":"List an alert's notifications, newest first.","tags":["Alerts"]}},"/data-subscriptions":{"get":{"description":"List the available data products, most recently released first. Each item carries `is_subscribed`, indicating whether this account can download it; products the account is not subscribed to are included too.\n","operationId":"listDataSubscriptions","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataSubscriptionListResponse"}}},"description":"The available data subscriptions."}},"summary":"List the account's data subscriptions, most recently released first.","tags":["Data Subscriptions"]}},"/data-subscriptions/{data_subscription_id}":{"get":{"description":"Metadata for a single data product, including a summary of its latest release.\n","operationId":"getDataSubscription","parameters":[{"$ref":"#/components/parameters/DataSubscriptionId"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataSubscriptionDetail"}}},"description":"The data subscription's metadata."},"404":{"description":"No such data product, or it has no releases yet."}},"summary":"Get a data subscription's metadata.","tags":["Data Subscriptions"]}},"/data-subscriptions/{data_subscription_id}/changelog":{"get":{"description":"The per-release change log for a data product, newest release first.","operationId":"getDataSubscriptionChangeLog","parameters":[{"$ref":"#/components/parameters/DataSubscriptionId"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DataSubscriptionChangeLogResponse"}}},"description":"The data subscription's change log."},"404":{"description":"No such data product, or it has no releases yet."}},"summary":"Get a data subscription's change log.","tags":["Data Subscriptions"]}},"/data-subscriptions/{data_subscription_id}/file":{"get":{"description":"Download the latest release of a data product as an Excel (.xlsx) file.\n","operationId":"downloadDataSubscription","parameters":[{"$ref":"#/components/parameters/DataSubscriptionId"}],"responses":{"200":{"content":{"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":{"schema":{"format":"binary","type":"string"}}},"description":"The latest release as an Excel workbook."},"404":{"description":"No such data product, or it has no releases yet."}},"summary":"Download a data subscription's latest release.","tags":["Data Subscriptions"]}},"/dockets":{"get":{"description":"Resolves a publisher's own name for a docket to the dockets carrying it. For docket-shaped types this is the docket number, e.g. `R.20-05-003`. Matching ignores case and punctuation, so `R.20-05-003`, `r 20 05 003` and `R2005003` are equivalent.\n\n`name` here is the same value as `Docket.name` on the way back, **not** the Halcyon `Docket.id`. See \"Identifiers\" above.\n\n`publisher` and `name` are both required today: this is identity resolution, not a constraint-based search. For that, use `POST /search/dockets`.\n\nA name is only unique within a publisher *and* docket type, so this returns a list: expect zero, one, or occasionally several dockets that differ by `docket_type`. An unknown name, or an unknown publisher id, is an empty `items`, not a 404.\n\n`document_count` and `summary` are not populated here. Fetch a returned `id` via `GET /dockets/{docket_id}` for them.\n","operationId":"listDockets","parameters":[{"$ref":"#/components/parameters/PublisherRefQuery"},{"$ref":"#/components/parameters/DocketNameQuery"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocketListResponse"}}},"description":"The dockets carrying this name, possibly none."},"400":{"description":"`name` is missing or empty, or `publisher` is missing or is not a publisher id."}},"summary":"List dockets by the publisher's own name for them.","tags":["Dockets"]}},"/dockets/{docket_id}":{"get":{"description":"Metadata for a single docket. Add `expand=summary` for an AI-generated summary of the docket, which is generated on demand and so is markedly slower; as with documents, it is offered here, one docket at a time, rather than on the search endpoints.\n","operationId":"getDocket","parameters":[{"$ref":"#/components/parameters/DocketId"},{"$ref":"#/components/parameters/Expand"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Docket"}}},"description":"The docket's metadata."},"404":{"description":"No such docket, or it is not visible to this account."}},"summary":"Fetch a docket's metadata by id.","tags":["Dockets"]}},"/documents":{"post":{"description":"Batch-fetch documents by id. Backs lookups of known ids and resolution of the document ids returned in query responses and alert notifications. For a single document, or for a summary, use `GET /documents/{document_id}`.\n\nAll or nothing: if any requested id does not resolve, the whole request is a 404 rather than a short `documents` array. A document you cannot see and a document that does not exist are deliberately indistinguishable, so a partial response is not offered. Duplicate ids collapse to one document.\n","operationId":"getDocuments","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentsRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"documents":{"items":{"$ref":"#/components/schemas/Document"},"type":"array"}},"required":["documents"],"type":"object"}}},"description":"The requested documents."},"400":{"description":"`document_ids` is missing, empty, not a list of UUIDs, or longer than 100."},"404":{"description":"At least one requested id does not exist, or is not visible to this account."}},"summary":"Fetch document metadata by id.","tags":["Documents"]}},"/documents/{document_id}":{"get":{"description":"Metadata for a single document. Add `expand=summary` for an AI-generated summary, which is generated on demand and so is markedly slower; it is offered here, one document at a time, rather than on the batch endpoints.\n","operationId":"getDocument","parameters":[{"$ref":"#/components/parameters/DocumentId"},{"$ref":"#/components/parameters/Expand"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Document"}}},"description":"The document's metadata."},"404":{"description":"No such document, or it is not visible to this account."}},"summary":"Fetch one document's metadata by id.","tags":["Documents"]}},"/filing-types":{"get":{"description":"Returns two sets. `items` holds normalized filing types, which span publishers and back the `filing_type_ids` constraint. `publisher_filing_types` holds each publisher's own labels, which back `publisher_filing_type_ids` and carry the normalized id they collapse onto.\n\nThe two id sets are drawn from different sequences and are not interchangeable: an id from one will not do the right thing in the other's constraint.\n","operationId":"listFilingTypes","parameters":[{"$ref":"#/components/parameters/PublisherIdFilter"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FilingTypesResponse"}}},"description":"The available filing types."}},"summary":"List filing types, normalized and per-publisher.","tags":["Constraints"]}},"/ping":{"post":{"description":"Present the `X-API-Key` and, if it is valid, the resolved account and user are echoed back. Use this to confirm a key works before making real calls.\n","operationId":"ping","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PingResponse"}}},"description":"The key is valid; the caller's resolved identity."},"403":{"description":"The API key is missing, malformed, unknown, disabled, or expired."}},"summary":"Verify an API key and return the caller's resolved identity.","tags":["Identity"]}},"/publishers":{"get":{"description":"Every publisher, with the id the `publisher_ids` constraint takes. `has_dockets` tells you whether docket search and docket lookup can return anything for it.\n","operationId":"listPublishers","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishersResponse"}}},"description":"The available publishers."}},"summary":"List the publishers Halcyon collects from.","tags":["Constraints"]}},"/queries":{"get":{"description":"Returns the account's queries in reverse-chronological order. Page with `limit` and `offset`; `next_offset` is set while more may remain.\n","operationId":"listQueries","parameters":[{"description":"Maximum number of queries to return. Capped at 100; use `offset` to page.","in":"query","name":"limit","required":false,"schema":{"default":25,"maximum":100,"minimum":1,"type":"integer"}},{"in":"query","name":"offset","required":false,"schema":{"default":0,"minimum":0,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryListResponse"}}},"description":"A page of stored queries."}},"summary":"List the caller's stored queries, newest first.","tags":["Query"]},"post":{"description":"Stores the query; it does not run it. Execute it with `POST /queries/{query_id}/run`. The response echoes the created query; `created_at` is null here and is populated once you re-fetch the query. `constraints` must narrow the query: a query over the whole corpus is not supported, and a request with an empty constraint set is rejected with a 400.\n","operationId":"createQuery","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateQueryRequest"}}},"required":true},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Query"}}},"description":"The created query."},"400":{"description":"The request or its constraints are invalid, including when any constraint set (a flat leaf, or any operand of `AND`, `OR` or `NOT`) has an empty field.\n"}},"summary":"Create a stored query from a question and constraints.","tags":["Query"]}},"/queries/{query_id}":{"delete":{"description":"Permanently deletes the query.","operationId":"deleteQuery","parameters":[{"$ref":"#/components/parameters/QueryId"}],"responses":{"204":{"description":"The query was deleted."},"404":{"description":"No such query."}},"summary":"Delete a stored query.","tags":["Query"]},"get":{"operationId":"getQuery","parameters":[{"$ref":"#/components/parameters/QueryId"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Query"}}},"description":"The query."},"404":{"description":"No such query."}},"summary":"Fetch a stored query.","tags":["Query"]}},"/queries/{query_id}/response":{"get":{"description":"Returns the query's latest response: `structured_output` if the query has a `response_schema`, otherwise the `components` run. Any citation `document_id`s (embedded in `structured_output`, or as `Citation` components) resolve to document metadata via `POST /documents`.\n","operationId":"getLatestQueryResponse","parameters":[{"$ref":"#/components/parameters/QueryId"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryResponse"}}},"description":"The latest response for the query."},"404":{"description":"No such query, or it has no response yet."}},"summary":"Get the most recent response for a query.","tags":["Query"]}},"/queries/{query_id}/run":{"post":{"description":"A single call runs the query and returns the fully-populated response. If the query has a `response_schema`, the answer is in `structured_output` conforming to it; otherwise it is in `components`, an ordered `LiteralText` & `Citation`. Exactly one of the two is populated (or neither, with `status: NO_RESULTS`, if nothing matched).\n\nWhen the matched set is large, a run answers from a bounded, ranked selection of it rather than every match, so coverage can be partial with no error and no signal in the response. For best accuracy, narrow `constraints` until the matched set is small (preview its size with `POST /search/documents` and `approximate_total_count`), or split a broad question into several queries over disjoint slices and combine their responses.\n","operationId":"runQuery","parameters":[{"$ref":"#/components/parameters/QueryId"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryResponse"}}},"description":"The query response."},"404":{"description":"No such query."}},"summary":"Execute a query and return its response.","tags":["Query"]}},"/search/dockets":{"post":{"description":"The same search as `POST /search/documents`, rolled up to dockets: it takes the identical constraint set and matches on document content, then returns the dockets those documents belong to. It does not match on docket names or numbers. To go from a publisher's own docket name or number to a docket, use `GET /dockets`.\n","operationId":"searchDockets","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocketSearchRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocketSearchResponse"}}},"description":"A page of matching dockets."},"400":{"description":"The request or its constraints are invalid."}},"summary":"Search dockets by constraints.","tags":["Search"]}},"/search/documents":{"post":{"description":"Runs a constraint-based search and returns matching documents with their resolved metadata (title, publisher, publication date, filing type, etc.). Summaries are per-document and are read one at a time via `GET /documents/{document_id}`.\n\n`POST /search/dockets` runs the same constraints and rolls the same matches up to the dockets containing them.\n","operationId":"searchDocuments","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}},"required":true},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentSearchResponse"}}},"description":"A page of matching documents."},"400":{"description":"The request or its constraints are invalid."}},"summary":"Search documents by constraints and return their metadata.","tags":["Search"]}},"/topics":{"get":{"operationId":"listTopics","responses":{"200":{"content":{"application/json":{"schema":{"additionalProperties":false,"properties":{"topics":{"items":{"$ref":"#/components/schemas/Topic"},"type":"array"}},"required":["topics"],"type":"object"}}},"description":"Available topics."}},"summary":"List topics available as the `topic_ids` search constraint.","tags":["Constraints"]}}},"security":[{"ApiKeyAuth":[]}],"servers":[{"description":"Halcyon Public API","url":"https://api.halcyon.io/v1"}],"tags":[{"description":"Verify an API key and resolve the caller.","name":"Identity"},{"description":"Discover the values you can constrain a search or query on (publishers, filing types, topics).","name":"Constraints"},{"description":"Run a constraint set and get back the matches, as documents or as the dockets containing them.","name":"Search"},{"description":"Create and execute questions answered over a constrained set of documents, and read their responses.","name":"Query"},{"description":"Resolve a publisher's own docket name or number, and fetch docket metadata by id.","name":"Dockets"},{"description":"Fetch document metadata by id, one at a time or in a batch.","name":"Documents"},{"description":"Read the scheduled alerts the caller subscribes to, and the notifications they have delivered.","name":"Alerts"},{"description":"List the data products this account is subscribed to.","name":"Data Subscriptions"}]}
