Developer documentation · API version 2026-09-28

Build on Valore

A REST API for everything on your calendar: events, guests, tickets, orders, subscribers and your team. Signed webhooks tell you the moment something happens, and the MCP server lets Claude, Cursor and other assistants work on your events directly.

Base URL
https://valore.app/api/v1
Authentication
Authorization: Bearer vlr_…
Format

JSON, snake_case, UTC timestamps, integer cents.

Getting started

Introduction

Every API key belongs to one calendar, which is Valore's organization unit: a brand, community or team that publishes events. A key sees only that calendar's events, guests and subscribers, and acts as the person who created it. Owners and admins can create keys from Settings → Developers.

REST API

Create events, manage guests and tickets, sync subscribers. Predictable resources, cursor pagination.

Webhooks

Signed HTTPS callbacks for registrations, check-ins, payments and more, retried automatically.

MCP server

Give AI assistants the same powers through the Model Context Protocol, scoped by the same keys.

Send your key as a bearer token on every request. Keys start with vlr_ and are shown once when created; only a hash is stored. Choose read-only when a key only needs to read data: it can call GET endpoints and read-only MCP tools, and nothing else. Revoking a key takes effect immediately.

header
Authorization: Bearer vlr_a1b2c3d4e5f6…

Keep keys server-side. Browsers may call GET endpoints (CORS is enabled), but a key in client code is a key anyone can copy.

  1. Create a key in Settings → Developers for the calendar you want to work with.
  2. List your published events:
export VALORE_API_KEY=vlr_…

curl "https://valore.app/api/v1/events?status=published&limit=5" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  1. Create an event with POST /events, add people with POST /events/:id/guests, and register a webhook to hear about new registrations.
  • Bodies are JSON with Content-Type: application/json. Field names are snake_case; enums are lowercase strings (going, in_person).
  • Single objects come back as { data: {…} }; lists as { data: […], next_cursor }.
  • Timestamps are ISO 8601 in UTC. When creating or updating events you may also send a wall-clock time like 2026-11-05T18:00, interpreted in the event's timezone.
  • Money is integer cents (price_cents: 2500 is $25.00) in the event's currency.
  • PATCH is partial: send only the fields that change. Sending null clears a nullable field.
  • Every response carries X-Request-Id. Include it when you contact support about a request.

Errors use conventional HTTP status codes and a JSON body of the shape { "error": "message" }. Validation messages name the field: starts_at: Invalid date.

400Invalid input. The message names the field, e.g. starts_at: Invalid date.
401Missing, revoked or malformed API key.
403The key is read-only, or the action needs a role the key's owner doesn't have.
404The resource doesn't exist or belongs to another calendar.
409Conflict with current state, e.g. deleting an event that has paid guests.
429Rate limit exceeded. Wait for Retry-After seconds.
500Something went wrong on our side. Retry with backoff; include X-Request-Id when reporting it.

List endpoints return up to limit items (default 25, max 100) and a next_cursor. Pass it back as ?cursor= to fetch the next page; it's null on the last page. Cursors are stable across inserts, so you won't skip or repeat rows while paging.

Node.js · walk every page
let cursor = null;
do {
  const url = new URL("https://valore.app/api/v1/events/EVENT_ID/guests");
  url.searchParams.set("limit", "100");
  if (cursor) url.searchParams.set("cursor", cursor);
  const page = await fetch(url, { headers }).then((r) => r.json());
  for (const guest of page.data) process(guest);
  cursor = page.next_cursor;
} while (cursor);

Each key may make 300 requests per minute. Every response includes X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix seconds). Over the limit you get 429 with a Retry-After header. Bulk endpoints (add guests, invite, import subscribers) accept hundreds of rows per call, so prefer them over loops.

Reference

Resources

All paths are relative to https://valore.app/api/v1. Examples use placeholder ids; every id you need comes back from a list or create call.

GET/me
GET/calendar
PATCH/calendar
GET/events
POST/events
GET/events/:id
PATCH/events/:id
POST/events/:id/publish
POST/events/:id/duplicate
DELETE/events/:id
GET/events/:id/guests
GET/guests
POST/events/:id/guests
GET/guests/:id
PATCH/guests/:id
POST/guests/:id/check-in
DELETE/guests/:id
GET/events/:id/invites
POST/events/:id/invites
GET/events/:id/hosts
POST/events/:id/hosts
DELETE/events/:id/hosts/:hostId
GET/events/:id/ticket-types
POST/events/:id/ticket-types
GET/ticket-types/:id
PATCH/ticket-types/:id
DELETE/ticket-types/:id
GET/events/:id/coupons
POST/events/:id/coupons
GET/coupons/:id
PATCH/coupons/:id
DELETE/coupons/:id
GET/events/:id/questions
POST/events/:id/questions
GET/questions/:id
PATCH/questions/:id
DELETE/questions/:id
GET/events/:id/orders
GET/orders/:id
GET/events/:id/feedback
GET/events/:id/blasts
POST/events/:id/blasts
GET/blasts/:id
POST/blasts/:id/send
GET/subscribers
POST/subscribers
POST/subscribers/import
GET/subscribers/:id
PATCH/subscribers/:id
DELETE/subscribers/:id
GET/team
GET/webhooks
POST/webhooks
GET/webhooks/:id
PATCH/webhooks/:id
DELETE/webhooks/:id
POST/webhooks/:id/test
GET/webhooks/:id/deliveries
POST/webhook-deliveries/:id/redeliver

Key introspection

Find out which calendar and account a key acts as, and its scope.

GET/api/v1/me

Retrieve the current key

Returns { data: Me }.
curl "https://valore.app/api/v1/me" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "key": {
      "id": "key_1",
      "name": "Zapier",
      "prefix": "vlr_a1b2c3d4",
      "scope": "read_write"
    },
    "calendar": {
      "id": "cal_9x1kq2",
      "slug": "sf-ai-builders",
      "name": "SF AI Builders"
    },
    "user": {
      "id": "usr_1",
      "name": "Jordan Reyes",
      "email": "jordan@example.com"
    },
    "rate_limit": {
      "requests_per_minute": 300
    }
  }
}

Calendar

The calendar (organization) this key belongs to. Every other resource is scoped to it.

GET/api/v1/calendar

Retrieve the calendar

Returns { data: Calendar }.
curl "https://valore.app/api/v1/calendar" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "cal_9x1kq2",
    "slug": "sf-ai-builders",
    "name": "SF AI Builders",
    "description": "Monthly demo nights for people shipping AI products.",
    "url": "https://valore.app/sf-ai-builders",
    "avatar_url": "https://…/avatar.jpg",
    "cover_url": null,
    "tint_color": "#18181b",
    "timezone": "America/Los_Angeles",
    "city": "San Francisco",
    "website_url": "https://sfaibuilders.com",
    "is_personal": false,
    "is_verified": true,
    "event_count": 42,
    "subscriber_count": 1830,
    "created_at": "2026-01-12T18:04:00.000Z"
  }
}
PATCH/api/v1/calendar

Update the calendar

Body parameters
name
string
2–80 characters.
description
string
slug
string
Public URL slug.
timezone
string
IANA zone.
city
string
website_url
string
avatar_url
string
cover_url
string
tint_color
string
Hex, e.g. #18181b.
instagram
string
Handle.
x_handle
string
linkedin
string
Returns { data: Calendar }.
curl -X PATCH "https://valore.app/api/v1/calendar" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "description": "Monthly demo nights for people shipping AI products.",
  "city": "San Francisco"
}'
Response · 200
{
  "data": {
    "id": "cal_9x1kq2",
    "slug": "sf-ai-builders",
    "name": "SF AI Builders",
    "description": "Monthly demo nights for people shipping AI products.",
    "url": "https://valore.app/sf-ai-builders",
    "avatar_url": "https://…/avatar.jpg",
    "cover_url": null,
    "tint_color": "#18181b",
    "timezone": "America/Los_Angeles",
    "city": "San Francisco",
    "website_url": "https://sfaibuilders.com",
    "is_personal": false,
    "is_verified": true,
    "event_count": 42,
    "subscriber_count": 1830,
    "created_at": "2026-01-12T18:04:00.000Z"
  }
}

Events

Create, update, publish, duplicate, cancel and delete events.

GET/api/v1/events

List events

  • Sorted by start time, ascending. Includes ticket types.
Query parameters
status
string
draftpublishedcanceled
from
datetime
Events starting at or after this time.
to
datetime
Events starting at or before this time.
limit
integerdefault 25
Page size, 1–100.
cursor
string
The next_cursor from the previous page.
Returns a page of Event objects as { data, next_cursor }.
curl "https://valore.app/api/v1/events?status=draft&from=2026-10-01T00:00:00Z" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "evt_7f3ab1",
      "slug": "demo-night-november",
      "url": "https://valore.app/demo-night-november",
      "calendar_id": "cal_9x1kq2",
      "title": "Demo Night · November",
      "description": "Six teams, five minutes each. Drinks after.",
      "cover_url": "https://…/cover.jpg",
      "status": "published",
      "visibility": "public",
      "starts_at": "2026-11-05T02:00:00.000Z",
      "ends_at": "2026-11-05T05:00:00.000Z",
      "timezone": "America/Los_Angeles",
      "location": {
        "type": "in_person",
        "name": "The Foundry",
        "address": "500 Howard St, San Francisco, CA",
        "city": "San Francisco",
        "region": "CA",
        "country": "US",
        "latitude": 37.788,
        "longitude": -122.396,
        "virtual_url": null
      },
      "category": "tech",
      "tags": [
        "ai",
        "demos"
      ],
      "capacity": 120,
      "require_approval": true,
      "waitlist_enabled": true,
      "registration_open": true,
      "registration_closes_at": null,
      "currency": "usd",
      "ticket_types": [
        {
          "id": "tt_01",
          "event_id": "evt_7f3ab1",
          "name": "General Admission",
          "description": null,
          "price_cents": 0,
          "quantity": null,
          "max_per_order": 1,
          "sales_start_at": null,
          "sales_end_at": null,
          "require_approval": false,
          "hidden": false,
          "sort_order": 0,
          "pricing_mode": "fixed",
          "created_at": "2026-10-01T17:00:00.000Z"
        }
      ],
      "published_at": "2026-10-01T17:00:00.000Z",
      "canceled_at": null,
      "created_at": "2026-10-01T16:58:00.000Z",
      "updated_at": "2026-10-02T09:12:00.000Z"
    }
  ],
  "next_cursor": "evt_7f3ab1"
}
POST/api/v1/events

Create an event

  • The key's owner becomes the first host.
  • A default ticket type is created: free, or priced at price_cents.
Body parameters
title
stringrequired
Up to 200 characters.
starts_at
datetimerequired
ISO 8601 with offset, or a wall-clock time (2026-11-05T18:00) interpreted in timezone.
ends_at
datetime
Defaults to two hours after starts_at.
timezone
string
IANA zone, e.g. America/Los_Angeles. Defaults to the calendar's.
description
string
Markdown.
cover_url
string
HTTPS image URL.
status
string
Defaults to published on create.
draftpublished
visibility
string
Private events require an invitation to register.
publicunlistedprivate
location_type
string
Or send a nested location object as returned by the API.
in_personvirtualhybridtbd
location_name
string
Venue name.
address
string
Street address.
city
string
virtual_url
string
Meeting link, revealed to confirmed guests.
capacity
integer
Omit for unlimited.
require_approval
boolean
Registrations land in pending_approval.
waitlist_enabled
boolean
registration_open
boolean
registration_closes_at
datetime
price_cents
integer
Create only: price of the default ticket (0 = free).
currency
stringdefault usd
ISO 4217, lowercase.
category
string
tags
string[]
slug
string
Custom URL slug (3–64 chars, lowercase).
Returns { data: Event } with status 201.
curl -X POST "https://valore.app/api/v1/events" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "title": "Founders Breakfast",
  "starts_at": "2026-11-05T09:00",
  "ends_at": "2026-11-05T11:00",
  "timezone": "America/Los_Angeles",
  "location_type": "in_person",
  "location_name": "Sightglass Coffee",
  "address": "270 7th St, San Francisco, CA",
  "capacity": 40,
  "require_approval": true
}'
Response · 201
{
  "data": {
    "id": "evt_7f3ab1",
    "slug": "demo-night-november",
    "url": "https://valore.app/demo-night-november",
    "calendar_id": "cal_9x1kq2",
    "title": "Demo Night · November",
    "description": "Six teams, five minutes each. Drinks after.",
    "cover_url": "https://…/cover.jpg",
    "status": "published",
    "visibility": "public",
    "starts_at": "2026-11-05T02:00:00.000Z",
    "ends_at": "2026-11-05T05:00:00.000Z",
    "timezone": "America/Los_Angeles",
    "location": {
      "type": "in_person",
      "name": "The Foundry",
      "address": "500 Howard St, San Francisco, CA",
      "city": "San Francisco",
      "region": "CA",
      "country": "US",
      "latitude": 37.788,
      "longitude": -122.396,
      "virtual_url": null
    },
    "category": "tech",
    "tags": [
      "ai",
      "demos"
    ],
    "capacity": 120,
    "require_approval": true,
    "waitlist_enabled": true,
    "registration_open": true,
    "registration_closes_at": null,
    "currency": "usd",
    "ticket_types": [
      {
        "id": "tt_01",
        "event_id": "evt_7f3ab1",
        "name": "General Admission",
        "description": null,
        "price_cents": 0,
        "quantity": null,
        "max_per_order": 1,
        "sales_start_at": null,
        "sales_end_at": null,
        "require_approval": false,
        "hidden": false,
        "sort_order": 0,
        "pricing_mode": "fixed",
        "created_at": "2026-10-01T17:00:00.000Z"
      }
    ],
    "published_at": "2026-10-01T17:00:00.000Z",
    "canceled_at": null,
    "created_at": "2026-10-01T16:58:00.000Z",
    "updated_at": "2026-10-02T09:12:00.000Z"
  }
}
GET/api/v1/events/:id

Retrieve an event

  • Includes live guest stats.
Returns { data: EventWithStats }.
curl "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "evt_7f3ab1",
    "slug": "demo-night-november",
    "url": "https://valore.app/demo-night-november",
    "calendar_id": "cal_9x1kq2",
    "title": "Demo Night · November",
    "description": "Six teams, five minutes each. Drinks after.",
    "cover_url": "https://…/cover.jpg",
    "status": "published",
    "visibility": "public",
    "starts_at": "2026-11-05T02:00:00.000Z",
    "ends_at": "2026-11-05T05:00:00.000Z",
    "timezone": "America/Los_Angeles",
    "location": {
      "type": "in_person",
      "name": "The Foundry",
      "address": "500 Howard St, San Francisco, CA",
      "city": "San Francisco",
      "region": "CA",
      "country": "US",
      "latitude": 37.788,
      "longitude": -122.396,
      "virtual_url": null
    },
    "category": "tech",
    "tags": [
      "ai",
      "demos"
    ],
    "capacity": 120,
    "require_approval": true,
    "waitlist_enabled": true,
    "registration_open": true,
    "registration_closes_at": null,
    "currency": "usd",
    "ticket_types": [
      {
        "id": "tt_01",
        "event_id": "evt_7f3ab1",
        "name": "General Admission",
        "description": null,
        "price_cents": 0,
        "quantity": null,
        "max_per_order": 1,
        "sales_start_at": null,
        "sales_end_at": null,
        "require_approval": false,
        "hidden": false,
        "sort_order": 0,
        "pricing_mode": "fixed",
        "created_at": "2026-10-01T17:00:00.000Z"
      }
    ],
    "published_at": "2026-10-01T17:00:00.000Z",
    "canceled_at": null,
    "created_at": "2026-10-01T16:58:00.000Z",
    "updated_at": "2026-10-02T09:12:00.000Z",
    "stats": {
      "going": 84,
      "pending_approval": 6,
      "waitlist": 0,
      "invited": 12,
      "declined": 2,
      "not_going": 3,
      "checked_in": 0,
      "capacity": 120,
      "spots_left": 36,
      "revenue_cents": 0,
      "page_views": 1412
    }
  }
}
PATCH/api/v1/events/:id

Update an event

Body parameters
title
stringrequired
Up to 200 characters.
starts_at
datetimerequired
ISO 8601 with offset, or a wall-clock time (2026-11-05T18:00) interpreted in timezone.
ends_at
datetime
Defaults to two hours after starts_at.
timezone
string
IANA zone, e.g. America/Los_Angeles. Defaults to the calendar's.
description
string
Markdown.
cover_url
string
HTTPS image URL.
status
string
Defaults to published on create.
draftpublished
visibility
string
Private events require an invitation to register.
publicunlistedprivate
location_type
string
Or send a nested location object as returned by the API.
in_personvirtualhybridtbd
location_name
string
Venue name.
address
string
Street address.
city
string
virtual_url
string
Meeting link, revealed to confirmed guests.
capacity
integer
Omit for unlimited.
require_approval
boolean
Registrations land in pending_approval.
waitlist_enabled
boolean
registration_open
boolean
registration_closes_at
datetime
currency
stringdefault usd
ISO 4217, lowercase.
category
string
tags
string[]
slug
string
Custom URL slug (3–64 chars, lowercase).
status
string
canceled cancels the event and emails confirmed guests.
draftpublishedcanceled
cancellation_note
string
Included in the cancellation email.
notify_guests
booleandefault true
Email confirmed guests about time/location changes.
Returns { data: EventWithStats }.
curl -X PATCH "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "title": "Founders Breakfast (Vol. 2)",
  "capacity": 60
}'
Response · 200
{
  "data": {
    "id": "evt_7f3ab1",
    "slug": "demo-night-november",
    "url": "https://valore.app/demo-night-november",
    "calendar_id": "cal_9x1kq2",
    "title": "Demo Night · November",
    "description": "Six teams, five minutes each. Drinks after.",
    "cover_url": "https://…/cover.jpg",
    "status": "published",
    "visibility": "public",
    "starts_at": "2026-11-05T02:00:00.000Z",
    "ends_at": "2026-11-05T05:00:00.000Z",
    "timezone": "America/Los_Angeles",
    "location": {
      "type": "in_person",
      "name": "The Foundry",
      "address": "500 Howard St, San Francisco, CA",
      "city": "San Francisco",
      "region": "CA",
      "country": "US",
      "latitude": 37.788,
      "longitude": -122.396,
      "virtual_url": null
    },
    "category": "tech",
    "tags": [
      "ai",
      "demos"
    ],
    "capacity": 120,
    "require_approval": true,
    "waitlist_enabled": true,
    "registration_open": true,
    "registration_closes_at": null,
    "currency": "usd",
    "ticket_types": [
      {
        "id": "tt_01",
        "event_id": "evt_7f3ab1",
        "name": "General Admission",
        "description": null,
        "price_cents": 0,
        "quantity": null,
        "max_per_order": 1,
        "sales_start_at": null,
        "sales_end_at": null,
        "require_approval": false,
        "hidden": false,
        "sort_order": 0,
        "pricing_mode": "fixed",
        "created_at": "2026-10-01T17:00:00.000Z"
      }
    ],
    "published_at": "2026-10-01T17:00:00.000Z",
    "canceled_at": null,
    "created_at": "2026-10-01T16:58:00.000Z",
    "updated_at": "2026-10-02T09:12:00.000Z",
    "stats": {
      "going": 84,
      "pending_approval": 6,
      "waitlist": 0,
      "invited": 12,
      "declined": 2,
      "not_going": 3,
      "checked_in": 0,
      "capacity": 120,
      "spots_left": 36,
      "revenue_cents": 0,
      "page_views": 1412
    }
  }
}
POST/api/v1/events/:id/publish

Publish a draft

Returns { data: Event }.
curl -X POST "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/publish" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "evt_7f3ab1",
    "slug": "demo-night-november",
    "url": "https://valore.app/demo-night-november",
    "calendar_id": "cal_9x1kq2",
    "title": "Demo Night · November",
    "description": "Six teams, five minutes each. Drinks after.",
    "cover_url": "https://…/cover.jpg",
    "status": "published",
    "visibility": "public",
    "starts_at": "2026-11-05T02:00:00.000Z",
    "ends_at": "2026-11-05T05:00:00.000Z",
    "timezone": "America/Los_Angeles",
    "location": {
      "type": "in_person",
      "name": "The Foundry",
      "address": "500 Howard St, San Francisco, CA",
      "city": "San Francisco",
      "region": "CA",
      "country": "US",
      "latitude": 37.788,
      "longitude": -122.396,
      "virtual_url": null
    },
    "category": "tech",
    "tags": [
      "ai",
      "demos"
    ],
    "capacity": 120,
    "require_approval": true,
    "waitlist_enabled": true,
    "registration_open": true,
    "registration_closes_at": null,
    "currency": "usd",
    "ticket_types": [
      {
        "id": "tt_01",
        "event_id": "evt_7f3ab1",
        "name": "General Admission",
        "description": null,
        "price_cents": 0,
        "quantity": null,
        "max_per_order": 1,
        "sales_start_at": null,
        "sales_end_at": null,
        "require_approval": false,
        "hidden": false,
        "sort_order": 0,
        "pricing_mode": "fixed",
        "created_at": "2026-10-01T17:00:00.000Z"
      }
    ],
    "published_at": "2026-10-01T17:00:00.000Z",
    "canceled_at": null,
    "created_at": "2026-10-01T16:58:00.000Z",
    "updated_at": "2026-10-02T09:12:00.000Z"
  }
}
POST/api/v1/events/:id/duplicate

Duplicate an event

  • Copies settings, ticket types, questions and hosts as a new draft. Guests are not copied.
Body parameters
starts_at
datetime
New start (same duration). Defaults to one week later.
title
string
Defaults to the original title.
Returns { data: Event } with status 201.
curl -X POST "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/duplicate" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "starts_at": "2026-12-03T18:00",
  "title": "Demo Night · December"
}'
Response · 201
{
  "data": {
    "id": "evt_7f3ab1",
    "slug": "demo-night-november",
    "url": "https://valore.app/demo-night-november",
    "calendar_id": "cal_9x1kq2",
    "title": "Demo Night · November",
    "description": "Six teams, five minutes each. Drinks after.",
    "cover_url": "https://…/cover.jpg",
    "status": "draft",
    "visibility": "public",
    "starts_at": "2026-11-05T02:00:00.000Z",
    "ends_at": "2026-11-05T05:00:00.000Z",
    "timezone": "America/Los_Angeles",
    "location": {
      "type": "in_person",
      "name": "The Foundry",
      "address": "500 Howard St, San Francisco, CA",
      "city": "San Francisco",
      "region": "CA",
      "country": "US",
      "latitude": 37.788,
      "longitude": -122.396,
      "virtual_url": null
    },
    "category": "tech",
    "tags": [
      "ai",
      "demos"
    ],
    "capacity": 120,
    "require_approval": true,
    "waitlist_enabled": true,
    "registration_open": true,
    "registration_closes_at": null,
    "currency": "usd",
    "ticket_types": [
      {
        "id": "tt_01",
        "event_id": "evt_7f3ab1",
        "name": "General Admission",
        "description": null,
        "price_cents": 0,
        "quantity": null,
        "max_per_order": 1,
        "sales_start_at": null,
        "sales_end_at": null,
        "require_approval": false,
        "hidden": false,
        "sort_order": 0,
        "pricing_mode": "fixed",
        "created_at": "2026-10-01T17:00:00.000Z"
      }
    ],
    "published_at": "2026-10-01T17:00:00.000Z",
    "canceled_at": null,
    "created_at": "2026-10-01T16:58:00.000Z",
    "updated_at": "2026-10-02T09:12:00.000Z"
  }
}
DELETE/api/v1/events/:id

Delete an event

  • Refused (409) when anyone has paid. Cancel with refunds instead.
Returns { data }.
curl -X DELETE "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "evt_7f3ab1",
    "deleted": true
  }
}

Guests

Registrations for an event: approve, decline, waitlist, check in, add or remove people.

GET/api/v1/events/:id/guests

List an event's guests

Query parameters
status
string
goingpending_approvalwaitlistinviteddeclinednot_going
limit
integerdefault 25
Page size, 1–100.
cursor
string
The next_cursor from the previous page.
Returns a page of Guest objects as { data, next_cursor }.
curl "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/guests?status=going" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "gst_2c9d10",
      "event_id": "evt_7f3ab1",
      "name": "Ada Lovelace",
      "email": "ada@example.com",
      "phone": null,
      "status": "going",
      "quantity": 1,
      "ticket_type_id": "tt_01",
      "answers": {
        "company": "Analytical Engines Ltd"
      },
      "amount_cents": 0,
      "currency": "usd",
      "payment_status": "none",
      "checked_in_at": null,
      "registered_at": "2026-10-03T21:14:09.000Z",
      "source": "page",
      "plus_ones": 0,
      "plus_one_names": [],
      "fee_cents": 0,
      "tax_cents": 0,
      "refunded_cents": 0
    }
  ],
  "next_cursor": "gst_2c9d10"
}
GET/api/v1/guests

Search guests across the calendar

Query parameters
email
email
Exact match.
q
string
Name or email contains.
status
string
goingpending_approvalwaitlistinviteddeclinednot_going
event_id
string
limit
integerdefault 25
Page size, 1–100.
cursor
string
The next_cursor from the previous page.
Returns a page of Guest objects as { data, next_cursor }.
curl "https://valore.app/api/v1/guests?email=ada@example.com&q=demo" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "gst_2c9d10",
      "event_id": "evt_7f3ab1",
      "name": "Ada Lovelace",
      "email": "ada@example.com",
      "phone": null,
      "status": "going",
      "quantity": 1,
      "ticket_type_id": "tt_01",
      "answers": {
        "company": "Analytical Engines Ltd"
      },
      "amount_cents": 0,
      "currency": "usd",
      "payment_status": "none",
      "checked_in_at": null,
      "registered_at": "2026-10-03T21:14:09.000Z",
      "source": "page",
      "plus_ones": 0,
      "plus_one_names": [],
      "fee_cents": 0,
      "tax_cents": 0,
      "refunded_cents": 0
    }
  ],
  "next_cursor": "gst_2c9d10"
}
POST/api/v1/events/:id/guests

Add guests directly

  • Guests are added as going and skip approval and capacity checks. Existing guests are returned unchanged.
Body parameters
guests
object[]required
Up to 500 { email, name? } objects.
notify
booleandefault true
Send the confirmation email.
Returns { data: Guest[] } with status 201.
curl -X POST "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/guests" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "guests": [
    {
      "email": "ada@example.com",
      "name": "Ada Lovelace"
    }
  ],
  "notify": true
}'
Response · 201
{
  "data": [
    {
      "id": "gst_2c9d10",
      "event_id": "evt_7f3ab1",
      "name": "Ada Lovelace",
      "email": "ada@example.com",
      "phone": null,
      "status": "going",
      "quantity": 1,
      "ticket_type_id": "tt_01",
      "answers": {
        "company": "Analytical Engines Ltd"
      },
      "amount_cents": 0,
      "currency": "usd",
      "payment_status": "none",
      "checked_in_at": null,
      "registered_at": "2026-10-03T21:14:09.000Z",
      "source": "page",
      "plus_ones": 0,
      "plus_one_names": [],
      "fee_cents": 0,
      "tax_cents": 0,
      "refunded_cents": 0
    }
  ]
}
GET/api/v1/guests/:id

Retrieve a guest

Returns { data: Guest }.
curl "https://valore.app/api/v1/guests/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "gst_2c9d10",
    "event_id": "evt_7f3ab1",
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "phone": null,
    "status": "going",
    "quantity": 1,
    "ticket_type_id": "tt_01",
    "answers": {
      "company": "Analytical Engines Ltd"
    },
    "amount_cents": 0,
    "currency": "usd",
    "payment_status": "none",
    "checked_in_at": null,
    "registered_at": "2026-10-03T21:14:09.000Z",
    "source": "page",
    "plus_ones": 0,
    "plus_one_names": [],
    "fee_cents": 0,
    "tax_cents": 0,
    "refunded_cents": 0
  }
}
PATCH/api/v1/guests/:id

Update a guest

  • Approving a guest who still owes payment keeps them pending with payment_status: "pending" until they pay.
Body parameters
status
string
Approve (going), decline, waitlist…
goingpending_approvalwaitlistinviteddeclinednot_going
notify
booleandefault true
Email the guest about the status change.
note
string
Message included in the email.
refund
boolean
Refund a paid guest being declined or removed.
name
string
phone
string
host_note
string
Private note visible to hosts only.
Returns { data: Guest }.
curl -X PATCH "https://valore.app/api/v1/guests/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "status": "going"
}'
Response · 200
{
  "data": {
    "id": "gst_2c9d10",
    "event_id": "evt_7f3ab1",
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "phone": null,
    "status": "going",
    "quantity": 1,
    "ticket_type_id": "tt_01",
    "answers": {
      "company": "Analytical Engines Ltd"
    },
    "amount_cents": 0,
    "currency": "usd",
    "payment_status": "none",
    "checked_in_at": null,
    "registered_at": "2026-10-03T21:14:09.000Z",
    "source": "page",
    "plus_ones": 0,
    "plus_one_names": [],
    "fee_cents": 0,
    "tax_cents": 0,
    "refunded_cents": 0
  }
}
POST/api/v1/guests/:id/check-in

Check a guest in

  • Only going guests can be checked in. The response adds already_checked_in.
Query parameters
undo
boolean
Reverse a check-in.
Returns { data: Guest }.
curl -X POST "https://valore.app/api/v1/guests/EVENT_OR_RESOURCE_ID/check-in" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "gst_2c9d10",
    "event_id": "evt_7f3ab1",
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "phone": null,
    "status": "going",
    "quantity": 1,
    "ticket_type_id": "tt_01",
    "answers": {
      "company": "Analytical Engines Ltd"
    },
    "amount_cents": 0,
    "currency": "usd",
    "payment_status": "none",
    "checked_in_at": "2026-11-05T02:04:00.000Z",
    "registered_at": "2026-10-03T21:14:09.000Z",
    "source": "page",
    "plus_ones": 0,
    "plus_one_names": [],
    "fee_cents": 0,
    "tax_cents": 0,
    "refunded_cents": 0,
    "already_checked_in": false
  }
}
DELETE/api/v1/guests/:id

Remove a guest

  • Marks them not_going without emailing them.
Query parameters
refund
boolean
Also refund a paid ticket.
Returns { data }.
curl -X DELETE "https://valore.app/api/v1/guests/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "gst_2c9d10",
    "removed": true
  }
}

Invitations

Email invitations to an event, and whether they were opened or accepted.

GET/api/v1/events/:id/invites

List invitations

Query parameters
limit
integerdefault 25
Page size, 1–100.
cursor
string
The next_cursor from the previous page.
Returns a page of Invite objects as { data, next_cursor }.
curl "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/invites" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "inv_5",
      "event_id": "evt_7f3ab1",
      "email": "alan@example.com",
      "name": "Alan",
      "status": "opened",
      "sent_at": "2026-10-02T10:00:00.000Z",
      "opened_at": "2026-10-02T10:42:00.000Z",
      "responded_at": null
    }
  ],
  "next_cursor": "inv_5"
}
POST/api/v1/events/:id/invites

Send invitations

  • Invites come from the key's owner. People already going are skipped. A 10-minute cooldown applies per address.
Body parameters
emails
string[]required
Up to 500 emails or { email, name } objects.
message
string
Personal note in the email (2,000 chars).
Returns { data } with status 201.
curl -X POST "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/invites" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "emails": [
    "grace@example.com",
    {
      "email": "alan@example.com",
      "name": "Alan"
    }
  ],
  "message": "Would love to see you there!"
}'
Response · 201
{
  "data": {
    "sent": 2,
    "skipped": 0
  }
}

Hosts & staff

Who runs an event: hosts (shown on the page), managers (hidden) and check-in staff.

GET/api/v1/events/:id/hosts

List hosts

Returns { data: Host[] }.
curl "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/hosts" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "hst_1",
      "event_id": "evt_7f3ab1",
      "email": "grace@example.com",
      "name": "Grace Hopper",
      "role": "host",
      "status": "accepted",
      "user_id": "usr_88",
      "avatar_url": null,
      "created_at": "2026-10-01T17:00:00.000Z"
    }
  ]
}
POST/api/v1/events/:id/hosts

Add a host, manager or checker

  • They're emailed. If they don't have an account yet, access activates when they sign up with that email.
Body parameters
email
emailrequired
name
string
role
stringdefault host
Checkers can only scan tickets.
hostmanagerchecker
Returns { data: Host } with status 201.
curl -X POST "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/hosts" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "email": "grace@example.com",
  "name": "Grace Hopper",
  "role": "host"
}'
Response · 201
{
  "data": {
    "id": "hst_1",
    "event_id": "evt_7f3ab1",
    "email": "grace@example.com",
    "name": "Grace Hopper",
    "role": "host",
    "status": "accepted",
    "user_id": "usr_88",
    "avatar_url": null,
    "created_at": "2026-10-01T17:00:00.000Z"
  }
}
DELETE/api/v1/events/:id/hosts/:hostId

Remove a host

  • An event always keeps at least one host.
Returns { data }.
curl -X DELETE "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/hosts/HOST_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "hst_1",
    "removed": true
  }
}

Ticket types

Free and paid tickets. Prices are integer cents in the event's currency.

GET/api/v1/events/:id/ticket-types

List ticket types

Returns { data: TicketType[] }.
curl "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/ticket-types" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "tt_02",
      "event_id": "evt_7f3ab1",
      "name": "Supporter",
      "description": "Covers a student's ticket.",
      "price_cents": 2500,
      "quantity": 50,
      "max_per_order": 4,
      "sales_start_at": null,
      "sales_end_at": "2026-11-04T23:59:00.000Z",
      "require_approval": false,
      "hidden": false,
      "sort_order": 1,
      "pricing_mode": "fixed",
      "created_at": "2026-10-01T17:05:00.000Z"
    }
  ]
}
POST/api/v1/events/:id/ticket-types

Create a ticket type

Body parameters
name
stringrequired
description
string
price_cents
integerdefault 0
0 = free; paid tickets are at least 50.
quantity
integer
Omit for unlimited.
max_per_order
integerdefault 1
1–20.
sales_start_at
datetime
sales_end_at
datetime
require_approval
boolean
hidden
boolean
Not shown on the event page.
Returns { data: TicketType } with status 201.
curl -X POST "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/ticket-types" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "name": "Supporter",
  "price_cents": 2500,
  "quantity": 50,
  "max_per_order": 4
}'
Response · 201
{
  "data": {
    "id": "tt_02",
    "event_id": "evt_7f3ab1",
    "name": "Supporter",
    "description": "Covers a student's ticket.",
    "price_cents": 2500,
    "quantity": 50,
    "max_per_order": 4,
    "sales_start_at": null,
    "sales_end_at": "2026-11-04T23:59:00.000Z",
    "require_approval": false,
    "hidden": false,
    "sort_order": 1,
    "pricing_mode": "fixed",
    "created_at": "2026-10-01T17:05:00.000Z"
  }
}
GET/api/v1/ticket-types/:id

Retrieve a ticket type

Returns { data: TicketType }.
curl "https://valore.app/api/v1/ticket-types/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "tt_02",
    "event_id": "evt_7f3ab1",
    "name": "Supporter",
    "description": "Covers a student's ticket.",
    "price_cents": 2500,
    "quantity": 50,
    "max_per_order": 4,
    "sales_start_at": null,
    "sales_end_at": "2026-11-04T23:59:00.000Z",
    "require_approval": false,
    "hidden": false,
    "sort_order": 1,
    "pricing_mode": "fixed",
    "created_at": "2026-10-01T17:05:00.000Z"
  }
}
PATCH/api/v1/ticket-types/:id

Update a ticket type

Accepts any field from the create endpoint. Send only what changes.

Returns { data: TicketType }.
curl -X PATCH "https://valore.app/api/v1/ticket-types/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "hidden": true
}'
Response · 200
{
  "data": {
    "id": "tt_02",
    "event_id": "evt_7f3ab1",
    "name": "Supporter",
    "description": "Covers a student's ticket.",
    "price_cents": 2500,
    "quantity": 50,
    "max_per_order": 4,
    "sales_start_at": null,
    "sales_end_at": "2026-11-04T23:59:00.000Z",
    "require_approval": false,
    "hidden": false,
    "sort_order": 1,
    "pricing_mode": "fixed",
    "created_at": "2026-10-01T17:05:00.000Z"
  }
}
DELETE/api/v1/ticket-types/:id

Delete a ticket type

  • Refused while guests hold it (hide it instead) or if it's the event's last ticket type.
Returns { data }.
curl -X DELETE "https://valore.app/api/v1/ticket-types/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "tt_02",
    "deleted": true
  }
}

Coupons

Discount codes for paid tickets.

GET/api/v1/events/:id/coupons

List coupons

Returns { data: Coupon[] }.
curl "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/coupons" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "cpn_3a",
      "event_id": "evt_7f3ab1",
      "code": "FRIENDS20",
      "percent_off": 20,
      "amount_off_cents": null,
      "max_uses": 100,
      "used_count": 12,
      "expires_at": null,
      "active": true,
      "created_at": "2026-10-01T17:06:00.000Z"
    }
  ]
}
POST/api/v1/events/:id/coupons

Create a coupon

Body parameters
code
stringrequired
2–40 chars; letters, numbers, dashes, underscores. Stored uppercase.
percent_off
integer
1–100. Set this or amount_off_cents.
amount_off_cents
integer
max_uses
integer
expires_at
datetime
active
booleandefault true
Returns { data: Coupon } with status 201.
curl -X POST "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/coupons" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "code": "FRIENDS20",
  "percent_off": 20,
  "max_uses": 100
}'
Response · 201
{
  "data": {
    "id": "cpn_3a",
    "event_id": "evt_7f3ab1",
    "code": "FRIENDS20",
    "percent_off": 20,
    "amount_off_cents": null,
    "max_uses": 100,
    "used_count": 12,
    "expires_at": null,
    "active": true,
    "created_at": "2026-10-01T17:06:00.000Z"
  }
}
GET/api/v1/coupons/:id

Retrieve a coupon

Returns { data: Coupon }.
curl "https://valore.app/api/v1/coupons/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "cpn_3a",
    "event_id": "evt_7f3ab1",
    "code": "FRIENDS20",
    "percent_off": 20,
    "amount_off_cents": null,
    "max_uses": 100,
    "used_count": 12,
    "expires_at": null,
    "active": true,
    "created_at": "2026-10-01T17:06:00.000Z"
  }
}
PATCH/api/v1/coupons/:id

Update a coupon

  • The code can't change: deactivate and create a new one.
Returns { data: Coupon }.
curl -X PATCH "https://valore.app/api/v1/coupons/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "active": false
}'
Response · 200
{
  "data": {
    "id": "cpn_3a",
    "event_id": "evt_7f3ab1",
    "code": "FRIENDS20",
    "percent_off": 20,
    "amount_off_cents": null,
    "max_uses": 100,
    "used_count": 12,
    "expires_at": null,
    "active": false,
    "created_at": "2026-10-01T17:06:00.000Z"
  }
}
DELETE/api/v1/coupons/:id

Delete a coupon

Returns { data }.
curl -X DELETE "https://valore.app/api/v1/coupons/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "cpn_3a",
    "deleted": true
  }
}

Registration questions

Questions guests answer when registering. Answers appear on the guest as `answers`.

GET/api/v1/events/:id/questions

List questions

Returns { data: Question[] }.
curl "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/questions" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "q_1",
      "event_id": "evt_7f3ab1",
      "label": "What are you building?",
      "type": "long_text",
      "options": [],
      "required": true,
      "sort_order": 0,
      "created_at": "2026-10-01T17:07:00.000Z"
    }
  ]
}
POST/api/v1/events/:id/questions

Add a question

Body parameters
label
stringrequired
type
stringdefault text
textlong_textselectmulti_selectcheckboxurlphonecompanysocialterms
options
string[]
For select / multi_select.
required
boolean
Returns { data: Question } with status 201.
curl -X POST "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/questions" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "label": "What are you building?",
  "type": "long_text",
  "required": true
}'
Response · 201
{
  "data": {
    "id": "q_1",
    "event_id": "evt_7f3ab1",
    "label": "What are you building?",
    "type": "long_text",
    "options": [],
    "required": true,
    "sort_order": 0,
    "created_at": "2026-10-01T17:07:00.000Z"
  }
}
GET/api/v1/questions/:id

Retrieve a question

Returns { data: Question }.
curl "https://valore.app/api/v1/questions/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "q_1",
    "event_id": "evt_7f3ab1",
    "label": "What are you building?",
    "type": "long_text",
    "options": [],
    "required": true,
    "sort_order": 0,
    "created_at": "2026-10-01T17:07:00.000Z"
  }
}
PATCH/api/v1/questions/:id

Update a question

Returns { data: Question }.
curl -X PATCH "https://valore.app/api/v1/questions/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "required": false
}'
Response · 200
{
  "data": {
    "id": "q_1",
    "event_id": "evt_7f3ab1",
    "label": "What are you building?",
    "type": "long_text",
    "options": [],
    "required": true,
    "sort_order": 0,
    "created_at": "2026-10-01T17:07:00.000Z"
  }
}
DELETE/api/v1/questions/:id

Delete a question

Returns { data }.
curl -X DELETE "https://valore.app/api/v1/questions/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "q_1",
    "deleted": true
  }
}

Orders

Ticket purchases. Amounts are integer cents.

GET/api/v1/events/:id/orders

List orders

Query parameters
status
string
pendingpaidpartially_refundedrefundedfailed
guest_id
string
limit
integerdefault 25
Page size, 1–100.
cursor
string
The next_cursor from the previous page.
Returns a page of Order objects as { data, next_cursor }.
curl "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/orders?status=pending&guest_id=demo" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "ord_9",
      "number": 1042,
      "number_label": "#1042",
      "event_id": "evt_7f3ab1",
      "guest_id": "gst_2c9d10",
      "email": "ada@example.com",
      "name": "Ada Lovelace",
      "status": "paid",
      "subtotal_cents": 2500,
      "discount_cents": 500,
      "fee_cents": 0,
      "tax_cents": 0,
      "total_cents": 2000,
      "refunded_cents": 0,
      "currency": "usd",
      "coupon_code": "FRIENDS20",
      "paid_at": "2026-10-03T21:15:00.000Z",
      "created_at": "2026-10-03T21:14:10.000Z"
    }
  ],
  "next_cursor": "ord_9"
}
GET/api/v1/orders/:id

Retrieve an order

Returns { data: Order }.
curl "https://valore.app/api/v1/orders/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "ord_9",
    "number": 1042,
    "number_label": "#1042",
    "event_id": "evt_7f3ab1",
    "guest_id": "gst_2c9d10",
    "email": "ada@example.com",
    "name": "Ada Lovelace",
    "status": "paid",
    "subtotal_cents": 2500,
    "discount_cents": 500,
    "fee_cents": 0,
    "tax_cents": 0,
    "total_cents": 2000,
    "refunded_cents": 0,
    "currency": "usd",
    "coupon_code": "FRIENDS20",
    "paid_at": "2026-10-03T21:15:00.000Z",
    "created_at": "2026-10-03T21:14:10.000Z"
  }
}

Feedback

Post-event ratings (1–5) and comments.

GET/api/v1/events/:id/feedback

List feedback

  • Adds summary: { count, average_rating }.
Query parameters
limit
integerdefault 25
Page size, 1–100.
cursor
string
The next_cursor from the previous page.
Returns a page of Feedback objects as { data, next_cursor }.
curl "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/feedback" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "fb_1",
      "event_id": "evt_7f3ab1",
      "guest_id": "gst_2c9d10",
      "guest_name": "Ada Lovelace",
      "guest_email": "ada@example.com",
      "rating": 5,
      "comment": "Best demo night yet.",
      "created_at": "2026-11-06T18:00:00.000Z"
    }
  ],
  "next_cursor": null,
  "summary": {
    "count": 31,
    "average_rating": 4.6
  }
}

Blasts

Email updates to an event's guests, written in markdown.

GET/api/v1/events/:id/blasts

List blasts

Query parameters
limit
integerdefault 25
Page size, 1–100.
cursor
string
The next_cursor from the previous page.
Returns a page of Blast objects as { data, next_cursor }.
curl "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/blasts" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "bl_4",
      "event_id": "evt_7f3ab1",
      "calendar_id": null,
      "subject": "Parking + doors at 6",
      "body": "Doors open at **6pm**. Parking is free on Howard after 6.",
      "audience": [
        "going"
      ],
      "status": "sent",
      "channel": "email",
      "scheduled_at": null,
      "sent_at": "2026-11-04T17:00:00.000Z",
      "recipient_count": 84,
      "stats": {
        "delivered": 84,
        "opened": 61,
        "clicked": 9
      },
      "created_at": "2026-11-04T16:55:00.000Z",
      "updated_at": "2026-11-04T17:00:00.000Z"
    }
  ],
  "next_cursor": null
}
POST/api/v1/events/:id/blasts

Create (and optionally send) a blast

  • Without send or scheduled_at the blast is saved as a draft you can send later.
Body parameters
subject
stringrequired
body
stringrequired
Markdown, up to 20,000 characters.
audience
string[]default ["going"]
Who receives it.
goingpending_approvalwaitlistinviteddeclinednot_goingchecked_innot_checked_in
send
booleandefault false
Send immediately.
scheduled_at
datetime
Send later (must be in the future).
Returns { data: Blast } with status 201.
curl -X POST "https://valore.app/api/v1/events/EVENT_OR_RESOURCE_ID/blasts" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "subject": "Parking + doors at 6",
  "body": "Doors open at **6pm**. Parking is free on Howard after 6.",
  "audience": [
    "going"
  ],
  "send": true
}'
Response · 201
{
  "data": {
    "id": "bl_4",
    "event_id": "evt_7f3ab1",
    "calendar_id": null,
    "subject": "Parking + doors at 6",
    "body": "Doors open at **6pm**. Parking is free on Howard after 6.",
    "audience": [
      "going"
    ],
    "status": "sent",
    "channel": "email",
    "scheduled_at": null,
    "sent_at": "2026-11-04T17:00:00.000Z",
    "recipient_count": 84,
    "stats": {
      "delivered": 84,
      "opened": 61,
      "clicked": 9
    },
    "created_at": "2026-11-04T16:55:00.000Z",
    "updated_at": "2026-11-04T17:00:00.000Z"
  }
}
GET/api/v1/blasts/:id

Retrieve a blast

Returns { data: Blast }.
curl "https://valore.app/api/v1/blasts/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "bl_4",
    "event_id": "evt_7f3ab1",
    "calendar_id": null,
    "subject": "Parking + doors at 6",
    "body": "Doors open at **6pm**. Parking is free on Howard after 6.",
    "audience": [
      "going"
    ],
    "status": "sent",
    "channel": "email",
    "scheduled_at": null,
    "sent_at": "2026-11-04T17:00:00.000Z",
    "recipient_count": 84,
    "stats": {
      "delivered": 84,
      "opened": 61,
      "clicked": 9
    },
    "created_at": "2026-11-04T16:55:00.000Z",
    "updated_at": "2026-11-04T17:00:00.000Z"
  }
}
POST/api/v1/blasts/:id/send

Send a draft now

Returns { data: Blast }.
curl -X POST "https://valore.app/api/v1/blasts/EVENT_OR_RESOURCE_ID/send" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "bl_4",
    "event_id": "evt_7f3ab1",
    "calendar_id": null,
    "subject": "Parking + doors at 6",
    "body": "Doors open at **6pm**. Parking is free on Howard after 6.",
    "audience": [
      "going"
    ],
    "status": "sent",
    "channel": "email",
    "scheduled_at": null,
    "sent_at": "2026-11-04T17:00:00.000Z",
    "recipient_count": 84,
    "stats": {
      "delivered": 84,
      "opened": 61,
      "clicked": 9
    },
    "created_at": "2026-11-04T16:55:00.000Z",
    "updated_at": "2026-11-04T17:00:00.000Z"
  }
}

Subscribers

People following the calendar (your newsletter audience).

GET/api/v1/subscribers

List subscribers

Query parameters
status
string
subscribedunsubscribed
limit
integerdefault 25
Page size, 1–100.
cursor
string
The next_cursor from the previous page.
Returns a page of Subscriber objects as { data, next_cursor }.
curl "https://valore.app/api/v1/subscribers?status=subscribed" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "sub_77",
      "email": "linus@example.com",
      "name": "Linus",
      "tags": [
        "newsletter"
      ],
      "status": "subscribed",
      "source": "api",
      "created_at": "2026-10-01T12:00:00.000Z"
    }
  ],
  "next_cursor": "sub_77"
}
POST/api/v1/subscribers

Add a subscriber

  • Someone who unsubscribed stays unsubscribed; only they can opt back in.
Body parameters
email
emailrequired
name
string
tags
string[]
Up to 20 tags (lowercased).
Returns { data: Subscriber } with status 201.
curl -X POST "https://valore.app/api/v1/subscribers" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "email": "linus@example.com",
  "name": "Linus",
  "tags": [
    "newsletter"
  ]
}'
Response · 201
{
  "data": {
    "id": "sub_77",
    "email": "linus@example.com",
    "name": "Linus",
    "tags": [
      "newsletter"
    ],
    "status": "subscribed",
    "source": "api",
    "created_at": "2026-10-01T12:00:00.000Z"
  }
}
POST/api/v1/subscribers/import

Bulk import subscribers

Body parameters
subscribers
object[]required
Up to 5,000 { email, name? } objects.
tags
string[]
Applied to everyone in the batch.
Returns { data } with status 201.
curl -X POST "https://valore.app/api/v1/subscribers/import" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "subscribers": [
    {
      "email": "a@example.com",
      "name": "A"
    },
    {
      "email": "b@example.com"
    }
  ],
  "tags": [
    "import-2026"
  ]
}'
Response · 201
{
  "data": {
    "added": 2,
    "updated": 0,
    "invalid": 0,
    "duplicates": 0,
    "opted_out": 0
  }
}
GET/api/v1/subscribers/:id

Retrieve a subscriber

Returns { data: Subscriber }.
curl "https://valore.app/api/v1/subscribers/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "sub_77",
    "email": "linus@example.com",
    "name": "Linus",
    "tags": [
      "newsletter"
    ],
    "status": "subscribed",
    "source": "api",
    "created_at": "2026-10-01T12:00:00.000Z"
  }
}
PATCH/api/v1/subscribers/:id

Update a subscriber

Body parameters
name
string
tags
string[]
Replaces the tag list.
status
string
Opt them out (honor unsubscribe requests this way).
unsubscribed
Returns { data: Subscriber }.
curl -X PATCH "https://valore.app/api/v1/subscribers/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "tags": [
    "newsletter",
    "vip"
  ]
}'
Response · 200
{
  "data": {
    "id": "sub_77",
    "email": "linus@example.com",
    "name": "Linus",
    "tags": [
      "newsletter"
    ],
    "status": "subscribed",
    "source": "api",
    "created_at": "2026-10-01T12:00:00.000Z"
  }
}
DELETE/api/v1/subscribers/:id

Delete a subscriber

  • Permanent. To honor an opt-out, PATCH status: "unsubscribed" instead.
Returns { data }.
curl -X DELETE "https://valore.app/api/v1/subscribers/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "sub_77",
    "deleted": true
  }
}

Team

People with a role on the calendar: owner, admins and members.

GET/api/v1/team

List team members

Returns { data: Member[] }.
curl "https://valore.app/api/v1/team" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "mem_1",
      "user_id": "usr_88",
      "name": "Grace Hopper",
      "email": "grace@example.com",
      "username": "grace",
      "avatar_url": null,
      "role": "admin",
      "joined_at": "2026-09-28T17:00:00.000Z"
    }
  ]
}

Webhooks

Manage endpoints and inspect deliveries programmatically. See the Webhooks guide for payloads and signatures.

GET/api/v1/webhooks

List webhooks

Returns { data: Webhook[] }.
curl "https://valore.app/api/v1/webhooks" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "wh_1",
      "url": "https://example.com/webhooks/valore",
      "events": [
        "guest.registered",
        "guest.updated"
      ],
      "active": true,
      "last_status": 200,
      "last_error": null,
      "last_sent_at": "2026-10-03T21:14:11.000Z",
      "created_at": "2026-10-01T17:10:00.000Z"
    }
  ]
}
POST/api/v1/webhooks

Create a webhook

  • The response includes secret exactly once. Store it to verify signatures.
Body parameters
url
stringrequired
Public HTTPS endpoint.
events
string[]required
Event names to receive.
Returns { data: Webhook } with status 201.
curl -X POST "https://valore.app/api/v1/webhooks" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/webhooks/valore",
  "events": [
    "guest.registered",
    "guest.updated"
  ]
}'
Response · 201
{
  "data": {
    "id": "wh_1",
    "url": "https://example.com/webhooks/valore",
    "events": [
      "guest.registered",
      "guest.updated"
    ],
    "active": true,
    "last_status": 200,
    "last_error": null,
    "last_sent_at": "2026-10-03T21:14:11.000Z",
    "created_at": "2026-10-01T17:10:00.000Z",
    "secret": "whsec_…"
  }
}
GET/api/v1/webhooks/:id

Retrieve a webhook

Returns { data: Webhook }.
curl "https://valore.app/api/v1/webhooks/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "wh_1",
    "url": "https://example.com/webhooks/valore",
    "events": [
      "guest.registered",
      "guest.updated"
    ],
    "active": true,
    "last_status": 200,
    "last_error": null,
    "last_sent_at": "2026-10-03T21:14:11.000Z",
    "created_at": "2026-10-01T17:10:00.000Z"
  }
}
PATCH/api/v1/webhooks/:id

Update a webhook

Body parameters
url
string
events
string[]
active
boolean
Pause or resume.
rotate_secret
boolean
Issue a new secret (returned once).
Returns { data: Webhook }.
curl -X PATCH "https://valore.app/api/v1/webhooks/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
  -H "Content-Type: application/json" \
  -d '{
  "active": false
}'
Response · 200
{
  "data": {
    "id": "wh_1",
    "url": "https://example.com/webhooks/valore",
    "events": [
      "guest.registered",
      "guest.updated"
    ],
    "active": false,
    "last_status": 200,
    "last_error": null,
    "last_sent_at": "2026-10-03T21:14:11.000Z",
    "created_at": "2026-10-01T17:10:00.000Z"
  }
}
DELETE/api/v1/webhooks/:id

Delete a webhook

Returns { data }.
curl -X DELETE "https://valore.app/api/v1/webhooks/EVENT_OR_RESOURCE_ID" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "wh_1",
    "deleted": true
  }
}
POST/api/v1/webhooks/:id/test

Send a test ping

Returns { data }.
curl -X POST "https://valore.app/api/v1/webhooks/EVENT_OR_RESOURCE_ID/test" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "ok": true,
    "status": 200,
    "error": null
  }
}
GET/api/v1/webhooks/:id/deliveries

List deliveries

Query parameters
limit
integerdefault 25
Page size, 1–100.
cursor
string
The next_cursor from the previous page.
Returns a page of Delivery objects as { data, next_cursor }.
curl "https://valore.app/api/v1/webhooks/EVENT_OR_RESOURCE_ID/deliveries" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "whd_1",
      "webhook_id": "wh_1",
      "event": "guest.registered",
      "status": "succeeded",
      "attempts": 1,
      "response_status": 200,
      "error": null,
      "duration_ms": 212,
      "next_attempt_at": null,
      "delivered_at": "2026-10-03T21:14:11.000Z",
      "created_at": "2026-10-03T21:14:10.000Z",
      "payload": {
        "id": "whd_1",
        "type": "guest.registered",
        "created_at": "2026-10-03T21:14:10.000Z",
        "data": {
          "id": "gst_2c9d10",
          "…": "…"
        }
      }
    }
  ],
  "next_cursor": null
}
POST/api/v1/webhook-deliveries/:id/redeliver

Redeliver

  • Sends the same payload again with a fresh signature.
Returns { data: Delivery }.
curl -X POST "https://valore.app/api/v1/webhook-deliveries/EVENT_OR_RESOURCE_ID/redeliver" \
  -H "Authorization: Bearer $VALORE_API_KEY"
Response · 200
{
  "data": {
    "id": "whd_1",
    "webhook_id": "wh_1",
    "event": "guest.registered",
    "status": "succeeded",
    "attempts": 1,
    "response_status": 200,
    "error": null,
    "duration_ms": 212,
    "next_attempt_at": null,
    "delivered_at": "2026-10-03T21:14:11.000Z",
    "created_at": "2026-10-03T21:14:10.000Z",
    "payload": {
      "id": "whd_1",
      "type": "guest.registered",
      "created_at": "2026-10-03T21:14:10.000Z",
      "data": {
        "id": "gst_2c9d10",
        "…": "…"
      }
    }
  }
}
Guides

Webhooks

Register an HTTPS endpoint in Settings → Developers (or via POST /webhooks) and pick the events you want. Valore POSTs a signed JSON body for each one. Respond with any 2xx within 8 seconds; do the real work asynchronously.

Events

TypeWhen
event.createdA new event is created on this calendar
event.updatedAn event’s details change
event.publishedA draft event goes live
event.canceledAn event is canceled
event.deletedAn event is permanently deleted
guest.registeredSomeone registers or requests to join
guest.updatedA guest’s status changes (approved, declined…)
guest.checked_inA guest is checked in at the door
order.paidA ticket order is paid
order.refundedAn order is refunded (fully or partially)
subscriber.createdSomeone subscribes to the calendar
subscriber.unsubscribedA subscriber opts out
feedback.submittedA guest leaves post-event feedback
pingYou pressed “Send test” or called the test endpoint

Delivery format

Guest, Order and Subscriber payloads use exactly the shapes returned by the REST API. The top-level id is the delivery id: retries reuse it, so store it to make your handler idempotent.

Example delivery
POST /your/endpoint
content-type: application/json
user-agent: Valore-Webhooks/1.0
x-valore-timestamp: 1790000000
x-valore-signature: 5f2b…c9   (hex HMAC-SHA256 of "<timestamp>.<raw body>")

{
  "id": "whd_01j9…",                   // delivery id: use it to de-duplicate retries
  "type": "guest.registered",
  "created_at": "2026-10-01T17:04:12.000Z",
  "data": { "id": "gst_…", "event_id": "evt_…", "name": "Ada Lovelace", "email": "ada@example.com", "status": "going", "…": "…" }
}

Verifying signatures

Each request carries x-valore-timestamp (Unix seconds) and x-valore-signature: the hex HMAC-SHA256 of `${timestamp}.${rawBody}` using the endpoint's signing secret. Verify against the raw body bytes, compare in constant time, and reject timestamps older than a few minutes. Rotating the secret from the dashboard invalidates the old one immediately.

import { createHmac, timingSafeEqual } from "node:crypto";

// Read the RAW request body (before JSON parsing) and pass the headers.
export function verifyValoreWebhook(rawBody, headers, secret = process.env.VALORE_WEBHOOK_SECRET) {
  const timestamp = headers["x-valore-timestamp"];
  const signature = headers["x-valore-signature"];
  if (!timestamp || !signature) return false;
  // Reject requests older than 5 minutes to prevent replays.
  if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
  const expected = createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
  const a = Buffer.from(expected);
  const b = Buffer.from(signature);
  return a.length === b.length && timingSafeEqual(a, b);
}

Retries and monitoring

  • A non-2xx response, a timeout (8s) or a connection error counts as a failure.
  • Failed deliveries are retried after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours (6 attempts in total), then marked failed.
  • Every attempt is logged. Inspect deliveries, see the exact payload and redeliver from the dashboard or with GET /webhooks/:id/deliveries.
  • Endpoints must be public HTTPS URLs. Localhost, private networks and URLs with credentials are rejected. Redirects are not followed.
  • Order of delivery isn't guaranteed across events; use the timestamps and ids in the payload rather than arrival order.

Valore speaks the Model Context Protocol over Streamable HTTP at https://valore.app/api/mcp. Connect Claude Code, Claude Desktop, Cursor or any MCP client with your API key and the assistant can list events, review guests, send invites and more, all scoped to the key's calendar. Read-only keys expose only read tools.

Claude Code
claude mcp add --transport http valore https://valore.app/api/mcp \
  --header "Authorization: Bearer vlr_YOUR_API_KEY"
search_public_eventsread

Search upcoming public events across all of Valore (not limited to your calendar). Matches the title, description, venue and tags; optionally filter by city or category.

list_eventsread

List events on your calendar (the calendar this API key belongs to), sorted by start time. Filter by status or a date range.

get_eventread

Retrieve one event on your calendar with its ticket types and live guest stats (going, pending, waitlist, checked in, revenue, page views).

create_eventwrite

Create an event on your calendar. It's published immediately unless status is "draft". Dates are wall-clock times in `timezone` (or ISO with an offset). Use price_cents for a single paid ticket (omit for free).

update_eventsends email

Change fields on an event (send only what should change). Registered guests are emailed about time/location changes unless notify_guests is false. status "canceled" cancels the event and notifies guests; "published" publishes a draft.

list_guestsread

List an event's guests (registrations, invitees, waitlist). Filter by status, check-in state, or search by name/email.

update_guest_statussends email

Approve, decline, waitlist or otherwise change a guest's status (e.g. status "going" approves a pending guest). The guest is emailed unless notify is false. Approving a guest who owes payment keeps them pending until they pay.

check_in_guestwrite

Mark a confirmed (going) guest as arrived, by guest_id or by the ticket_token from their QR code. undo: true reverses a check-in.

send_invitessends email

Email invitations to an event from the API key owner. People who are already registered are skipped. Up to 500 per call.

create_blastwrite

Draft an email blast. With event_id it goes to that event's guests (audience: guest statuses such as going, pending_approval, waitlist, checked_in, not_checked_in; default going). Without event_id it's a newsletter to your calendar's subscribers (audience: subscriber tags; empty = everyone). Nothing is sent until send_blast, unless scheduled_at is set.

send_blastsends email

Send a drafted blast now to its audience. Blasts that were already sent can't be sent again.

list_subscribersread

List people subscribed to your calendar (newest first). Filter by status, tag, or search by name/email.

add_subscriberswrite

Add people to your calendar's subscriber list (up to 500 per call), optionally tagging them. People who previously unsubscribed are left opted out.

get_event_insightsread

Analytics for one event: guest stats, registrations by day, page views and top traffic sources, guest sources, feedback ratings and email performance.

Step-by-step setup for each client lives in Settings → Developers → MCP.

A machine-readable OpenAPI 3.1 document is published at /api/v1/openapi.json. Import it into Postman, Insomnia or an SDK generator, or point a code assistant at it.

2026-09-28
  • New resources: hosts, ticket types, coupons, registration questions, orders, feedback, blasts, team, webhooks and /me.
  • Events: publish, duplicate and delete. Guests: calendar-wide search, detail edits and removal. Subscribers: retrieve, update, delete and bulk import.
  • Read-only API keys, per-key rate limits with X-RateLimit-* headers, and X-Request-Id on every response.
  • Webhooks: delivery log with automatic retries and redelivery; new events event.published, event.deleted, order.paid, order.refunded, subscriber.created, subscriber.unsubscribed.
  • OpenAPI 3.1 document at /api/v1/openapi.json.
2026-06-01
  • Initial public API: calendar, events, guests, invitations and subscribers. Webhooks with HMAC-SHA256 signatures. MCP server.
Questions or a missing endpoint? Tell the Valore Agent (bottom right) and it files a request with the team, or email developers@valore.app.