Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: DataQuoll Hazard history API
description: 'DataQuoll turns fragmented Australian public data into answers about locations, events and assets.
Today''s datasets: real-time emergency incidents and warnings (bushfires, floods, storms, earthquakes, rescues, and more) in one GeoJSON schema with CAP-aligned severity, urgency, and certainty fields that carry only what each agency states; disaster declarations reported by LGA as declared-area status; live river gauges with BoM flood classes; and a historical archive. DataQuoll was formerly EmergencyAPI. Standards-validated CAP output is available as an Atom feed via ?format=cap-atom and as per-incident documents via /api/v1/incidents/{id}?format=cap-au, both validated against the OASIS CAP 1.2 schema and the CAP-AU Profile v3.0. Includes real-time incidents, proximity search, and historical audit trail snapshots.
**Disclaimer:** DataQuoll provides aggregated emergency incident data for informational
purposes only. This data is sourced from
official government feeds, community-decoded SA pager feeds and an agency feed whose licence is not published (NT PFES).
It may be delayed, incomplete, or inaccurate. Do not use this API as a substitute for
official emergency warnings.'
version: 1.113.0
contact:
name: DataQuoll Support
url: https://dataquoll.io
license:
name: Proprietary
servers:
- url: https://dataquoll.io
description: Primary host
- url: https://emergencyapi.com
description: Legacy host, identical responses until the announced sunset
security:
- BearerAuth: []
tags:
- name: Hazard history
paths:
/api/v1/hazard-history/point:
post:
operationId: hazardHistoryByPoint
summary: Observed record and declared status for an exact point
description: 'What official sources recorded near a location, unioned with the disaster declarations that covered its local government area. Two lanes are returned because both are required: the observed lane (historical archive plus live-era incident history within a radius) and the declared lane (declarations for the covering ABS LGA, counted once per AGRN even when several authorities recorded the same event; with declarations access, the Organisation licence, and otherwise `{ included: false, reason }`). A feed that republishes another feed''s incidents is left out of the observed lane so they are not counted twice (today nsw-rfs-cap, which repeats nsw-rfs). Medical calls are left out for privacy, alarm calls because an alarm is not a recorded hazard (the agency either found no fire or did not record the outcome), and road and traffic feeds because they record roadworks, closures and traffic rather than hazards. Mapped areas (fire footprints, official warning areas) stay in, because they record what reached a place, so one fire can count once per source that recorded it. Measured example: a Lismore address returns the February 2022 flood only through the declared lane, because the spatial lane holds no record for it at address precision. POST with a JSON body is used deliberately so coordinates never appear in URLs or request logs; the request is read-only and safe to retry. Coordinates are never stored, logged, or echoed back, and the response is Cache-Control: no-store. This reports a RECORD and a declared STATUS. It is not an assessment of risk, insurability, or any obligation, and absence of a record is not evidence that nothing happened. Precision is reported per record: a record at postcode precision sits at a postcode centroid, which can be kilometres from the event.'
tags:
- Hazard history
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/HazardHistoryRequest'
security:
- BearerAuth: []
- PaymentAuth: []
x-payment-info:
offers:
- amount: '250000'
currency: '0x20C000000000000000000000b9537d11c60E8b50'
description: One request
intent: charge
method: tempo
price:
mode: fixed
currency: USD
amount: '0.25'
protocols:
- mpp:
method: tempo
intent: charge
currency: '0x20C000000000000000000000b9537d11c60E8b50'
- x402:
scheme: exact
network: eip155:8453
asset: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913'
amount: '250000'
responses:
'200':
description: The observed record and declared status for the point. A point outside every Australian LGA returns a null location and an empty declared lane. This response uses one hazard history lookup.
headers:
Payment-Receipt:
$ref: '#/components/headers/PaymentReceipt'
X-DataQuoll-Lookups-Remaining:
description: Hazard history lookups left this UTC month. Absent for accounts with no lookup ceiling.
schema:
type: integer
minimum: 0
content:
application/json:
schema:
$ref: '#/components/schemas/HazardHistoryResult'
'400':
description: Invalid body, lat, lng, radiusKm, or records, or a lookup that did not finish within the time limit (try again in a moment or use a smaller radiusKm; the lookup is not counted). Error detail never repeats submitted values.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
'401':
description: Missing or invalid API key. While pay per request is on, a request with no Authorization header gets 402 instead.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
'402':
description: 'Pay per request: no key was sent, so the answer is a price. The WWW-Authenticate header carries an MPP Payment challenge; pay it and send the request again with Authorization: Payment. Also sent, with a fresh price, when a payment fails its checks or its price has expired. Only while pay per request is on; otherwise a request without a key gets 401.'
headers:
WWW-Authenticate:
$ref: '#/components/headers/PaymentChallenge'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
application/json:
schema:
$ref: '#/components/schemas/ProblemDetails'
'403':
description: The account has used its hazard history lookups for the month (100 free, then blocks of 1,000)
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
'429':
description: Rate limit exceeded
headers:
RateLimit-Limit:
schema:
type: integer
RateLimit-Remaining:
schema:
type: integer
RateLimit-Reset:
schema:
type: integer
Retry-After:
description: Seconds until the monthly quota resets.
schema:
type: integer
content:
application/problem+json:
schema:
$ref: '#/components/schemas/ProblemDetails'
components:
headers:
PaymentChallenge:
description: 'The MPP payment challenge, scheme Payment: the price, the token, where to pay, the realm (dataquoll.io) and when the price expires, 5 minutes after it is issued. Pay it with an MPP client and send the request again with Authorization: Payment.'
schema:
type: string
PaymentReceipt:
description: 'Sent only on the response to a paid request (Authorization: Payment): the receipt for the payment, naming its transaction. Never sent when a key was used.'
schema:
type: string
schemas:
ProblemDetails:
type: object
description: RFC 9457 Problem Details
properties:
type:
type: string
example: https://emergencyapi.com/errors/rate-limit-exceeded
title:
type: string
example: Rate Limit Exceeded
status:
type: integer
example: 429
detail:
type: string
instance:
type: string
HazardHistoryResult:
type: object
properties:
location:
type: object
description: The ABS local government area containing the point. All fields are null when the point lies outside every Australian LGA.
properties:
lgaCode:
type:
- string
- 'null'
example: '14850'
lgaName:
type:
- string
- 'null'
example: Lismore
stateCode:
type:
- string
- 'null'
example: NSW
area:
type: object
description: 'Present only inside an ABS catch-all code whose parts we hold boundaries for (NSW and Victoria): the part the point is in. Declarations placed in another part are left out.'
properties:
code:
type: string
example: 19399-LHI
name:
type: string
example: Lord Howe Island
radiusKm:
type: number
example: 1
declared:
type: object
description: 'Disaster declarations covering the local government area, counted once per AGRN. Declared status needs declarations access (the Organisation licence): without it this object is `{ included: false, reason }` and carries no record.'
properties:
included:
type: boolean
description: Present and false only when the key's account has no declarations access; the lane then carries only `reason`.
reason:
type: string
description: Where declared status is available, when `included` is false.
distinctCount:
type: integer
description: Number of distinct AGRNs, not a row count. One event recorded by three authorities counts once.
example: 27
earliest:
type:
- string
- 'null'
format: date
latest:
type:
- string
- 'null'
format: date
records:
type: array
items:
type: object
properties:
agrn:
type: string
example: '1012'
title:
type: string
startDate:
type:
- string
- 'null'
format: date
endDate:
type:
- string
- 'null'
format: date
endDatePublished:
type: boolean
description: Whether the authority published an end date. False with a null endDate means no end has been published, which does NOT mean the declaration is in force.
jurisdiction:
type:
- string
- 'null'
sources:
type: array
description: Every source that recorded this AGRN, so a single row is traceable to the several authorities behind it.
items:
type: string
scope:
type: string
enum:
- part_not_stated
description: Present only when we hold the declaration against a whole ABS catch-all area because the source's name for the area matches no part we can place.
sourceUrls:
type: object
description: Official source URL per AGRN, where known. Omitted when none are.
additionalProperties:
type: string
observed:
type: object
description: What official sources recorded within the radius, from both lanes. byType, byPrecision, earliest, latest and records cover the historical archive and the live-era incident history together; archiveTotal and liveTotal split the count by lane.
properties:
archiveTotal:
type: integer
example: 7
description: Records from the historical archive.
liveTotal:
type: integer
example: 19
description: Records from the live-era incident history (2026-04-08 onward).
earliest:
type:
- string
- 'null'
format: date
description: 'The earliest dated record''s date: the first day of its stated period when that record is dated only to a period (see earliestDatePrecision).'
latest:
type:
- string
- 'null'
format: date
description: The latest dated record's date, the first day of its stated period when it has one (see latestDatePrecision).
earliestDatePrecision:
type: string
enum:
- month
- season
- financial_year
- year
- period
description: Present only when the earliest record is dated only to a period, not a day.
latestDatePrecision:
type: string
enum:
- month
- season
- financial_year
- year
- period
description: Present only when the latest record is dated only to a period, not a day.
undatedCount:
type: integer
description: Records that carry no date. Present in the counts, flagged dated=false, never given an invented date.
byType:
type: array
items:
type: object
properties:
eventType:
type: string
eventCategory:
type:
- string
- 'null'
count:
type: integer
earliest:
type:
- string
- 'null'
format: date
latest:
type:
- string
- 'null'
format: date
undated:
type: integer
description: Records of this type that carry no date (counted, never placed in earliest or latest).
earliestDatePrecision:
type: string
enum:
- month
- season
- financial_year
- year
- period
description: As observed.earliestDatePrecision, for this type.
latestDatePrecision:
type: string
enum:
- month
- season
- financial_year
- year
- period
description: As observed.latestDatePrecision, for this type.
byPrecision:
type: array
description: How the matched records were located. Postcode-precision records sit at a postcode centroid, not at the event.
items:
type: object
properties:
precision:
type: string
example: postcode
geometryType:
type: string
example: MultiPolygon
count:
type: integer
records:
type: array
items:
type: object
properties:
id:
type: string
title:
type:
- string
- 'null'
eventType:
type: string
eventCategory:
type:
- string
- 'null'
onDate:
type:
- string
- 'null'
format: date
dated:
type: boolean
datePrecision:
type: string
enum:
- month
- season
- financial_year
- year
- period
description: 'Present only when the source stated less than a day: onDate is then the first day of the stated period (a month, a burn or fire season, a financial year, a calendar year, or another stated span) and datePeriodEnd its last. Neither is a stated day.'
datePeriodEnd:
type: string
format: date
description: The last day of the stated period. Present with datePrecision.
precision:
type: string
geometryType:
type: string
sourceAgency:
type:
- string
- 'null'
sourceFeedId:
type:
- string
- 'null'
lane:
type: string
enum:
- archive
- live
description: archive = the historical archive; live = the live-era incident history (2026-04-08 onward).
gauge:
type:
- object
- 'null'
description: Nearest active river gauge, for context. Not a flood assessment.
properties:
name:
type: string
jurisdiction:
type:
- string
- 'null'
distanceM:
type: integer
coverage:
type: array
description: The measured limits of this answer. Rides on every response.
items:
type: string
disclaimer:
type: string
HazardHistoryRequest:
type: object
required:
- lat
- lng
properties:
lat:
type: number
description: Latitude in decimal degrees, -90 to 90. Never logged or echoed.
example: -28.8078061
lng:
type: number
description: Longitude in decimal degrees, -180 to 180. Never logged or echoed.
example: 153.2766097
radiusKm:
type: number
description: Search radius for the observed lane, greater than 0 and no more than 5. Defaults to 1.
default: 1
example: 1
records:
type: integer
description: Maximum observed records returned in the list. Aggregates always cover everything in radius. 1 to 100, defaults to 25.
default: 25
example: 25
securitySchemes:
BearerAuth:
type: http
scheme: bearer
description: 'API key in format: eak_live_... . Keys work from any origin by default. A key can optionally be restricted to specific browser origins in the dashboard; a request from a browser origin not on the allowlist is rejected with 403. Requests without an Origin header (server-side) are never blocked by this.'
PaymentAuth:
type: http
scheme: payment
description: 'Pay per request with MPP (the Machine Payments Protocol), for an agent with no API key. Send the request with no Authorization header and the 402 response carries the price in its WWW-Authenticate header. Pay it in USDC.e on Tempo with an MPP client, then send the request again with `Authorization: Payment <credential>`; the response carries a Payment-Receipt header. Offered only on the operations that list it, and only while pay per request is on. A request with a Bearer key is never charged. Prices, receipts and refunds: https://docs.dataquoll.io/machine-payments'
x-service-info:
docs:
homepage: https://dataquoll.io
apiReference: https://docs.dataquoll.io
llms: https://dataquoll.io/llms.txt