← Lane availability

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

  1. 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.
  2. 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.txt containing the token.
    The domain must be the one your pools' official pages are on. If another organisation runs the pool for you (or you for a council), we also need the owner's written OK. Leave the record in place: we re-check it every month, and pause your data if it's gone for three days in a row.
  3. Try the sandbox. You get an API key. Pool 0 is a sandbox: we check what you send and show you how we read it, but never store or publish it.
  4. Shadow period (1–2 weeks). We take your data but don't show it yet, and compare it with what we already have.
  5. 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
        }
      ]
    }
  ]
}
FieldRules
generatedAtWhen 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.
poolIdThe id we give you for each pool; 0 is the sandbox.
totalLanesLap lanes the pool has (1–30).
startLocal time at the pool, YYYY-MM-DDTHH:MM, on a quarter hour. No offset.
minutes15, 30 or 60.
lanes / closedEither 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

StatusMeaning
200 / 202Checked (sandbox) / accepted. The body says what happened to each pool.
400Invalid document; problems lists each field and what's wrong.
401 / 403Bad credentials / not allowed (not approved yet, suspended, or not your pool).
413 / 415Too large / not JSON.
429Too 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.