{"openapi":"3.1.0","info":{"title":"Apartment Fax Developer API","description":"The supported public integration routes use a major version in the URL, currently `/v1`. Backward-compatible additions stay within that version; breaking changes use a new `/vN` prefix. Before Apartment Fax retires a version, it will publish at least 180 days of notice in the OpenAPI description, developer page, and llms.txt. Deprecated version responses will include `Deprecation` and `Sunset` headers. No v1 retirement is scheduled. Quota-managed REST responses include RateLimit-Policy, RateLimit, RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset. A 429 response also includes Retry-After.","version":"1.0.0"},"paths":{"/v1/addresses/resolve":{"post":{"tags":["Public API"],"summary":"Resolve Guest Address","operationId":"resolve_guest_address_v1_addresses_resolve_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressResolveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Resolve Guest Address V1 Addresses Resolve Post"}}},"headers":{"Deprecation":{"description":"Present only after this API version is formally deprecated. The value is the RFC 9745 Structured Field date when the deprecation was announced.","schema":{"type":"string","pattern":"^@[0-9]+$"}},"Sunset":{"description":"Present only after retirement is scheduled. The RFC 8594 HTTP-date is at least 180 days after Apartment Fax publishes the retirement notice.","schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/guest/resolve":{"post":{"summary":"Resolve Guest Address","operationId":"resolve_guest_address_api_guest_resolve_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddressResolveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Resolve Guest Address Api Guest Resolve Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/guest/checkout":{"post":{"summary":"Create Guest Checkout","operationId":"create_guest_checkout_api_guest_checkout_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestCheckoutRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Guest Checkout Api Guest Checkout Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/guest/checkout/embedded":{"post":{"summary":"Create Guest Embedded Checkout","operationId":"create_guest_embedded_checkout_api_guest_checkout_embedded_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestCheckoutRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Guest Embedded Checkout Api Guest Checkout Embedded Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/guest/order/{order_id}/email":{"post":{"summary":"Capture Guest Email","operationId":"capture_guest_email_api_guest_order__order_id__email_post","parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestEmailCaptureRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"boolean"},"title":"Response Capture Guest Email Api Guest Order  Order Id  Email Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/guest/order/{order_id}":{"get":{"summary":"Get Guest Order","operationId":"get_guest_order_api_guest_order__order_id__get","parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Guest Order Api Guest Order  Order Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/guest/order/{order_id}/pdf":{"get":{"summary":"Get Guest Order Pdf","operationId":"get_guest_order_pdf_api_guest_order__order_id__pdf_get","parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","title":"Order Id"}},{"name":"token","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"}},{"name":"download","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Download"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/report":{"post":{"summary":"Create Report","description":"Start a compile. Costs the caller one report.\n\nThis route took no ``authorization`` at all until 2026-08-08 and never asked who was\ncalling, so anyone could compile without limit at our cost and attribute the result to\nany account. Order matters below: everything that can turn a request away for *our*\nreasons happens before the debit, so a rejected request never costs a credit.","operationId":"create_report_api_report_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportRequest"}}}},"responses":{"202":{"description":"Report compile accepted. Poll the URL in the Location header or statusUrl until status is done or error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedReportJob"}}},"headers":{"Location":{"description":"Relative URL of the report job resource to poll.","schema":{"type":"string","example":"/api/report/{job_id}"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/balance":{"get":{"summary":"Get Balance","description":"Reports this account has left, for the header to show.","operationId":"get_balance_api_balance_get","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Balance Api Balance Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/report/{job_id}":{"get":{"summary":"Get Report","operationId":"get_report_api_report__job_id__get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Report Api Report  Job Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/report/{job_id}/pdf":{"get":{"summary":"Get Report Pdf","operationId":"get_report_pdf_api_report__job_id__pdf_get","parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"download","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Download"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/reports":{"get":{"summary":"List Reports","description":"This account's reports. Unlike the per-id routes there is no unowned case to fall\nback on, so an unverified caller gets nothing rather than everything.\n\nThe dashboard draws itself entirely from this, so a row has to carry everything a row\nshows. It used to fetch each report's whole body to find the score; now the listing\nbrings it, and the live job table is overlaid on top for the two things a stored row\ncannot know: that a compile is still running rather than interrupted, and the result of\none that finished moments ago and has not been read back yet.","operationId":"list_reports_api_reports_get","parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque `nextCursor` value returned by the previous page.","title":"Cursor"},"description":"Opaque `nextCursor` value returned by the previous page."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Maximum collection items to return.","default":50,"title":"Limit"},"description":"Maximum collection items to return."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/api-accounts":{"post":{"summary":"Create Api Account","description":"Open an API account. It starts empty; credits are bought for it separately.\n\nThe retry key is accepted and unused because there is nothing for it to do: a name is\nunique per owner, so creating \"production\" twice returns the first account rather than\na second one, and a retried request is the same request.","operationId":"create_api_account_api_api_accounts_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiAccountRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Api Account Api Api Accounts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"List Api Accounts","description":"This user's API accounts, each with its balance and its keys.","operationId":"list_api_accounts_api_api_accounts_get","parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque `nextCursor` value returned by the previous page.","title":"Cursor"},"description":"Opaque `nextCursor` value returned by the previous page."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Maximum collection items to return.","default":50,"title":"Limit"},"description":"Maximum collection items to return."},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiAccountListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/api-accounts/{account_id}/keys":{"post":{"summary":"Create Api Key","description":"Issue a key for an account.\n\n``secret`` is in this response and in no other, ever. Only its hash is stored, so a\ncaller who loses it revokes the key and makes another one; there is nothing here that\ncan hand it back.\n\nThat is also the whole shape of the retry key here. Sending one makes the key's id\nstable, so a retry after a lost response cannot leave a second live credential behind;\nit returns the key that was made with ``secret`` null, which says plainly that the\nsecret is gone and the key should be revoked and reissued.","operationId":"create_api_key_api_api_accounts__account_id__keys_post","parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"string","title":"Account Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Api Key Api Api Accounts  Account Id  Keys Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/api-keys/{key_id}":{"delete":{"summary":"Revoke Api Key","description":"Turn a key off. Takes effect on its next request, not eventually.","operationId":"revoke_api_key_api_api_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","title":"Key Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Api Key Api Api Keys  Key Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/previews/batch":{"post":{"tags":["Public API"],"summary":"Get multiple public previews","description":"Accepts an array of 1 to 25 public preview lookup operations and returns one result per operation in request order. Each result is the same free, read-only preview available from GET /v1/previews/{slug}; this endpoint cannot access paid reports or customer data.","operationId":"preview_batch_v1_previews_batch_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PreviewBatchOperation"},"minItems":1,"maxItems":25,"description":"Public preview lookup operations to execute in one request.","title":"Operations"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PreviewBatchResult"},"title":"Response Preview Batch V1 Previews Batch Post"}}},"headers":{"Deprecation":{"description":"Present only after this API version is formally deprecated. The value is the RFC 9745 Structured Field date when the deprecation was announced.","schema":{"type":"string","pattern":"^@[0-9]+$"}},"Sunset":{"description":"Present only after retirement is scheduled. The RFC 8594 HTTP-date is at least 180 days after Apartment Fax publishes the retirement notice.","schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/previews/{slug}":{"get":{"tags":["Public API"],"summary":"Preview Page","description":"The free half of a report, for the generated page at ``/{slug}``.\n\nUnlike ``POST /api/report`` this is synchronous. A preview is not a job: it is a\ndocument a crawler asks for and expects a body from, and returning 202 plus a poll\nURL to Googlebot would leave every generated page indexing as an empty shell.","operationId":"preview_page_v1_previews__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Preview Page V1 Previews  Slug  Get"}}},"headers":{"Deprecation":{"description":"Present only after this API version is formally deprecated. The value is the RFC 9745 Structured Field date when the deprecation was announced.","schema":{"type":"string","pattern":"^@[0-9]+$"}},"Sunset":{"description":"Present only after retirement is scheduled. The RFC 8594 HTTP-date is at least 180 days after Apartment Fax publishes the retirement notice.","schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/preview/{slug}":{"get":{"summary":"Preview Page","description":"The free half of a report, for the generated page at ``/{slug}``.\n\nUnlike ``POST /api/report`` this is synchronous. A preview is not a job: it is a\ndocument a crawler asks for and expects a body from, and returning 202 plus a poll\nURL to Googlebot would leave every generated page indexing as an empty shell.","operationId":"preview_page_api_preview__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Preview Page Api Preview  Slug  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/seo/{slug}":{"get":{"summary":"Seo Preview Page","description":"The complete initial HTML for the public ``/{slug}`` address page.\n\nThis route is intentionally corpus-only. A random or stale URL must return a real 404,\nnot trigger a 66-request report compile and eventually become a client-side soft 404.","operationId":"seo_preview_page_seo__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/seo-path/{borough_slug}/{part2}/{part3}/{part4}":{"get":{"summary":"Seo Hierarchical Preview Page","description":"Serve borough/neighborhood/address/apartment paths from the corpus.","operationId":"seo_hierarchical_preview_page_seo_path__borough_slug___part2___part3___part4__get","parameters":[{"name":"borough_slug","in":"path","required":true,"schema":{"type":"string","title":"Borough Slug"}},{"name":"part2","in":"path","required":true,"schema":{"type":"string","title":"Part2"}},{"name":"part3","in":"path","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Part3"}},{"name":"part4","in":"path","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Part4"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/seo-path/{borough_slug}/{part2}/{part3}":{"get":{"summary":"Seo Hierarchical Preview Page","description":"Serve borough/neighborhood/address/apartment paths from the corpus.","operationId":"seo_hierarchical_preview_page_seo_path__borough_slug___part2___part3__get","parameters":[{"name":"borough_slug","in":"path","required":true,"schema":{"type":"string","title":"Borough Slug"}},{"name":"part2","in":"path","required":true,"schema":{"type":"string","title":"Part2"}},{"name":"part3","in":"path","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Part3"}},{"name":"part4","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Part4"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/seo-path/{borough_slug}/{part2}":{"get":{"summary":"Seo Hierarchical Preview Page","description":"Serve borough/neighborhood/address/apartment paths from the corpus.","operationId":"seo_hierarchical_preview_page_seo_path__borough_slug___part2__get","parameters":[{"name":"borough_slug","in":"path","required":true,"schema":{"type":"string","title":"Borough Slug"}},{"name":"part2","in":"path","required":true,"schema":{"type":"string","title":"Part2"}},{"name":"part3","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Part3"}},{"name":"part4","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Part4"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sitemap.xml":{"get":{"summary":"Sitemap Index","description":"The published releases, or the staged launch until the first one exists.","operationId":"sitemap_index_sitemap_xml_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sitemaps/foundation.xml":{"get":{"summary":"Foundation Sitemap","description":"Homepage, focused guides and the public borough directory hierarchy.","operationId":"foundation_sitemap_sitemaps_foundation_xml_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sitemaps/elite-search.xml":{"get":{"summary":"Elite Landing Sitemap","description":"The four focused lookup pages, independent of the generated corpus.","operationId":"elite_landing_sitemap_sitemaps_elite_search_xml_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sitemaps/core-search.xml":{"get":{"summary":"Core Landing Sitemap","description":"The three 75+ Core-tier lookup pages, independent of the generated corpus.","operationId":"core_landing_sitemap_sitemaps_core_search_xml_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sitemaps/second-wave-search.xml":{"get":{"summary":"Second Wave Landing Sitemap","description":"The eight additional lookup pages backed by current report sources.","operationId":"second_wave_landing_sitemap_sitemaps_second_wave_search_xml_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sitemaps/address-launch.xml":{"get":{"summary":"Address Launch Sitemap","description":"The deterministic 25,000-URL cohort used for the first search submission.","operationId":"address_launch_sitemap_sitemaps_address_launch_xml_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/sitemaps/release/{release_id}-{shard}.xml":{"get":{"summary":"Release Sitemap Shard","description":"One immutable shard of a published release.","operationId":"release_sitemap_shard_sitemaps_release__release_id___shard__xml_get","parameters":[{"name":"release_id","in":"path","required":true,"schema":{"type":"integer","title":"Release Id"}},{"name":"shard","in":"path","required":true,"schema":{"type":"integer","title":"Shard"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sitemaps/{batch_id}/{tier}-{shard}.xml":{"get":{"summary":"Sitemap Shard","description":"One immutable weekly-batch shard.","operationId":"sitemap_shard_sitemaps__batch_id___tier___shard__xml_get","parameters":[{"name":"batch_id","in":"path","required":true,"schema":{"type":"integer","title":"Batch Id"}},{"name":"tier","in":"path","required":true,"schema":{"type":"string","title":"Tier"}},{"name":"shard","in":"path","required":true,"schema":{"type":"integer","title":"Shard"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/robots.txt":{"get":{"summary":"Robots","operationId":"robots_robots_txt_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/health":{"get":{"tags":["Public API"],"summary":"Health","operationId":"health_v1_health_get","responses":{"200":{"description":"Successful Response","headers":{"Deprecation":{"description":"Present only after this API version is formally deprecated. The value is the RFC 9745 Structured Field date when the deprecation was announced.","schema":{"type":"string","pattern":"^@[0-9]+$"}},"Sunset":{"description":"Present only after retirement is scheduled. The RFC 8594 HTTP-date is at least 180 days after Apartment Fax publishes the retirement notice.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health V1 Health Get"}}}}}}},"/api/health":{"get":{"summary":"Health","operationId":"health_api_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Api Health Get"}}}}}}},"/v1/agent/register":{"post":{"tags":["Public API"],"summary":"Register Agent","description":"Hand an anonymous agent its own API account and the one key that spends from it.\n\nNo credential is needed to call this, and the reason that is safe is the balance: the\naccount opens with nothing in it. What comes back reads the free public previews and\nbuys exactly nothing until credits are purchased for the account, so an open\nregistration endpoint mints principals rather than money.\n\n``secret`` is in this response and in no other, ever, the same as the signed-in key\nroute: only its hash is stored, so an agent that loses it revokes the key and registers\nagain.\n\nThe retry key is accepted and deliberately not deduplicated on, which follows from the\nsentence above rather than contradicting it: replaying a registration could only return\nthe first account without its secret, and an account the caller cannot authenticate as\nis worse to receive than a second one. So a retry opens another account, and that\naccount holds no balance and can spend nothing.","operationId":"register_agent_v1_agent_register_post","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRegistrationRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Register Agent V1 Agent Register Post"}}},"headers":{"Deprecation":{"description":"Present only after this API version is formally deprecated. The value is the RFC 9745 Structured Field date when the deprecation was announced.","schema":{"type":"string","pattern":"^@[0-9]+$"}},"Sunset":{"description":"Present only after retirement is scheduled. The RFC 8594 HTTP-date is at least 180 days after Apartment Fax publishes the retirement notice.","schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/agent/revoke":{"post":{"tags":["Public API"],"summary":"Revoke Agent Key","description":"Turn off the key that authenticated this request. No key id needed, and none known.\n\n401 and 403 say different things here, the same way they do on the management plane:\nnothing presented, or something unverifiable, is 401; a perfectly valid Clerk session\nthat simply is not the credential this route revokes is 403, because a signed-in user\nrevokes by id at ``DELETE /api/api-keys/{key_id}`` and retrying here will never work.\n\nThe retry key is accepted and unused because revocation is already idempotent by\nconstruction: the key is off either way, and a replayed call simply reports that it was\nnot the one that turned it off.","operationId":"revoke_agent_key_v1_agent_revoke_post","parameters":[{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke Agent Key V1 Agent Revoke Post"}}},"headers":{"Deprecation":{"description":"Present only after this API version is formally deprecated. The value is the RFC 9745 Structured Field date when the deprecation was announced.","schema":{"type":"string","pattern":"^@[0-9]+$"}},"Sunset":{"description":"Present only after retirement is scheduled. The RFC 8594 HTTP-date is at least 180 days after Apartment Fax publishes the retirement notice.","schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/stripe/webhook":{"post":{"summary":"Stripe Webhook","description":"Where a payment turns into a balance.\n\nThe raw body is required: the signature covers the exact bytes Stripe sent, so parsing\nto JSON first and re-serialising would fail verification. An event that does not\nverify gets a 400 and no side effect.\n\nReturning 200 on an event we chose not to act on is deliberate. Stripe retries\nnon-2xx, and retrying an event this endpoint will always ignore achieves nothing.","operationId":"stripe_webhook_api_stripe_webhook_post","parameters":[{"name":"Stripe-Signature","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stripe-Signature"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","minLength":1,"maxLength":255},{"type":"null"}],"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate.","title":"Idempotency-Key"},"description":"A caller-generated key that makes a retried write return the original resource instead of creating or charging for a duplicate."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Stripe Webhook Api Stripe Webhook Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AcceptedReportJob":{"properties":{"id":{"type":"string","title":"Id","description":"Report identifier retained for existing clients; equal to jobId."},"jobId":{"type":"string","title":"Jobid","description":"Job identifier used in the polling URL."},"statusUrl":{"type":"string","title":"Statusurl","description":"Relative URL to poll until status is done or error."},"status":{"type":"string","title":"Status","description":"Current job status; initially running."},"stage":{"type":"string","title":"Stage"},"step":{"type":"integer","title":"Step"},"address":{"type":"string","title":"Address"},"unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unit"},"elapsedMs":{"type":"integer","title":"Elapsedms"},"report":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Report"},"detail":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Detail"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["id","jobId","statusUrl","status","stage","step","address","unit","elapsedMs","report","detail","error"],"title":"AcceptedReportJob","description":"A newly accepted report compile and the resource agents should poll."},"AddressResolveRequest":{"properties":{"address":{"type":"string","maxLength":500,"title":"Address"},"unit":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Unit"}},"type":"object","required":["address"],"title":"AddressResolveRequest"},"AgentRegistrationRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Name"}},"type":"object","title":"AgentRegistrationRequest","description":"Body of ``POST /v1/agent/register``. Everything in it is optional, because an agent\nthat knows nothing about this service but the URL has to be able to POST an empty body\nand get a working credential back."},"ApiAccountListResponse":{"properties":{"accounts":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Accounts"},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nextcursor","description":"Opaque cursor to pass as `cursor` on the next request; null when exhausted."},"hasMore":{"type":"boolean","title":"Hasmore","description":"Whether another page is available after this one."}},"type":"object","required":["accounts","nextCursor","hasMore"],"title":"ApiAccountListResponse","description":"One cursor page of API accounts."},"ApiAccountRequest":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name"}},"type":"object","required":["name"],"title":"ApiAccountRequest","description":"Body of ``POST /api/api-accounts``. The name is for the person reading a list of\nthem, not for anything the service does: \"production\" and \"staging\" are the point."},"GuestCheckoutRequest":{"properties":{"address":{"type":"string","maxLength":500,"title":"Address"},"unit":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Unit"},"email":{"type":"string","maxLength":320,"title":"Email","default":""}},"type":"object","required":["address"],"title":"GuestCheckoutRequest"},"GuestEmailCaptureRequest":{"properties":{"token":{"type":"string","maxLength":512,"title":"Token"},"email":{"type":"string","maxLength":320,"title":"Email"}},"type":"object","required":["token","email"],"title":"GuestEmailCaptureRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"PreviewBatchOperation":{"properties":{"slug":{"type":"string","maxLength":200,"minLength":1,"title":"Slug","description":"An Apartment Fax public preview slug, for example 117-w-13th-st-apt-4r."}},"type":"object","required":["slug"],"title":"PreviewBatchOperation","description":"One public preview lookup in ``POST /v1/previews/batch``."},"PreviewBatchResult":{"properties":{"slug":{"type":"string","title":"Slug"},"status":{"type":"integer","title":"Status"},"preview":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Preview"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["slug","status"],"title":"PreviewBatchResult","description":"The result for one operation, kept in request order."},"ReportListResponse":{"properties":{"reports":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Reports"},"nextCursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nextcursor","description":"Opaque cursor to pass as `cursor` on the next request; null when exhausted."},"hasMore":{"type":"boolean","title":"Hasmore","description":"Whether another page is available after this one."}},"type":"object","required":["reports","nextCursor","hasMore"],"title":"ReportListResponse","description":"One cursor page of report summaries."},"ReportRequest":{"properties":{"address":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Address"},"unit":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Unit"},"ask":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Ask"},"email":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}],"title":"Email"},"replay":{"anyOf":[{"type":"boolean"},{"type":"string"},{"type":"null"}],"title":"Replay"}},"type":"object","title":"ReportRequest","description":"Body of ``POST /api/report``. Either ``address`` or ``ask`` must be present.\n\nThe length caps are a second line of defence behind the raw body-size check in\n``_enforce_request_limits``: that check rejects an oversized request outright, this\nkeeps any single field from being unreasonably large even inside a body that is\ntechnically under the cap."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"tags":[{"name":"Public API","description":"Supported, versioned Apartment Fax integration endpoints.","externalDocs":{"description":"API versioning and deprecation policy","url":"https://apartmentfaxnyc.com/developers/api-versioning"}}]}