AI Agent Platform

The event platform agents can actually use.

17 documented tools — 10 read, 7 write, 4 answering without a key — served over REST, described by one OpenAPI document, and mirrored over MCP. Same authorization, same error shape, same rows as the console.

17
Tools
10
Read
7
Write
6
Scopes
Connect over REST/api/agent/v1
# Discover the surface — no credential needed
curl -s https://turnout.teraai.cc/api/agent/v1/tools

# Read the public event feed
curl -s 'https://turnout.teraai.cc/api/agent/v1/events?city=San+Francisco&pageSize=3'

# Call a write tool with a scoped key
curl -s https://turnout.teraai.cc/api/agent/v1/tools/create_event \
  -H "authorization: Bearer $TURNOUT_AGENT_TOKEN" \
  -H 'content-type: application/json' \
  -d '{"name":"Launch night","startsAt":"2027-03-01T19:00:00Z","timezone":"Europe/Berlin","capacity":120}'
Connect over MCPstdio-less · HTTP
{
  "mcpServers": {
    "turnout": {
      "url": "https://turnout.teraai.cc/api/agent/v1/mcp",
      "headers": {
        "authorization": "Bearer $TURNOUT_AGENT_TOKEN"
      }
    }
  }
}

The MCP server exposes the same tool names and arguments. Without a credential it still answers the public read tools, which is enough for search and discovery inside an agent workspace.

Tool catalogue

Every tool, with its schema and its permissions

Generated from the registry on this request. Expand a tool to see the JSON schema the executor validates against, the scopes it needs, and a call you can run.

Searches two sources and returns them in one list, each row tagged with `origin`. "turnout" rows are events an organizer published on Turnout, read live from Turnout's own database — the primary source. "discover" rows are the imported third-party catalogue (San Francisco), subject to its own licence. Own events are listed first. Draft, cancelled, private and fixture events are never returned by either source, so a row an agent sees is a row its public page shows. Fields Turnout does not record (end time, address, city, price, category for own events) are null with a notice, never guessed.

Use it when

Use when you need to know what is happening: to find an organizer's published event to offer a user, to find comparable events, to check whether a date is busy, or to answer a question about a place, category or timeframe.

Not for
  • ✕ Attendance, conversion or demand numbers — neither public source carries them. Use the credentialed analytics tools.
  • ✕ One known slug — use get_event.
Endpoint
/api/agent/v1/tools/discover_events
Version
v1
Scopes
none — public
Idempotency
optional
Side effects
none
Input schema
{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "minLength": 2,
      "maxLength": 120
    },
    "city": {
      "type": "string",
      "minLength": 2,
      "maxLength": 60
    },
    "neighbourhood": {
      "type": "string",
      "minLength": 2,
      "maxLength": 60
    },
    "category": {
      "type": "string",
      "minLength": 2,
      "maxLength": 60
    },
    "dateFrom": {
      "type": "string",
      "minLength": 4,
      "maxLength": 40,
      "description": "ISO 8601 date or timestamp, e.g. 2026-12-01 or 2026-12-01T19:00:00Z"
    },
    "dateTo": {
      "type": "string",
      "minLength": 4,
      "maxLength": 40,
      "description": "ISO 8601 date or timestamp, e.g. 2026-12-01 or 2026-12-01T19:00:00Z"
    },
    "free": {
      "type": "boolean"
    },
    "mode": {
      "type": "string",
      "enum": [
        "in_person",
        "online"
      ]
    },
    "sort": {
      "type": "string",
      "enum": [
        "soonest",
        "latest"
      ]
    },
    "source": {
      "type": "string",
      "enum": [
        "both",
        "turnout",
        "catalogue"
      ]
    },
    "page": {
      "type": "integer",
      "minimum": 1,
      "maximum": 500
    },
    "pageSize": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "description": "Rows per page (1-100)."
    }
  },
  "additionalProperties": false
}
Example call
curl -s https://turnout.teraai.cc/api/agent/v1/tools/discover_events \
  -H 'content-type: application/json' \
  -d '{"query":"pottery","dateFrom":"2026-12-01","pageSize":10}'

Find pottery events in December.

Authorization

Scopes, and what each one unlocks

A credential carries an explicit scope list. Reads are separate from writes, and the two destructive actions carry an extra confirmation.

ScopeWhat it allows
events:readRead public event data (the Discover catalogue) and the organization's own events.
organizers:readRead public organizer profiles.
analytics:readRead the organization's own first-party metrics, including the credential's own call budget.
rsvp:writeCreate a registration on a published event. Records a real participant, so it is never granted by default.
events:writeCreate and change the organization's own events: drafts, edits, publishing and cancelling. Publishing and cancelling also require `confirm: true` on the call.
campaigns:writeDraft a campaign and queue its reminders. Queuing writes reminder rows; nothing is sent by Turnout in this build.

Credentials are issued by an organizer

Keys are minted inside the console, scoped at creation, and revocable at any time. A key that has never been used is also the one that is easiest to remove: every call is logged against it, so usage is visible before you revoke.

  • ▸ Token format and rotation handled server-side
  • ▸ Per-call ledger: tool, status, credential
  • ▸ No scope grants a send action — Turnout does not deliver messages in this build
Sign in to issue a key
Read-only playground

Search the public event feed as an agent would

No key, no writes, no side effects. The panel calls GET /api/agent/v1/events from your browser and shows exactly what comes back — including errors and rate limits.

Live feed · GET /api/agent/v1/eventsidle
EventCityStartsPriceMode
Scope of this playground: it can only read public data — the events organizers have published inside Turnout. Anything that touches an organization's own events, participants or metrics requires a credential with the matching scope, issued inside the console.