Developers · API v1
Broadcast Map API
Three HTTPS calls let installer apps declare the venues that offer Auracast™ broadcasts, let networked transmitters say a venue is broadcasting right now, and let any app read the map. Free to use, open specification, no personal data.
- REST + JSON
- Free
- Reads without a key
- Data under CC BY 4.0
Quick start
Every call goes to https://aurapulse.org/api/v1/, sends and returns JSON (UTF-8), and works over HTTPS only. Send a User-Agent header naming your app or device and its version (for example ExampleApp/4.2), so that an error can be traced back to its source.
Reading needs no key. Try it now, from a terminal:
curl "https://aurapulse.org/api/v1/venues?lat=46.58&lng=0.34&radius_km=25"Or right here
The answer will show here.The API itself always answers in English, whatever the language of this page.
| Call | Method and path | Who calls it | Key |
|---|---|---|---|
| Declare a venue | POST /venues | Installer and configuration apps, when a transmitter is set up | Partner |
| Remove a venue | DELETE /venues/{id} | The partner that declared it | Partner |
| List my venues | GET /partner/venues | A partner checking its declarations | Partner |
| Report live | POST /venues/{id}/live | Networked transmitters, a partner’s cloud | Venue or partner |
| Read nearby venues | GET /venues?lat=&lng=&radius_km= | Any app or website | None |
| Read one venue | GET /venues/{id} | Any app or website | None |
A declared venue shows on the map once a moderator has checked it. A venue that reported live in the last 10 minutes shows as Live, with a green dot, on the map and in every read.
Keys
Keys go in the Authorization: Bearer <key> header. They are free and do not expire, but a key that sends wrong data can be revoked. A key that may have leaked is replaced on request: the old one stops working the same day.
| Key | Looks like | Given to | Allows |
|---|---|---|---|
| Partner key | apk_live_ + 32 characters | One per company, on request | Declaring, removing and listing that partner’s venues; reporting them live from the partner’s cloud |
| Venue key | avk_ + 32 characters | Returned when a venue is declared; also given by the map team for a venue already on the map | Reporting that one venue as live |
| Test key | apk_test_ + 32 characters | Anyone who asks | Every partner call, on test data that never reaches the map |
A venue key only lets a device say “this venue is live”: it cannot change the venue’s name, address or streams. A transmitter can store it without risk to the listing.
To get a key, write to contact@aurapulse.org with your company name, the products concerned and the name to show as the source on the map. A test key is usually sent the same day.
Declare a venue
POST /venues with a partner key, when a transmitter is installed or its broadcast settings change. Calling it again with the same external_id updates the venue instead of creating a second one.
curl -X POST "https://aurapulse.org/api/v1/venues" \
-H "Authorization: Bearer apk_live_..." \
-H "Content-Type: application/json" \
-H "User-Agent: ExampleApp/4.2" \
-d @venue.json{
"external_id": "site-48213",
"name": "Example Cinema",
"address": "1 Example Street, 00000 Exampletown, France",
"country": "FR",
"lat": 46.5802,
"lng": 0.3404,
"type": "screen",
"streams": [
{ "name": "EXAMPLE_SCREEN_1", "label": "Screen 1", "access": "open", "languages": ["fr"] },
{ "name": "EXAMPLE_SCREEN_2", "label": "Screen 2, English version", "access": "password", "languages": ["en"] }
],
"public": true
}external_id,name,country,streamsandpublicare required, plus eitheraddressorlat+lng. Every field is described in The venue object.publicmust betrue: the map only lists places open to the public. A home, an office or a private event is refused.- Never send the broadcast password (Broadcast Code):
accessonly says whether there is one.
Answer 201 Created (or 200 OK for an update):
{
"id": "example-cinema-exampletown",
"status": "pending",
"venue_key": "avk_...",
"map_url": "https://aurapulse.org/map/#example-cinema-exampletown"
}status is pending until a moderator publishes the venue, then published. venue_key is returned only when a declaration is first created: store it in the transmitter if it can report live.
A venue already on the map
Recommended: before declaring, read the venues within 200 m (GET /venues?lat=…&lng=…&radius_km=0.2) and ask the installer whether the place is one of them. If it is, send that venue’s id as join_venue_id. Without it, the map matches the declaration itself, in this order:
- Same partner and same
external_id: the same venue, updated. - A venue within 150 m that already has one of the declared Broadcast Names: the same venue. The answer gives its existing
id. - A venue within 150 m with a similar name but none of the same Broadcast Names: kept
pendingand flagged to the moderator as a possible duplicate. - Nothing close: a new venue,
pending.
When a declaration joins a venue, its level goes up to declared, but a venue level (confirmed by the venue itself) is kept, and so are the fields the map team corrected by hand. Two venues in one building (a cinema and a shop in the same mall) stay apart as long as their Broadcast Names differ.
Remove a venue
DELETE /venues/{id} with the partner key that declared it, for example when a transmitter is uninstalled. The venue stops being Live at once and leaves the map once a moderator confirms. Answer 202 Accepted:
{ "id": "example-cinema-exampletown", "status": "removal_requested" }GET /partner/venues lists every venue declared with your key, with its external_id and status, 100 per page (next gives the next page). It is the way to check a declaration without waiting for it on the map.
Report live
POST /venues/{id}/live with that venue’s key (or the partner key that declared it, for a partner’s own cloud), every 5 minutes while the transmitter broadcasts. The venue shows as Live for 10 minutes after the last report, so one missed report changes nothing.
{
"streams": [
{ "name": "EXAMPLE_SCREEN_1", "access": "open" },
{ "name": "EXAMPLE_SCREEN_2", "access": "password" }
],
"device": { "maker": "Example Audio", "model": "TX-200", "firmware": "2.3.1" }
}streamslists what is on air now. An empty list means the transmitter is on but silent: the venue is not shown as Live.- Only Broadcast Names declared for the venue count; others are ignored and listed back in
ignored. deviceis optional and only used to show the source (“Live via Example Audio TX-200”).- Add a random delay of 0 to 60 seconds to the first report after power-on, so that many transmitters restarting together after a power cut do not all call at once.
- Only what is online can report. A transmitter with no network keeps its place on the map but is never shown as Live.
Answer 200 OK:
{
"live_until": "2026-10-19T21:10:00Z",
"next_report_in": 300,
"ignored": []
}next_report_in is in seconds and must be followed: it lets the map slow every device down without a firmware update. A device that reports more often is answered 429.
Read venues
No key needed. Answers can be called from any web page (CORS is open) and may be cached for 60 seconds.
GET /venues?lat=46.58&lng=0.34&radius_km=25 returns the published venues within radius_km (0.1 to 100, default 25), nearest first, 50 per page:
{
"venues": [
{
"id": "example-cinema-exampletown",
"name": "Example Cinema",
"city": "Exampletown",
"lat": 46.5802,
"lng": 0.3404,
"distance_km": 0.4,
"type": "screen",
"streams": [{ "name": "EXAMPLE_SCREEN_1", "access": "open", "languages": ["fr"] }],
"level": "declared",
"live": { "status": "live", "since": "2026-10-19T19:02:00Z", "last_seen": "2026-10-19T21:00:00Z" }
}
],
"next": null
}live=onlykeeps only the venues that are live now.type=screen,worshipfilters by type.nextis the URL of the next page, ornull.GET /venues/{id}returns one venue, or404.
The venue object
| Field | Type | Rules |
|---|---|---|
id | string | Set by the map from the name and city. Never changes. |
external_id | string | Your own id for the site, 1 to 64 characters. Only returned to you. |
join_venue_id | string | Sent only when declaring: the id of an existing venue the installer chose. See A venue already on the map. |
name | string | Name of the place as the public knows it, 2 to 80 characters. |
address | string | Full postal address, up to 200 characters. |
city | string | Filled from the address if missing. |
country | string | ISO 3166-1 alpha-2 code: FR, GB, US… |
lat, lng | number | WGS 84, 5 decimals or more. Found from the address if missing (OpenStreetMap). |
type | string | One of screen, public, museum, worship, transport, education, hearing, sport, health, retail, other. screen is a cinema, theatre or concert hall; public a town hall, library or courthouse; hearing hearing care. More types may be added: show an unknown type as other. |
type_detail | string | Optional, up to 40 characters, free words for the place (Stadium, Hospital). |
streams | array | 1 to 16 items. |
streams[].name | string | The Broadcast Name exactly as broadcast, 1 to 32 characters. |
streams[].label | string | Optional, up to 40 characters: what the stream is for (Screen 1, English version). |
streams[].access | string | open, password or unknown. The password itself is never sent. |
streams[].languages | array | Optional ISO 639-1 codes of the audio (fr, en). |
public | boolean | Must be true when declaring. Not returned. |
level | string | Returned only: documented (found in a public source), reported (sent by a visitor through the map’s form), declared (sent by a partner through this API), venue (confirmed by the venue itself). |
source | object | Returned only: the partner’s name, or the press article. |
live | object | Returned only: status (live or off), since and last_seen (ISO 8601, UTC). |
When the map team moves a venue to a more precise type, a later declaration with other does not undo it.
Errors and limits
Every error has the same shape, so a device can log it as it is:
{ "error": { "code": "invalid_field", "field": "streams[1].name", "message": "Broadcast Name is longer than 32 characters." } }| HTTP | code | When |
|---|---|---|
| 400 | invalid_json, invalid_field, missing_field | The body cannot be read, or a field breaks its rules |
| 401 | missing_key, unknown_key | No key, or a key the map does not know |
| 403 | revoked_key, not_your_venue, not_public | Key revoked, venue declared by another partner, or public is not true |
| 404 | not_found | No venue with that id, or an unknown address |
| 409 | external_id_conflict | This external_id is already used for a different place |
| 429 | too_many_requests | Over a limit below; the Retry-After header says when to try again |
| 500, 503 | server_error, maintenance | Our side; retry after Retry-After, or 5 minutes |
| Call | Limit |
|---|---|
| Declare or remove | 500 per day per partner key |
| Report live | 1 per next_report_in per venue (300 seconds today) |
| Read | 60 per minute per IP address |
Testing
A test key (apk_test_…) works on every partner call, with the same checks and the same answers, plus "test": true. Test declarations never reach the moderators or the public map, and are erased after 24 hours. Check them with GET /partner/venues. Test live reports use the venue keys returned by test declarations.
Rules
No personal data. The API takes and gives places and broadcasts only: no installer names, no e-mail addresses, no device serial numbers. IP addresses are used for rate limits and kept 7 days at most. Details in the privacy policy.
Public places only. Declared venues are checked by a moderator before they appear.
Right to removal. Any venue can ask to be taken off the map at contact@aurapulse.org, even one declared by a partner; it is removed within 7 days and is not declared again through the API.
Passwords stay private. The map shows that a stream is protected, never its password.
Reusing the data. Everything the read calls return is under CC BY 4.0: free to show in any app or site, with the credit “Data: AuraPulse broadcast map” and a link to aurapulse.org/map.
No guarantee. The API is free and runs on a small host, with no promise of availability. Clients must keep working when it does not answer: a missed declaration can be sent again, a missed live report only delays the green dot.
Versioning. v1 only grows: new optional fields, new values and new calls, never a removed or renamed field. A breaking change goes to v2, announced 12 months ahead, and v1 keeps running during that time.
Open specification. This page is published under CC BY 4.0: anyone may implement it, including another map.
Trademarks. Auracast™ is a trademark of Bluetooth SIG, Inc.; AuraPulse is an independent project, not affiliated with or endorsed by Bluetooth SIG. Partner names are shown on the map only with their agreement.
Not in v1
Planned as optional fields, so that v1 integrations keep working: broadcast schedules (“Saturdays during shows”), a link that opens an open stream directly from an app, and automatic publication for partners whose declarations have proved reliable. Ideas and questions are welcome at contact@aurapulse.org.
Version 1 · updated 19 October 2026 · https://aurapulse.org/api/v1/