Developer hub
REST API v1 OpenAPI 3.1 MCP-equivalent policy

Rizz Invites developer platform

One event contract, now over REST.

Use the same OAuth grants or host PATs as MCP. Scopes, tenant isolation, confirmations, idempotency, rate limits, sandbox behavior, and audit policy are shared by both transports.

API origin

https://rizzinvites.com

Every operation path below starts with /api/v1.

Start here

Make your first authenticated request

Send a bearer token in the Authorization header. Browser cookies and web sessions never authorize API calls. JSON fields use snake_case and unknown fields are rejected at every nesting level.

Read the current account
curl https://rizzinvites.com/api/v1/account \
  -H 'Authorization: Bearer $RIZZ_ACCESS_TOKEN' \
  -H 'Accept: application/json'
Create a draft event
curl https://rizzinvites.com/api/v1/events \
  -H 'Authorization: Bearer $RIZZ_ACCESS_TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"name":"Birthday dinner","party_date":"2026-09-12","time_from":"18:00:00","timezone":"America/New_York"}'

OAuth and PATs

Sign in or create an account in the browser

Start OAuth at /oauth/authorize with the canonical https://rizzinvites.com resource and PKCE S256. If the host has no account, the existing magic-link or Google browser flow creates one, preserves the validated OAuth request, resumes consent, and returns the code only to the registered redirect URI. There is no MCP or REST signup endpoint.

Admin boundary

The /api/v1/admin scope accepts admin-audience PATs only. OAuth, host PATs, non-admin users, and browser sessions are rejected.

Golden workflow

Draft, design, guests, entitlement, delivery

The free path never opens checkout. Create checkout only when the current event response indicates that the guest count or selected capability requires a paid tier.

  1. 1
    create_event

    Create a draft with local date/time and an explicit timezone.

  2. 2
    add_guests

    Import 1–100 contactable guests atomically with Idempotency-Key.

  3. 3
    search_templates / generate_cover

    Choose an active template or queue a cover, then select exactly one design.

  4. 4
    create_checkout_link (conditional)

    Only create checkout if the event needs a paid tier; reconcile it with POST.

  5. 5
    send_invites

    Request the delivery preview, review it, then retry identically with RizzInvites-Confirmation.

  6. 6
    get_event / list_guests

    Re-read canonical state and delivery outcomes after the queue commits.

Retry safety

Headers bind consequential work

Header values are normalized into the same internal arguments as MCP before hashing. Transport is excluded from the binding, so a retry can cross from MCP to REST when it uses the same actor and normalized business arguments.

RizzInvites-Confirmation

A protected mutation without this header returns 409 confirmation_required with a preview and token. Send, cancel, and delete tokens expire after 15 minutes; other confirmation tokens expire after 5. Only send_invites, cancel_event, and delete_event may replay a stored confirmed response for 24 hours.

Idempotency-Key

Required for guest batches, cover generation, checkout creation, and guest messaging. Matching completed results replay for 24 hours; changed arguments return 409 idempotency_conflict.

Confirm an invitation delivery
# First request returns 409 confirmation_required with a preview and token.
curl -X POST https://rizzinvites.com/api/v1/events/123/invitation-deliveries \
  -H 'Authorization: Bearer $RIZZ_ACCESS_TOKEN'

# Retry the identical request with the returned token.
curl -X POST https://rizzinvites.com/api/v1/events/123/invitation-deliveries \
  -H 'Authorization: Bearer $RIZZ_ACCESS_TOKEN' \
  -H 'RizzInvites-Confirmation: rzi_cfm_...'

Generated reference

Every canonical route

Operation metadata below comes from the same contract used for MCP discovery, REST dispatch, schema validation, and OpenAPI generation.

Host API

Host PAT or OAuth token; the public OpenAPI document contains only the 17 launch-enabled host operations and four content routes.

GET
/api/v1/events

list_events

live
host audience events:read
Validated request and response example
{
  "limit": 50
}
{
  "data": {
    "events": []
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
GET
/api/v1/events/:event_id

get_event

live
host audience events:read
Validated request and response example
{
  "event_id": 42
}
{
  "data": {
    "allow_plus_ones": true,
    "created_at": "2026-08-08T12:00:00Z",
    "design": {
      "type": "none"
    },
    "guest_count": 0,
    "host_message": "Join us!",
    "id": 42,
    "name": "Maya's birthday",
    "party_date": "2026-09-12",
    "role": "owner",
    "rsvp_summary": {
      "confirmed": 0,
      "declined": 0,
      "pending": 0,
      "plus_ones_total": 0
    },
    "status": "draft",
    "tier": "free",
    "time_from": "15:00:00",
    "timezone": "America/New_York",
    "timezone_inferred": false,
    "updated_at": "2026-08-08T12:00:00Z"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
GET
/api/v1/events/:event_id/guests

list_guests

live
host audience guests:read
Validated request and response example
{
  "event_id": 42,
  "limit": 50
}
{
  "data": {
    "guests": [
      {
        "contacts_revealed": false,
        "delivery_status": "pending",
        "id": 7,
        "masked_email": "s***@example.com",
        "name": "Sam",
        "plus_ones": 0,
        "rsvp_status": "pending"
      }
    ]
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
GET
/api/v1/templates

search_templates

live
host audience events:read
Validated request and response example
{
  "category": "kids_birthday",
  "limit": 20
}
{
  "data": {
    "templates": [
      {
        "category": "kids_birthday",
        "id": 3,
        "name": "Garden",
        "preview_url": "https://cdn.example.com/template.png",
        "tags": [
          "garden"
        ]
      }
    ]
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
GET
/api/v1/account

get_account

live
host audience account:read
Validated request and response example
{}
{
  "data": {
    "account_mode": "production",
    "ai_pro_active": false,
    "email": "h***@example.com",
    "id": 1,
    "name": "Host",
    "timezone": "America/New_York"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
POST
/api/v1/events

create_event

live
host audience events:write
Validated request and response example
{
  "name": "Maya's birthday",
  "party_date": "2026-09-12",
  "time_from": "15:00",
  "timezone": "America/New_York"
}
{
  "data": {
    "allow_plus_ones": true,
    "created_at": "2026-08-08T12:00:00Z",
    "design": {
      "type": "none"
    },
    "guest_count": 0,
    "host_message": "Join us!",
    "id": 42,
    "name": "Maya's birthday",
    "party_date": "2026-09-12",
    "role": "owner",
    "rsvp_summary": {
      "confirmed": 0,
      "declined": 0,
      "pending": 0,
      "plus_ones_total": 0
    },
    "status": "draft",
    "tier": "free",
    "time_from": "15:00:00",
    "timezone": "America/New_York",
    "timezone_inferred": false,
    "updated_at": "2026-08-08T12:00:00Z"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
PATCH
/api/v1/events/:event_id

update_event

live
host audience events:write
Validated request and response example
{
  "event_id": 42,
  "name": "Updated party"
}
{
  "data": {
    "allow_plus_ones": true,
    "created_at": "2026-08-08T12:00:00Z",
    "design": {
      "type": "none"
    },
    "guest_count": 0,
    "host_message": "Join us!",
    "id": 42,
    "name": "Updated party",
    "party_date": "2026-09-12",
    "role": "owner",
    "rsvp_summary": {
      "confirmed": 0,
      "declined": 0,
      "pending": 0,
      "plus_ones_total": 0
    },
    "status": "draft",
    "tier": "free",
    "time_from": "15:00:00",
    "timezone": "America/New_York",
    "timezone_inferred": false,
    "updated_at": "2026-08-08T12:01:00Z"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
POST
/api/v1/events/:event_id/guests

add_guests

live
host audience guests:write
Validated request and response example
{
  "event_id": 42,
  "guests": [
    {
      "email": "sam@example.com",
      "name": "Sam"
    }
  ],
  "idempotency_key": "guest-import-42-v1"
}
{
  "data": {
    "count": 1,
    "guests": [
      {
        "id": 7,
        "name": "Sam"
      }
    ]
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
PATCH
/api/v1/events/:event_id/guests/:guest_id

update_guest

live
host audience guests:write
Validated request and response example
{
  "event_id": 42,
  "guest_id": 7,
  "name": "Sam Lee"
}
{
  "data": {
    "id": 7,
    "name": "Sam Lee"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
DELETE
/api/v1/events/:event_id/guests/:guest_id

remove_guest

live
host audience guests:write
Validated request and response example
{
  "event_id": 42,
  "guest_id": 7
}
{
  "data": {
    "deleted": true
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
POST
/api/v1/events/:event_id/invitation-deliveries

send_invites

live
host audience messaging:send
Validated request and response example
{
  "confirmation_token": "rzi_cfm_fixture",
  "event_id": 42
}
{
  "data": {
    "event_id": 42,
    "queued_count": 1,
    "sent_at": "2026-08-08T12:00:00Z",
    "skipped": []
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_send_fixture",
    "warnings": []
  }
}
POST
/api/v1/events/:event_id/covers

generate_cover

live
host audience ai:generate
Validated request and response example
{
  "event_id": 42,
  "idempotency_key": "cover-42-v1",
  "theme": "enchanted garden"
}
{
  "data": {
    "created_at": "2026-08-08T12:00:00Z",
    "event_id": 42,
    "id": 9,
    "selected": false,
    "status": "queued",
    "theme": "enchanted garden"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
GET
/api/v1/events/:event_id/covers/:generation_id

get_cover_status

live
host audience events:read
Validated request and response example
{
  "event_id": 42,
  "generation_id": 9
}
{
  "data": {
    "cover_url": "https://cdn.example.com/cover.png",
    "created_at": "2026-08-08T12:00:00Z",
    "event_id": 42,
    "id": 9,
    "selected": true,
    "status": "succeeded",
    "theme": "enchanted garden"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
PUT
/api/v1/events/:event_id/design

set_event_design

live
host audience events:write
Validated request and response example
{
  "event_id": 42,
  "generation_id": 9
}
{
  "data": {
    "allow_plus_ones": true,
    "created_at": "2026-08-08T12:00:00Z",
    "design": {
      "cover_url": "https://cdn.example.com/cover.png",
      "id": 9,
      "type": "generation"
    },
    "guest_count": 0,
    "host_message": "Join us!",
    "id": 42,
    "name": "Maya's birthday",
    "party_date": "2026-09-12",
    "role": "owner",
    "rsvp_summary": {
      "confirmed": 0,
      "declined": 0,
      "pending": 0,
      "plus_ones_total": 0
    },
    "status": "draft",
    "tier": "free",
    "time_from": "15:00:00",
    "timezone": "America/New_York",
    "timezone_inferred": false,
    "updated_at": "2026-08-08T12:00:00Z"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
POST
/api/v1/events/:event_id/checkouts

create_checkout_link

live
host audience billing:checkout
Validated request and response example
{
  "event_id": 42,
  "idempotency_key": "checkout-42-v1",
  "tier": "pro"
}
{
  "data": {
    "amount_cents": 1499,
    "checkout_id": "rzi_chk_fixture",
    "currency": "usd",
    "event_id": 42,
    "expires_at": "2026-08-08T12:30:00Z",
    "status": "open",
    "tier": "pro",
    "url": "https://checkout.stripe.com/example"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
POST
/api/v1/checkouts/:checkout_id/reconcile

check_payment_status

live
host audience billing:checkout
Validated request and response example
{
  "checkout_id": "rzi_chk_fixture"
}
{
  "data": {
    "amount_cents": 1499,
    "checkout_id": "rzi_chk_fixture",
    "currency": "usd",
    "event_id": 42,
    "expires_at": "2026-08-08T12:30:00Z",
    "status": "paid",
    "tier": "pro"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
POST
/api/v1/events/:event_id/cancellations

cancel_event

post-beta
host audience events:write
Validated request and response example
{
  "confirmation_token": "rzi_cfm_fixture",
  "event_id": 42
}
{
  "data": {
    "allow_plus_ones": true,
    "created_at": "2026-08-08T12:00:00Z",
    "design": {
      "id": 3,
      "type": "template"
    },
    "guest_count": 1,
    "host_message": "Join us!",
    "id": 42,
    "name": "Maya's birthday",
    "party_date": "2026-09-12",
    "role": "owner",
    "rsvp_summary": {
      "confirmed": 0,
      "declined": 0,
      "pending": 1,
      "plus_ones_total": 0
    },
    "status": "cancelled",
    "tier": "free",
    "time_from": "15:00:00",
    "timezone": "America/New_York",
    "timezone_inferred": false,
    "updated_at": "2026-08-08T12:01:00Z"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
DELETE
/api/v1/events/:event_id

delete_event

post-beta
host audience events:write
Validated request and response example
{
  "confirmation_token": "rzi_cfm_fixture",
  "event_id": 42
}
{
  "data": {
    "deleted": true
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
POST
/api/v1/events/:event_id/guest-messages

message_guests

post-beta
host audience messaging:send
Validated request and response example
{
  "confirmation_token": "rzi_cfm_fixture",
  "event_id": 42,
  "idempotency_key": "change-42-v1",
  "message": "New venue"
}
{
  "data": {
    "event_id": 42,
    "queued_count": 1
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
POST
/api/v1/events/:event_id/cohosts

add_cohost

post-beta
host audience events:write
Validated request and response example
{
  "confirmation_token": "rzi_cfm_fixture",
  "email": "sam@example.com",
  "event_id": 42,
  "name": "Sam"
}
{
  "data": {
    "id": 8,
    "name": "Sam",
    "status": "pending"
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
DELETE
/api/v1/events/:event_id/cohosts/:cohost_id

remove_cohost

post-beta
host audience events:write
Validated request and response example
{
  "cohost_id": 8,
  "confirmation_token": "rzi_cfm_fixture",
  "event_id": 42
}
{
  "data": {
    "deleted": true
  },
  "meta": {
    "next_cursor": null,
    "request_id": "req_fixture",
    "warnings": []
  }
}
GET
/api/v1/pricing

get_pricing

live
host audience events:read
Validated request and response example
{}
{
  "data": {
    "tiers": [
      {
        "id": "free",
        "name": "Free",
        "subtitle": "Up to 10 guests",
        "price_cents": 0,
        "max_guests": 10
      }
    ]
  },
  "meta": {
    "warnings": [],
    "request_id": "req_example",
    "next_cursor": null
  }
}
GET
/api/v1/guides/host-playbook

get_host_playbook

live
host audience events:read
Validated request and response example
{}
{
  "data": {
    "content": "# Host playbook",
    "media_type": "text/markdown"
  },
  "meta": {
    "warnings": [],
    "request_id": "req_example",
    "next_cursor": null
  }
}
GET
/api/v1/prompts

list_prompts

live
host audience authenticated; response is caller-filtered
Validated request and response example
{}
{
  "data": {
    "prompts": []
  },
  "meta": {
    "warnings": [],
    "request_id": "req_example",
    "next_cursor": null
  }
}
POST
/api/v1/prompts/:prompt_name/render

render_prompt

live
host audience authenticated; response is caller-filtered
Validated request and response example
{
  "guest_count": 12,
  "occasion": "birthday"
}
{
  "data": {
    "message": "Help me plan a safe draft event.",
    "name": "plan_my_party"
  },
  "meta": {
    "warnings": [],
    "request_id": "req_example",
    "next_cursor": null
  }
}

Collections

Opaque cursor pagination

Events and guests default to 50 items and accept at most 100. Template search defaults to 20 and accepts at most 50. Pass the opaque meta.next_cursor value unchanged as cursor; an invalid cursor returns 422 validation_failed. A null next_cursor means the collection is complete.

Continue a collection
curl 'https://rizzinvites.com/api/v1/events?limit=50&cursor=eyJhZnRlcl9pZCI6NDJ9' \
  -H 'Authorization: Bearer $RIZZ_ACCESS_TOKEN'

# Reuse meta.next_cursor exactly; do not parse or modify it.

Operational contract

Envelopes, statuses, limits, and CORS

Success uses {data, meta}; failures use {error}. X-Request-ID mirrors meta.request_id and Retry-After accompanies 429 responses. Request bodies are capped at 1,000,000 bytes and responses at 100,000 bytes.

CORS: configured origins may use GET, POST, PATCH, PUT, DELETE, and OPTIONS with Authorization, Content-Type, Idempotency-Key, RizzInvites-Confirmation, and X-Request-ID. Cookies are never enabled.

Statuses: 200 reads/updates/deletes; 201 creates; 202 queued cover/delivery/message work; 400 syntax; 401 auth; 402 payment; 403 scope/origin; 404 inaccessible or disabled; 409 confirmation/state/idempotency; 413 size; 422 schema/blocklist; 429 limits; 503 temporary failure.

ai 10 / credential / hour
checkout 10 / credential / hour
event_messaging 3 / event / day
messaging 5 / credential / hour
mutation 30 / credential / minute
pre_auth 60 / IP / minute
read 120 / credential / minute
not_found

Use error.next_action and refresh current resource state.

malformed_request

Use error.next_action and refresh current resource state.

validation_failed

Use error.next_action and refresh current resource state.

invalid_state

Use error.next_action and refresh current resource state.

not_draft

Use error.next_action and refresh current resource state.

design_missing

Call set_event_design.

payment_required

Call create_checkout_link with details.required_tier, complete payment, poll, and retry.

guest_limit_reached

Use error.next_action and refresh current resource state.

quota_exceeded

Use error.next_action and refresh current resource state.

contact_blocked

Remove or correct the redacted row index.

confirmation_required

Review the preview and repeat identical arguments with its token.

confirmation_expired

Request a new preview.

rate_limited

Wait details.retry_after_seconds.

conflict

Use error.next_action and refresh current resource state.

idempotency_conflict

Use error.next_action and refresh current resource state.

request_too_large

Use error.next_action and refresh current resource state.

response_too_large

Use error.next_action and refresh current resource state.

temporarily_unavailable

Retry later with the request_id.

unauthorized

Use error.next_action and refresh current resource state.

insufficient_scope

Use error.next_action and refresh current resource state.

200 success
{
  "data": {
    "id": 42,
    "name": "Birthday dinner"
  },
  "meta": {
    "warnings": [],
    "request_id": "req_01",
    "next_cursor": null
  }
}
409 confirmation
{
  "error": {
    "code": "confirmation_required",
    "message": "Confirm this action and retry with the confirmation token.",
    "details": {
      "expires_at": "2026-08-09T18:15:00Z",
      "confirmation_token": "rzi_cfm_..."
    },
    "retryable": false,
    "next_action": {
      "retry": true
    }
  },
  "meta": {
    "request_id": "req_02"
  }
}
429 rate limit
{
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Retry later.",
    "details": {
      "retry_after_seconds": 60
    },
    "retryable": true,
    "next_action": {}
  },
  "meta": {
    "request_id": "req_03"
  }
}

Version and availability

Stable v1, with post-beta routes visible but off.

Additive optional fields remain in /api/v1; breaking changes require /api/v2. Event deletion, cancellation, guest messaging, and cohost operations return 404 until post-beta is separately enabled. Production sandbox is disabled. The MCP_ENABLED kill switch disables MCP, OAuth execution, and REST execution while this documentation and its generated contracts remain public.

Changelog · 2026-08-09

v1 launch contract: canonical OAuth resource, REST/MCP parity, closed outputs, correlated error envelopes, and launch-only public OpenAPI publication.