Skip to content
over55s.au

For developers

Build with over55s.au.

Two integration points for Pro-tier operators: a REST API to read your villages + leads on demand, and a CRM webhook that pushes every qualified lead to your endpoint signed with HMAC-SHA256.

REST API

Read your villages and lead history with a single Bearer token. Use it for ETL into your data warehouse, internal dashboards, or any system that needs the canonical state of your over55s.au presence.

Base URL

https://over55s.au/api/v1

Auth

Bearer o55_live_…

Rate limit

60 req/min

Quickstart

Generate a key from the operator dashboard, then fire your first request:

# List all your villages
curl https://over55s.au/api/v1/listings \
  -H "Authorization: Bearer o55_live_…"

# Just NSW villages, paginated
curl "https://over55s.au/api/v1/listings?state=NSW&limit=20" \
  -H "Authorization: Bearer o55_live_…"

# All tour-intent leads received this year
curl "https://over55s.au/api/v1/leads?since=2026-01-01&intent=tour" \
  -H "Authorization: Bearer o55_live_…"

Endpoints

GET/api/v1/listings

All listings owned by the authenticated operator.

Query parameters

stateNSW / VIC / QLD / WA / SA / TAS / ACT / NT
tierfree | standard | featured
limitpage size (default 50, max 200)
offsetpagination offset

Response 200

{
  "listings": [
    {
      "id": "uuid",
      "name": "Aveo Newstead",
      "slug": "aveo-newstead",
      "state": "QLD",
      "postcode": "4006",
      "tier": "featured",
      "address": "10 Sample St",
      "phone": "07 1234 5678",
      "email": "...",
      "website": "https://...",
      "verified": true,
      "suburb": { "name": "Newstead", "slug": "newstead" },
      "url": "https://over55s.au/village/qld/newstead/aveo-newstead"
    }
  ],
  "pagination": { "total": 17, "limit": 50, "offset": 0, "has_more": false }
}
GET/api/v1/leads

Leads received across all your listings. Use ?since= for incremental ETL.

Query parameters

sinceISO date — only leads on/after this
listing_idUUID — filter to one village
intenttour | info_pack | vacancy | general
statusnew | sent | reviewed | disputed | invalid
limitpage size (default 50, max 200)
offsetpagination offset

Response 200

{
  "leads": [
    {
      "id": "uuid",
      "listing_id": "uuid",
      "source": "ai_agent_qualify",
      "intent": "tour",
      "contact": {
        "name": "Jane Sample",
        "email": "jane@example.com",
        "phone": "+61400000000"
      },
      "resident_age_years": 72,
      "start_date": "2026-08-01",
      "notes": "[AI-qualified enquiry]...",
      "status": "sent",
      "ai_qualified": true,
      "received_at": "2026-05-21T03:15:42.103Z"
    }
  ],
  "pagination": { "total": 1, "limit": 50, "offset": 0, "has_more": false }
}

Response headers

  • X-RateLimit-Limit — your current ceiling (default 60/min)
  • X-RateLimit-Remaining — requests left in this 60s window
  • X-API-Key-Prefix — first 12 chars of the key used (audit aid)

Error format

{
  "error": {
    "code": "missing_credentials" | "invalid" | "expired" | "revoked"
          | "pro_tier_required" | "rate_limited" | "internal_error",
    "message": "Human-readable explanation"
  }
}

CRM webhook

Every qualified lead also POSTs to your CRM as a signed HTTPS request. Configure the URL in the operator dashboard, and verify the HMAC-SHA256 signature on receipt.

Payload

POST <your-url>
Content-Type: application/json
User-Agent: over55s-webhook/1.0
X-Over55s-Event: lead.created
X-Over55s-Signature: sha256=<hex>

{
  "event": "lead.created",
  "timestamp": "2026-05-21T03:15:42.103Z",
  "qualified_by": "ai_agent" | "form",
  "listing": {
    "id": "uuid",
    "slug": "village-slug",
    "name": "Village Name",
    "state": "NSW",
    "suburb": "Suburb"
  },
  "lead": {
    "id": "uuid",
    "intent": "tour" | "info_pack" | "vacancy" | "general",
    "name": "Jane Sample",
    "email": "jane@example.com",
    "phone": "+61400000000",
    "resident_age_years": 72,
    "start_date": "2026-08-01",
    "notes": "Free-text from the AI conversation or form"
  }
}

Verifying signatures

Re-compute HMAC-SHA256 of the raw request body using your stored secret, then compare to the X-Over55s-Signature header with constant-time equality:

// Node.js
import crypto from 'crypto';

function verify(rawBody, headerSig, secret) {
  const expected = 'sha256=' +
    crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(headerSig)
  );
}
# Python
import hmac, hashlib

def verify(raw_body: bytes, header_sig: str, secret: str) -> bool:
    expected = 'sha256=' + hmac.new(
        secret.encode(), raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, header_sig)

Delivery + retry

  • Your endpoint should return 2xx within 8 seconds.
  • On 5xx or timeout we retry after 1s, then 5s (3 attempts total).
  • On 4xx we stop — your endpoint rejected the payload.
  • Every attempt is recorded in your dashboard's delivery log.

Both features are Pro-tier ($199/mo)

You can generate keys and configure webhooks on any tier so your engineering team can prepare the integration. The dispatcher only fires on listings that are actually on Pro.

Spotted a bug or need a feature not listed? hey@over55s.au