Send us your lane availability
Run a pool? Instead of us reading your public lane availability page, you can send the numbers straight to us. Swimmers see them sooner and labelled Data provided by your organisation, and nothing breaks when your website changes. It's free.
How it works
- Get in touch. Email operators@laneup.au from an address on your organisation's domain, with the pools you run, your ABN and a link to each pool's page on your website.
- Prove you control your domain. We send you a token. Publish it in either place:
- a DNS TXT record:
_lane-verify.example.com.au=lane-verify=<token>, or - a text file at
https://example.com.au/.well-known/lane-availability.txtcontaining the token.
- a DNS TXT record:
- Try the sandbox. You get an API key. Pool
0is a sandbox: we check what you send and show you how we read it, but never store or publish it. - Shadow period (1–2 weeks). We take your data but don't show it yet, and compare it with what we already have.
- Live. Your data replaces ours for your pools. If it stops coming for 12 hours, we fall back to reading your website, so swimmers always see something.
The format
One JSON document lists, for each pool, the lanes free for lap swimming in each time slot, from
yesterday to 14 days ahead. Each document replaces the whole schedule for those pools.
Schema: /api/v1/schema.json · example:
/api/v1/example.json.
{
"version": 1,
"generatedAt": "2026-11-10T05:00:00+11:00",
"pools": [
{
"poolId": 0,
"totalLanes": 8,
"slots": [
{
"start": "2026-11-10T05:00",
"minutes": 30,
"closed": true
},
{
"start": "2026-11-10T05:30",
"minutes": 30,
"lanes": 6
},
{
"start": "2026-11-10T06:00",
"minutes": 30,
"lanes": 4
},
{
"start": "2026-11-10T06:30",
"minutes": 15,
"lanes": 2
},
{
"start": "2026-11-10T06:45",
"minutes": 15,
"lanes": 0
},
{
"start": "2026-11-10T07:00",
"minutes": 60,
"lanes": 5
}
]
}
]
}
| Field | Rules |
|---|---|
generatedAt | When you produced the document, with a UTC offset. Must be newer than the last one we accepted, no more than 48 hours old and not in the future. |
poolId | The id we give you for each pool; 0 is the sandbox. |
totalLanes | Lap lanes the pool has (1–30). |
start | Local time at the pool, YYYY-MM-DDTHH:MM, on a quarter hour. No offset. |
minutes | 15, 30 or 60. |
lanes / closed | Either lanes free for lap swimming (0 to totalLanes; 0 means open but full) or "closed": true. Slots you leave out count as closed. |
Send numbers only. Unknown fields are rejected, and we never accept personal information (member names, booking references). Up to 50 pools and 256 KB per document.
Option A: we fetch it (simplest)
Publish the document at an https URL on your verified domain and tell us the URL. We
fetch it up to once an hour while your pools are open, more often at the times it tends to change. We
don't follow redirects.
Option B: you send it
PUT https://laneup.au/api/v1/schedule with Content-Type: application/json.
Published within 10 minutes. Up to 60 requests an hour per key; sending when your schedule changes is plenty.
With an API key
curl -X PUT https://laneup.au/api/v1/schedule \
-H "Authorization: Bearer lk_…" \
-H "Content-Type: application/json" \
--data @lanes.json
With a signature (recommended)
Generate an Ed25519 key pair and send us only the public key. Nothing secret ever leaves your systems, and a captured request can't be replayed after 5 minutes or used for anything else. We can make signatures mandatory for your organisation.
// Node 18+
import { createHash, createPrivateKey, sign } from 'node:crypto';
const body = JSON.stringify(feed);
const ts = Math.floor(Date.now() / 1000).toString();
const message = ['v1', ts, 'PUT', '/api/v1/schedule', createHash('sha256').update(body).digest('hex')].join('\n');
const signature = sign(null, Buffer.from(message), createPrivateKey(privateKeyPem)).toString('base64');
await fetch('https://laneup.au/api/v1/schedule', {
method: 'PUT', body,
headers: { 'Content-Type': 'application/json', 'X-Lane-Key': keyId, 'X-Lane-Timestamp': ts, 'X-Lane-Signature': signature },
});
Responses
| Status | Meaning |
|---|---|
| 200 / 202 | Checked (sandbox) / accepted. The body says what happened to each pool. |
| 400 | Invalid document; problems lists each field and what's wrong. |
| 401 / 403 | Bad credentials / not allowed (not approved yet, suspended, or not your pool). |
| 413 / 415 | Too large / not JSON. |
| 429 | Too many requests; wait for Retry-After seconds. |
GET /api/v1/me with your credentials shows your organisation, status and pool ids.
Safeguards
Keys are stored hashed, can be rotated with no downtime (two keys at once) and revoked straight away. Every request is logged. If an upload looks broken (say most open slots suddenly show closed), we keep showing your last good data until a good upload arrives or we confirm it with you.
By sending data you agree to the data contribution terms.