Skip to main content
Reference · v1

API Reference

Base URL https://curateone.ai/api/v1 — JSON in, JSON out, bearer-key auth on every call.

Account

Who the key belongs to, and how many AI credits remain.

GET/me

Retrieve the account

Returns the account behind the presented API key, its plan, and the current billing period's credit usage. Use it as the canonical "is my key working?" probe.

Request
curl https://curateone.ai/api/v1/me \
  -H "Authorization: Bearer co_live_…"
Response
{
  "account": {
    "id": "acc_8f31…",
    "name": "Akino Studio",
    "email": "owner@example.com",
    "plan": "pro",
    "createdAt": 1750757400000
  },
  "usage": { "used": 14, "limit": 100, "remaining": 86, "bonusTokens": 25 }
}

Sites

Every website on the account — list them, inspect one, or generate a new one.

GET/sites

List sites

All sites on the account, newest first. `status` is draft, provisioning, or live; `url` is set once the site's subdomain is fully live (SSL + content checks passed).

Request
curl https://curateone.ai/api/v1/sites \
  -H "Authorization: Bearer co_live_…"
Response
{
  "sites": [
    {
      "id": "prj_ax92…",
      "name": "Billu Barber",
      "status": "live",
      "url": "https://billu-barber.curateone.ai",
      "customDomain": null,
      "pages": 5,
      "createdAt": 1751189000000,
      "updatedAt": 1752598000000
    }
  ]
}
POST/sites5 AI credits

Generate a site

Starts a full AI website generation as a background job and returns 202 with a job id. Poll GET /jobs/{jobId} until the job is terminal. Costs 5 AI credits (the same as a site build in the Studio), reserved up front and refunded automatically if the job fails or is cancelled. Builds share the Studio's per-account generation limit: a short burst, then a slow hourly refill — past it the call answers 429 rate_limited with Retry-After.

Body parameters

businessNamerequiredstringThe business the site is for.
industryrequiredstringIndustry or category, e.g. "barber shop", "SaaS analytics".
audiencestringWho the site should speak to.
goalsstringWhat the site should achieve (bookings, signups, calls…).
personalitystringBrand personality cues, e.g. "premium, playful".
competitorsstringCompetitor names or URLs to differentiate from.
existingUrlstringAn existing website to draw context from.
Request
curl -X POST https://curateone.ai/api/v1/sites \
  -H "Authorization: Bearer co_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "businessName": "Billu Barber",
    "industry": "barber shop",
    "audience": "young professionals in Indiranagar",
    "goals": "walk-in bookings"
  }'
Response
{ "jobId": "job_k2f8…" }
GET/sites/{id}

Retrieve a site

One site by id. Returns 404 for sites that don't exist or belong to another account.

Request
curl https://curateone.ai/api/v1/sites/prj_ax92… \
  -H "Authorization: Bearer co_live_…"
Response
{
  "site": {
    "id": "prj_ax92…",
    "name": "Billu Barber",
    "status": "live",
    "url": "https://billu-barber.curateone.ai",
    "customDomain": null,
    "pages": 5,
    "createdAt": 1751189000000,
    "updatedAt": 1752598000000
  }
}

Generation jobs

Track a POST /sites generation from queued to live-editable.

GET/jobs/{id}

Poll a job

The job's current status: pending, running, completed, failed, or cancelled. Poll every 3–5 seconds. On completed, `siteId` is set — the generated site is then available via GET /sites/{siteId}. Failed and cancelled jobs refund their reserved credits automatically.

Request
curl https://curateone.ai/api/v1/jobs/job_k2f8… \
  -H "Authorization: Bearer co_live_…"
Response
{
  "job": {
    "id": "job_k2f8…",
    "status": "running",
    "progress": 62,
    "stage": "Composing pages",
    "siteId": null,
    "error": null
  }
}
DELETE/jobs/{id}

Cancel a job

Cancels a queued or running generation and refunds the reserved credits. Idempotent — cancelling a finished job returns its terminal state unchanged.

Request
curl -X DELETE https://curateone.ai/api/v1/jobs/job_k2f8… \
  -H "Authorization: Bearer co_live_…"
Response
{
  "job": { "id": "job_k2f8…", "status": "cancelled", "progress": 62, "stage": "Cancelled", "siteId": null, "error": null }
}

Leads

Form submissions captured on your live sites, with CRM status.

GET/sites/{id}/leads

List leads

The site's captured leads, newest first. Sync them into your own CRM, or use webhooks (see the Webhooks guide) for push instead of pull.

Query parameters

statusstringFilter: new, contacted, qualified, won, or lost.
limitnumberPage size, 1–200. Default 50.
skipnumberOffset for pagination. Default 0.
Request
curl "https://curateone.ai/api/v1/sites/prj_ax92…/leads?status=new&limit=50" \
  -H "Authorization: Bearer co_live_…"
Response
{
  "leads": [
    {
      "id": "led_77ab…",
      "name": "Priya S",
      "email": "priya@example.com",
      "phone": "+91 98…",
      "message": "Do you take Sunday appointments?",
      "status": "new",
      "source": "/contact",
      "createdAt": 1752600000000
    }
  ],
  "total": 1
}

Events

The site's events page — list and create events, and read who has registered.

GET/sites/{id}/events

List events

The site's events, soonest first (most recent first for `when=past`). `confirmedSeats` counts confirmed registrations; `url` is the event's path on the site.

Query parameters

whenstringupcoming, past, or all (default).
statusstringFilter: published or draft.
limitnumberPage size, 1–200. Default 50.
skipnumberOffset for pagination. Default 0.
Request
curl "https://curateone.ai/api/v1/sites/prj_ax92…/events?when=upcoming" \
  -H "Authorization: Bearer co_live_…"
Response
{
  "events": [
    {
      "id": "3f2c…",
      "slug": "open-studio-day",
      "title": "Open studio day",
      "summary": "Try the wheel with our potters.",
      "startsAt": 1760000000000,
      "endsAt": 1760014400000,
      "timezone": "Asia/Kolkata",
      "venueName": "The studio",
      "address": null,
      "onlineUrl": null,
      "priceLabel": "Free",
      "capacity": 30,
      "registrationEnabled": true,
      "confirmedSeats": 12,
      "status": "published",
      "url": "/events/open-studio-day",
      "createdAt": 1752600000000,
      "updatedAt": 1752600000000
    }
  ],
  "total": 1
}
POST/sites/{id}/events

Create an event

Creates an event and returns 201 with it. Saved as a draft unless `status` is "published", so a calendar sync never puts a half-mapped event on the live site.

Body parameters

titlerequiredstringThe event's name.
startsAtrequirednumber | stringStart time: epoch milliseconds or an ISO-8601 string.
endsAtnumber | stringEnd time, same formats.
timezonestringIANA time zone, e.g. "Asia/Kolkata".
venueNamestringWhere it happens.
addressstringStreet address.
mapUrlstringA map link for the venue.
onlineUrlstringJoin link for an online event.
summarystringOne or two lines for listings.
descriptionMarkdownstringThe full description, in Markdown.
priceLabelstringFree text, e.g. "Free" or "₹500".
capacitynumberSeats available; omit for unlimited.
registrationEnabledbooleanAccept registrations. Default true.
statusstringdraft (default) or published.
Request
curl -X POST https://curateone.ai/api/v1/sites/prj_ax92…/events \
  -H "Authorization: Bearer co_live_…" \
  -H "Content-Type: application/json" \
  -d '{ "title": "Open studio day", "startsAt": "2026-11-02T10:00:00+05:30", "capacity": 30 }'
Response
{ "event": { "id": "3f2c…", "slug": "open-studio-day", "title": "Open studio day", "status": "draft", "url": "/events/open-studio-day" } }
GET/sites/{id}/events/{eventId}/registrations

List registrations

Who has registered for an event. This is attendees' personal data (names, emails, phone numbers), returned only to the account that owns the site.

Query parameters

statusstringFilter: confirmed, waitlisted, or cancelled.
limitnumberPage size, 1–200. Default 100.
skipnumberOffset for pagination. Default 0.
Request
curl "https://curateone.ai/api/v1/sites/prj_ax92…/events/3f2c…/registrations?status=confirmed" \
  -H "Authorization: Bearer co_live_…"
Response
{
  "registrations": [
    {
      "id": "9a1d…",
      "name": "Priya S",
      "email": "priya@example.com",
      "phone": null,
      "seats": 2,
      "message": null,
      "fields": null,
      "status": "confirmed",
      "createdAt": 1752600000000
    }
  ],
  "total": 1,
  "confirmedSeats": 12
}

Analytics

Cookieless first-party analytics for any site on the account.

GET/sites/{id}/analytics

Retrieve analytics

Traffic summary for the chosen range: pageviews, uniques, CTA clicks, form funnel, conversion, daily series, top pages/referrers, and privacy-safe device/country/language breakdowns.

Query parameters

rangestring7d, 30d (default), or 90d.
Request
curl "https://curateone.ai/api/v1/sites/prj_ax92…/analytics?range=30d" \
  -H "Authorization: Bearer co_live_…"
Response
{
  "analytics": {
    "range": 30,
    "pageviews": 1284,
    "uniques": 902,
    "ctaClicks": 187,
    "formViews": 240,
    "formSubmits": 41,
    "leads": 41,
    "conversion": 3.2,
    "series": [{ "day": "2026-07-15", "pageviews": 96 }],
    "topPaths": [{ "path": "/", "views": 810 }],
    "topReferrers": [{ "ref": "google.com", "visits": 322 }],
    "devices": [{ "device": "mobile", "views": 884 }],
    "topCountries": [{ "country": "IN", "views": 1030 }],
    "languages": [{ "lang": "en", "views": 1102 }],
    "sources": [{ "source": "organic", "views": 640 }]
  }
}