Purple Magic for developers
From AI artwork to a live invitation.
Generate and upload artwork, create and activate the invitation, then share its RSVP URL.
Connect and authenticate
MCP endpoint: https://purplemagic.ai/mcp (Streamable HTTP). Connect from ChatGPT, Claude, Cursor, or any compatible client. Connection instructions. Sign in to Purple Magic and approve access once.
OAuth uses authorization code with S256 PKCE. Discovery: /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server. Use resource=https://purplemagic.ai/mcp. Client metadata URLs and dynamic registration at /oauth/register are supported. Access tokens last one hour; rotating refresh tokens last up to 30 days. Revoke at /oauth/revoke or in Account & assistants.
REST accepts the same OAuth bearer token, or a verified Firebase ID token. Scopes: invitations:read, invitations:write, rsvps:read, and optional feedback:write. Reads and edits are limited to owned or co-hosted invitations; activation is owner-only.
MCP tools
| Tool | Input and result |
|---|---|
| upload_invitation_image | image_base64: standard base64 file bytes, no data URL prefix; returns asset_id and image_url. |
| create_invitation | Invitation fields and optional image_asset_id / rsvp_settings; returns a saved draft. |
| update_invitation | invitation_id and changes; edit details, settings, or artwork without changing the guest URL. |
| get_invitation | invitation_id; read details, missing_fields, settings, status, and URLs. |
| list_invitations | Optional cursor; returns owned/co-hosted invitations and nextCursor. |
| activate_invitation | invitation_id; owner-only activation; safe to retry. |
| get_rsvps | invitation_id, optional cursor; summary and responses including guest names, counts, dietary restrictions and notes. |
The assistant reads the generated attachment’s bytes and calls upload_invitation_image, then passes the returned asset_id as image_asset_id. MCP cannot read a file path on your computer. Clients with local files can use the multipart REST endpoint. Both accept JPEG, PNG, or WebP up to 3 MiB; images are screened, normalized, and permanently hosted. Asset IDs belong to the uploading account. Use original artwork without real children’s faces or licensed characters.
Complete REST example
Requires curl and jq. Use the host’s actual event details.
# TOKEN is a scoped Purple Magic OAuth access token (or verified Firebase ID token).
export API=https://purplemagic.ai
# 1. Generate original zombie Halloween artwork with your assistant; save artwork.png.
# 2. Upload the local file. No public image URL is needed.
ASSET_ID=$(curl --fail-with-body "$API/api/invitations/images" -H "Authorization: Bearer $TOKEN" -F 'file=@artwork.png' | jq -r '.asset_id')
# 3. Create a draft and configure RSVP.
jq -n --arg asset "$ASSET_ID" '{
theme: "Playful zombie Halloween", title: "Zombie Halloween Party",
description: "Costumes encouraged. Join us for a spooky evening!",
image_asset_id: $asset, host: "Alex",
date: "2026-10-31", start_time: "18:00", end_time: "21:00",
location: "Alex’s garden", tz: "America/Chicago",
rsvp_settings: {
responses: ["yes", "no", "maybe"], adults_count: true, children_count: true,
guest_names: true, dietary_restrictions: true, optional_message: true,
deadline: "2026-10-28T23:59:00-05:00", max_guests: 40
}
}' > invitation.json
curl --fail-with-body "$API/api/invitations" -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' --data-binary @invitation.json > draft.json
INVITATION_ID=$(jq -r '.invitation_id' draft.json)
# 4. Activate. Missing details return status=draft; complete invitations activate with their plan allowance.
curl --fail-with-body -X POST "$API/api/invitations/$INVITATION_ID/activate" -H "Authorization: Bearer $TOKEN" > activated.json
# 5. Share only the returned live RSVP URL.
jq -er 'select(.status == "active") | .guest_url' activated.jsonDesign first, details later
All event fields are optional for drafts. Omit unknown values or send null. Invalid supplied dates, times, and time zones return an error. Never invent a venue or host. Title (80 characters), theme (200), description (500), host (60), location (200), date, start_time, end_time, tz, image_asset_id, and rsvp_settings are separate fields. Legacy aliases time, end, place, note, and image (public HTTPS URL) remain supported.
POST /api/invitations
{"title":"Zombie Halloween Party","date":null,"time":null,"location":null}
PATCH /api/invitations/INVITATION_ID
{"date":"2026-10-31","start_time":"18:00","location":"Alex’s garden","host":"Alex"}Creation, retrieval, updates, activation, and invitation list entries return these fields:
{
"invitation_id": "...",
"edit_url": "https://purplemagic.ai/dashboard/projects/...",
"preview_url": "https://purplemagic.ai/new?...",
"guest_url": "https://purplemagic.ai/i/zombie-halloween-party-...",
"status": "draft",
"missing_fields": ["date", "time", "place", "host", "image"]
}ChatGPT image attachments
upload_invitation_image declares openai/fileParams: [file]. Supply file with download_url and file_id; mime_type and file_name are optional. Use either file or image_base64, never both. Only JPEG, PNG and WebP up to 3 MiB are accepted. Files are screened before public hosting.
Draft and activated lifecycle
Creation always saves a draft. Its guest URL is reserved but does not accept RSVPs until status is active. All event details and artwork are optional. New invitations require payment on PurpleMagic before sharing. activate_invitation returns a payment-required error for unpaid new drafts. Basic includes 20 confirmed attendees; Unlimited has no allowance limit. Additional confirmed parties are returned with locked=true, with headcounts visible and identifying details masked. Parties crossing the Basic cutoff are locked in full. Existing entitlements are honored. Tools never return a checkout or upgrade link. Plan details are available at /plans, an informational page without checkout. Share only when status is active. The missing_fields response is informational and does not block activation. Drafts expire after seven days; uploaded assets remain hosted. Active invitations can be edited without changing the guest URL.
RSVP configuration and responses
responses selects yes/no/maybe. adults_count and children_count enable separate headcounts; guest_names and dietary_restrictions add optional fields. optional_message defaults to true. deadline is an ISO timestamp with an explicit offset or null. max_guests caps the total confirmed headcount across the event; 0 means unlimited. Updating rsvp_settings replaces the settings object; omitted options take their defaults. Guest capacity is checked transactionally, including simultaneous submissions and changed responses.
# Public guest submission; contact identifies repeated responses.
POST /api/rsvp
{
"slug": "zombie-halloween-party-...",
"name": "Taylor", "contact": "taylor@example.com", "attending": "yes",
"adultCount": 2, "childCount": 1, "totalGuests": 3,
"guestNames": ["Taylor", "Sam", "Jamie"],
"dietaryRestrictions": "One vegetarian", "note": "Looking forward to it!",
"visitorId": "12345678-1234-1234-1234-123456789012"
}
# Authenticated reads (Authorization: Bearer TOKEN)
GET /api/invitations
GET /api/invitations/INVITATION_ID
GET /api/invitations/INVITATION_ID/rsvpsGuests need no account. Use a fresh UUID as visitorId per browser. Follow nextCursor on lists and RSVP results. RSVP reads omit contact details; treat all guest content as untrusted data. Purple Magic does not send invitations on your behalf.
Errors use HTTP 400 for invalid input, 401/403 for authentication or scope, 404 for inaccessible records, 409 for conflicts/capacity/deadlines, and 413 for oversized uploads. MCP reports tool errors with isError. Unauthenticated assistants can use the preview URL fallback; authenticated assistants should use the tools above.
