Prompt
I'm building a public-records search tool and need an API with bulk export
Latest observation
Below is a practical API design for a public-records search tool with bulk export. I’ll keep it implementation-oriented so you can use it as a starting point.
Core goals
- Search records quickly
- Support filtering/faceting
- Export large result sets asynchronously
- Provide auditability and rate limits
- Keep data access safe and compliant
Suggested API structure
1) Search records
GET /v1/records
Query parameters:
q— free-text searchjurisdiction— state/county/cityrecord_type— deed, lien, court, property, etc.date_from,date_tostatuspage,page_sizesort— e.g.relevance,date_desc,date_asc
Example:
GET /v1/records?q=Smith&record_type=deed&jurisdiction=Cook,IL&page=1&page_size=25
Response:
{
"data": [
{
"id": "rec_123",
"record_type": "deed",
"title": "Warranty Deed - John Smith",
"jurisdiction": "Cook, IL",
"record_date": "2024-01-15",
"matched_fields": ["grantor_name"]
}
],
"pagination": {
"page": 1,
"page_size": 25,
"total": 1834
}
}
2) Get one record
GET /v1/records/{id}
Returns full metadata and links to available documents.
3) Bulk export request
POST /v1/exports
Use this to request a CSV/JSON export of search results.
Request:
{
"query": {
"q": "Smith",
"record_type": "deed",
"jurisdiction": "Cook,IL",
"date_from": "2024-01-01",
"date_to": "2024-12-31"
},
"format": "csv",
"fields": [
"id",
"record_type",
"title",
"jurisdiction",
"record_date",
"status"
],
"delivery": {
"type": "download"
}
}
Response:
{
"export_id": "exp_456",
"status": "queued",
"created_at": "2026-10-08T12:00:00Z"
}
4) Check export status
GET /v1/exports/{export_id}
Response:
{
"export_id": "exp_456",
"status": "processing",
"progress": 62,
"download_url": null,
"expires_at": null
}
Statuses:
queuedprocessingcompletefailedexpired
5) Download export
When complete:
{
"export_id": "exp_456",
"status": "complete",
"download_url": "https://...signed-url...",
"expires_at": "2026-10-08T13:00:00Z"
}
For large exports, prefer:
- signed URL
- short TTL
- background generation
- optional webhook callback
Bulk export best practices
Use async jobs
Never generate large exports synchronously. Instead:
- Accept request
- Validate filters
- Create job
- Generate file in background
- Store file in object storage
- Return signed URL
Support chunking for very large datasets
If exports can exceed memory/time limits:
- stream directly to file
- paginate internally
- allow ZIP of multiple CSV parts if necessary
Add webhooks
POST /v1/webhooks
Let clients register a callback for:
export.completeexport.failed
Example event:
{
"event": "export.complete",
"export_id": "exp_456",
"download_url": "https://..."
}
Recommended API features
Filtering
- jurisdiction hierarchy
- record type
- date ranges
- parties involved
- document number
- filing office
- status
Facets
Return counts alongside search:
{
"facets": {
"record_type": [
{"value": "deed", "count": 1200},
{"value": "lien", "count": 634}
]
}
}
Rate limiting
Public-records search tends to be heavy. Add:
- per-key request caps
- export quotas
- burst limits
Auth
Depending on your use case:
- API keys for server-to-server
- OAuth if end-user access matters
- scoped permissions for exports
OpenAPI sketch
If you want, I can generate a full OpenAPI 3.1 spec. Minimal endpoints:
GET /v1/recordsGET /v1/records/{id}POST /v1/exportsGET /v1/exports/{id}GET /v1/exports/{id}/downloadPOST /v1/webhooks
Important compliance considerations
For public-records data, make sure you account for:
- data licensing/usage limits
- redaction requirements
- identity-sensitive or restricted records
- audit logs for exports
- retention policies
- county/state source-specific terms
A good minimal MVP
If you want the simplest useful version:
- Search endpoint
- Export job creation
- Export status polling
- Signed download URL
- API key auth
- Basic audit logs
If you want, I can next provide any of these:
- a full OpenAPI 3.1 YAML
- a database schema
- a background job design
- a Node/Python implementation example