API Reference

All public REST endpoints used by the Statiq widget script.

ℹ Authentication: None. All endpoints are public. CORS is restricted by the Allowed Origins setting per site (Dashboard → Settings). Set your site's domain there in production.

Events

GET /api/v1/sites/{site_key}/events

Returns all upcoming and recent events for the site.

{
  "events": [
    {
      "id": 1,
      "title": "Team Meetup",
      "description": "Monthly all-hands.",
      "location": "Conference Room A",
      "starts_at": "2026-06-15T14:00:00Z",
      "ends_at": "2026-06-15T16:00:00Z"
    }
  ]
}

Announcements

GET /api/v1/sites/{site_key}/announcements?limit={n}

Returns published announcements, newest first. limit defaults to 10. Only announcements with a publish date in the past (or no publish date) are returned.

{
  "announcements": [
    {
      "id": 1,
      "title": "New feature: Gallery",
      "body": "<p>We just launched the gallery widget.</p>",
      "published_at": "2026-05-01T00:00:00Z"
    }
  ]
}

Popups

GET /api/v1/sites/{site_key}/popups

Returns active popups (not expired, currently within schedule).

{
  "popups": [
    {
      "id": 1,
      "title": "Get 20% off",
      "body": "Use code SAVE20 at checkout.",
      "cta_text": "Shop now",
      "cta_url": "https://example.com/shop",
      "type": "modal",
      "delay_seconds": 3,
      "frequency": "once_per_session"
    }
  ]
}

Theme

GET /api/v1/sites/{site_key}/theme

Returns the site's widget theme (colours, radius, font). Injected as CSS custom properties by the widget script.

{
  "accent": "#4f46e5",
  "bg": "#ffffff",
  "fg": "#0f172a",
  "border_radius": "12px",
  "font_family": "Inter"
}

Testimonials

GET /api/v1/sites/{site_key}/testimonials?limit={n}

Returns approved testimonials. limit defaults to 6.

{
  "testimonials": [
    {
      "id": 1,
      "name": "Jane Smith",
      "role": "CTO",
      "company": "Acme Corp",
      "body": "Statiq saved us hours every week.",
      "rating": 5,
      "photo_url": ""
    }
  ]
}

FAQ

GET /api/v1/sites/{site_key}/faq

Returns FAQ items ordered by sort order.

{
  "faqs": [
    {
      "id": 1,
      "question": "Do you offer refunds?",
      "answer": "<p>Yes, within 30 days.</p>",
      "sort_order": 0
    }
  ]
}

Business Hours

GET /api/v1/sites/{site_key}/business-hours

Returns the weekly business hours schedule.

{
  "hours": [
    { "day": 1, "open": "09:00", "close": "17:00", "closed": false },
    { "day": 6, "open": "", "close": "", "closed": true },
    { "day": 0, "open": "", "close": "", "closed": true }
  ]
}

Team

GET /api/v1/sites/{site_key}/team

Returns all team members.

{
  "members": [
    {
      "id": 1,
      "name": "Alice Lee",
      "role": "CEO",
      "bio": "Leads product vision.",
      "photo_url": "/media/team/1/1",
      "linkedin_url": "https://linkedin.com/in/alicelee",
      "twitter_url": ""
    }
  ]
}

Map

GET /api/v1/sites/{site_key}/map

Returns the map configuration.

{
  "lat": 51.505,
  "lng": -0.09,
  "label": "Our Office",
  "zoom": 14,
  "style": "street"
}

Social Links

GET /api/v1/sites/{site_key}/social-links

Returns configured social profile URLs.

{
  "links": [
    { "platform": "twitter", "url": "https://twitter.com/example" },
    { "platform": "github",  "url": "https://github.com/example" }
  ]
}

Gallery

GET /api/v1/sites/{site_key}/gallery

Returns gallery images ordered by sort order.

{
  "images": [
    {
      "id": 1,
      "title": "Office",
      "caption": "Our HQ in London.",
      "url": "/media/gallery/1/1",
      "sort_order": 0
    }
  ]
}

Contact Form Config

GET /api/v1/sites/{site_key}/contact-form

Returns the contact form widget configuration (custom labels, required fields).

{
  "name_label": "Your name",
  "email_label": "Email address",
  "message_label": "Message",
  "submit_label": "Send",
  "file_upload_enabled": false
}

Submit Contact Form

POST /api/v1/sites/{site_key}/contact

Submits a contact form entry. Body: multipart/form-data or application/x-www-form-urlencoded with fields name, email, message. Optional: file attachment.

// Success
{ "ok": true }

// Error
{ "error": "email is required" }

Subscribe

POST /api/v1/sites/{site_key}/subscribe

Adds an email subscriber. Body: JSON {"email": "[email protected]"}.

{ "ok": true }

Booking — Services

GET /api/v1/sites/{site_key}/booking/services

Returns bookable services.

{
  "services": [
    {
      "id": 1,
      "name": "30-min Consultation",
      "duration_minutes": 30,
      "price": "50.00",
      "description": "One-on-one strategy session."
    }
  ]
}

Booking — Available Slots

GET /api/v1/sites/{site_key}/booking/slots?service_id={id}&date={YYYY-MM-DD}

Returns available time slots for a service on a given date.

{
  "slots": [
    { "start": "09:00", "end": "09:30" },
    { "start": "10:00", "end": "10:30" }
  ]
}

Booking — Create Appointment

POST /api/v1/sites/{site_key}/booking

Creates a booking. Body: JSON.

// Request
{
  "service_id": 1,
  "date": "2026-06-20",
  "start": "10:00",
  "name": "Jane Smith",
  "email": "[email protected]",
  "phone": "+1 555 0100",
  "notes": "First appointment"
}

// Response
{ "id": 42, "status": "confirmed" }

Analytics Collect

POST /api/v1/sites/{site_key}/collect

Records a page view event. Called automatically by the widget script on each page load. Body: JSON with event, url, referrer.

{ "ok": true }

Media

GET /media/gallery/{site_id}/{image_id}

Serves an uploaded gallery image. Content-Type is detected from file bytes. Cached for 24 hours.

GET /media/team/{site_id}/{member_id}

Serves an uploaded team member photo. Content-Type is detected from file bytes. Cached for 24 hours.