AuraPulse
Home Map

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.

CallMethod and pathWho calls itKey
Declare a venuePOST /venuesInstaller and configuration apps, when a transmitter is set upPartner
Remove a venueDELETE /venues/{id}The partner that declared itPartner
List my venuesGET /partner/venuesA partner checking its declarationsPartner
Report livePOST /venues/{id}/liveNetworked transmitters, a partner’s cloudVenue or partner
Read nearby venuesGET /venues?lat=&lng=&radius_km=Any app or websiteNone
Read one venueGET /venues/{id}Any app or websiteNone

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.

KeyLooks likeGiven toAllows
Partner keyapk_live_ + 32 charactersOne per company, on requestDeclaring, removing and listing that partner’s venues; reporting them live from the partner’s cloud
Venue keyavk_ + 32 charactersReturned when a venue is declared; also given by the map team for a venue already on the mapReporting that one venue as live
Test keyapk_test_ + 32 charactersAnyone who asksEvery 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, streams and public are required, plus either address or lat + lng. Every field is described in The venue object.
  • public must be true: 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): access only 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:

  1. Same partner and same external_id: the same venue, updated.
  2. A venue within 150 m that already has one of the declared Broadcast Names: the same venue. The answer gives its existing id.
  3. A venue within 150 m with a similar name but none of the same Broadcast Names: kept pending and flagged to the moderator as a possible duplicate.
  4. 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" }
}
  • streams lists 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.
  • device is 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=only keeps only the venues that are live now. type=screen,worship filters by type.
  • next is the URL of the next page, or null.
  • GET /venues/{id} returns one venue, or 404.

The venue object

FieldTypeRules
idstringSet by the map from the name and city. Never changes.
external_idstringYour own id for the site, 1 to 64 characters. Only returned to you.
join_venue_idstringSent only when declaring: the id of an existing venue the installer chose. See A venue already on the map.
namestringName of the place as the public knows it, 2 to 80 characters.
addressstringFull postal address, up to 200 characters.
citystringFilled from the address if missing.
countrystringISO 3166-1 alpha-2 code: FR, GB, US…
lat, lngnumberWGS 84, 5 decimals or more. Found from the address if missing (OpenStreetMap).
typestringOne 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_detailstringOptional, up to 40 characters, free words for the place (Stadium, Hospital).
streamsarray1 to 16 items.
streams[].namestringThe Broadcast Name exactly as broadcast, 1 to 32 characters.
streams[].labelstringOptional, up to 40 characters: what the stream is for (Screen 1, English version).
streams[].accessstringopen, password or unknown. The password itself is never sent.
streams[].languagesarrayOptional ISO 639-1 codes of the audio (fr, en).
publicbooleanMust be true when declaring. Not returned.
levelstringReturned 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).
sourceobjectReturned only: the partner’s name, or the press article.
liveobjectReturned 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." } }
HTTPcodeWhen
400invalid_json, invalid_field, missing_fieldThe body cannot be read, or a field breaks its rules
401missing_key, unknown_keyNo key, or a key the map does not know
403revoked_key, not_your_venue, not_publicKey revoked, venue declared by another partner, or public is not true
404not_foundNo venue with that id, or an unknown address
409external_id_conflictThis external_id is already used for a different place
429too_many_requestsOver a limit below; the Retry-After header says when to try again
500, 503server_error, maintenanceOur side; retry after Retry-After, or 5 minutes
CallLimit
Declare or remove500 per day per partner key
Report live1 per next_report_in per venue (300 seconds today)
Read60 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/