PartyIRL · getting the night ready
Loading…PartyIRL · getting the night ready
Loading…A REST API and an MCP server for real-life events: create with one prompt, RSVP, search your city. Free, keyed to your account, same rules as the app.
Step 1 · Get your key
A key acts as YOU: it can publish events and RSVP under your name. Treat it like a password; revoke it from the same screen the moment it leaks.
Step 2 · Authenticate
Every request carries the key as a Bearer token. Base URL: https://api.partyirl.com
Authorization: Bearer pk_live_YOUR_KEY
Unknown or revoked keys get 401. Errors are always JSON: { "error": { "code", "message" } }.
You
Who this key acts as.
curl https://api.partyirl.com/v1/me \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{
"id": "cm…", "handle": "joel", "displayName": "Joel",
"avatarUrl": null, "avatarColor": "lime",
"createdAt": "2026-08-09T23:00:16.874Z",
"hostedEvents": 12, "followers": 3
}Edit your profile: handle, display name, initials-avatar color, or avatar photo.
curl -X PATCH https://api.partyirl.com/v1/me \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "handle": "joel_thomas", "displayName": "Joel Thomas", "avatarColor": "pool" }'Response
{ …same shape as GET /v1/me, updated }Events
Everything the app's create and edit forms can do. Host-only actions check ownership exactly like the site.
Your calendar: events you host plus events you RSVP'd to.
curl https://api.partyirl.com/v1/events \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{
"hosted": [{ "slug": "…", "title": "…", "startsAt": "…",
"timezone": "…", "categories": ["…"],
"visibility": "…", "city": "…", "archived": false }],
"attending": [{ …same fields, plus "rsvpStatus": "IN",
"guestCount": 0 }]
}One event, full detail. Gated addresses only appear once you've RSVP'd (or host it). guestList follows the host's guestListVisibility and is null when you're not permitted — the counts are always there. It carries names and faces only: no phone number, phone tail, or email is ever returned for anyone but yourself.
curl https://api.partyirl.com/v1/events/taco-night-x7k2p9 \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{
"slug": "taco-night-x7k2p9", "title": "TACO NIGHT",
"description": "…", "startsAt": "…", "timezone": "…",
"categories": ["FOOD_DRINK", "PARTY"],
"locationName": "…", "address": null, "city": "…",
"capacity": 15, "goingCount": 9, "waitlistCount": 0,
"guestListVisibility": "CONFIRMED_GUESTS",
"guestList": [{ "id": "cm…", "displayName": "Maya",
"avatarUrl": null, "avatarColor": "pool",
"guestCount": 1, "status": "IN" }],
"host": { "handle": "…", "displayName": "…" },
"url": "https://partyirl.com/e/taco-night-x7k2p9",
"myRsvp": { "status": "IN", "guestCount": 0 }
}Create + publish an event. Send a prompt and the AI drafts everything: title, copy, time, poster. Or send a full draft object to skip the AI.
curl -X POST https://api.partyirl.com/v1/events \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "rooftop movie night saturday 8pm, byo blanket, 20 ppl",
"vibe": "chill",
"timezone": "America/Los_Angeles",
"visibility": "UNLISTED"
}'Response
201 Created
{
"slug": "rooftop-movie-night-a1b2c3",
"url": "https://partyirl.com/e/rooftop-movie-night-a1b2c3",
"title": "ROOFTOP MOVIE NIGHT",
"startsAt": "2026-08-15T03:00:00.000Z",
"timezone": "America/Los_Angeles",
"visibility": "UNLISTED"
}RSVP as yourself. Repeat calls replace the previous answer; OUT cancels. A full event with a waitlist turns IN into WAITLIST. Check the returned status.
curl -X POST https://api.partyirl.com/v1/events/taco-night-x7k2p9/rsvp \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "IN", "guestCount": 1 }'Response
{ "slug": "taco-night-x7k2p9", "status": "IN", "guestCount": 1 }Partial edit. Send only the fields to change. Same fields as the app's edit form: title, description, startsAt (guests get a date-change banner), endsAt, timezone, locationName, address, city, state, hideAddressUntilRsvp, capacity, waitlistEnabled, maxGuestsPerRsvp, categories, requireName, commentsEnabled, commentsPrivate, guestListVisibility, visibility, poster.
curl -X PATCH https://api.partyirl.com/v1/events/taco-night-x7k2p9 \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "capacity": 30, "commentsPrivate": true }'Response
{ …the updated event, same shape as GET /v1/events/:slug }Archive (or restore) THIS date only. Reversible. The link keeps working, RSVPs close, it leaves Discover. On a recurring event the series keeps going.
curl -X POST https://api.partyirl.com/v1/events/taco-night-x7k2p9/archive \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "archived": true }'Response
{ "slug": "taco-night-x7k2p9", "archived": true }Permanently delete THIS date. The guest list, answers, and passes go with it. Requires an explicit confirm.
curl -X DELETE https://api.partyirl.com/v1/events/taco-night-x7k2p9 \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "confirm": true }'Response
{ "slug": "taco-night-x7k2p9", "deleted": true }Recurrence schedules
Address a recurrence through any occurrence slug. A Series is the community; this endpoint only changes the repeating calendar schedule.
Apply fields to EVERY upcoming occurrence (each keeps its own date). Send only what you mean to push. the explicit field list is the app's "only what you changed" save; sending everything is its OVERRIDE mode.
curl -X PATCH https://api.partyirl.com/v1/events/run-club-week-3/recurrence \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "capacity": 40, "locationName": "Festival Beach" }'Response
{ "slug": "run-club-week-3", "updatedOccurrences": 8,
"fields": ["capacity", "locationName"] }Stop the repeat (no new dates are created). futureAction decides what happens to already-created upcoming dates. Requires confirm.
curl -X POST https://api.partyirl.com/v1/events/run-club-week-3/recurrence/end \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "futureAction": "ARCHIVE", "confirm": true }'Response
{ "slug": "run-club-week-3", "ended": true,
"futureAction": "ARCHIVE", "affectedOccurrences": 8 }Questions & answers
The RSVP questionnaire guests see.
curl https://api.partyirl.com/v1/events/taco-night-x7k2p9/questions \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{ "slug": "…", "questions": [{ "id": "…", "position": 0,
"type": "SINGLE_SELECT", "label": "Coming for…",
"required": true, "options": ["Tacos", "Margs", "Both"] }] }Replace the questionnaire (host only; copies to upcoming occurrences on a series). Answers to removed questions are deleted. Max 15.
curl -X PUT https://api.partyirl.com/v1/events/taco-night-x7k2p9/questions \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "questions": [{ "type": "YES_NO", "label": "Bringing a dish?",
"required": true }] }'Response
{ "slug": "…", "questions": [ …with server ids ] }Host only: every guest's answers, grouped by guest.
curl https://api.partyirl.com/v1/events/taco-night-x7k2p9/answers \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{ "slug": "…", "answers": [{ "guest": "Maya", "handle": "maya",
"status": "IN", "answers": [{ "questionId": "…", "value": true }] }] }Guests
PartyIRL never hands out other people's contact details. No endpoint returns a guest's phone number, phone tail, or email — not to hosts, not to anyone. You get names, avatars, RSVP state, and the answers they gave your questions.
Host only: the guest list. Statuses, plus-ones, door check-ins, question answers, and whether you've blocked them. Contact details are never included — no phone number, no phone tail, no email. userId is the opaque account id POST /v1/blocks takes.
curl https://api.partyirl.com/v1/events/taco-night-x7k2p9/guests \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{ "slug": "…", "guests": [{ "rsvpId": "…", "userId": "cm…",
"name": "Maya", "status": "IN", "guestCount": 1,
"checkedIn": false, "blocked": false,
"rsvpedAt": "…", "answers": [ … ] }] }Host only: move a guest between IN, WAITLIST, and OUT. The host's word is final; promoting over capacity is allowed on purpose.
curl -X PATCH https://api.partyirl.com/v1/events/taco-night-x7k2p9/guests/RSVP_ID \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "IN" }'Response
{ "slug": "…", "rsvpId": "RSVP_ID", "status": "IN" }Hosts
Multi-host: roles are handed out BY PHONE NUMBER, so you can add the friend who works your door before they've ever opened PartyIRL — their access starts the moment that number signs in. OWNER = everything, including delete and transfer · CO_HOST = edits the event, runs the guest list and the wall, works the door · DOOR = checks people in and reads the guest list for that, nothing else. Reading the list needs edit access; changing it is owner-only. Phone numbers always come back masked.
Everyone with a role on the event, owner first. claimed:false means they were invited by phone and haven't signed in yet. id is what the PATCH and DELETE below take (the owner's row isn't one of them).
curl https://api.partyirl.com/v1/events/taco-night-x7k2p9/hosts \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{ "slug": "…", "hosts": [
{ "id": "owner:cm…", "role": "OWNER", "userId": "cm…",
"displayName": "Joel", "handle": "joel", "avatarUrl": null,
"avatarColor": "lime", "phoneMasked": "•••• 9991",
"claimed": true, "createdAt": "…" },
{ "id": "cm…", "role": "DOOR", "userId": null,
"displayName": null, "handle": null,
"phoneMasked": "•••• 0100", "claimed": false, "createdAt": "…" }
] }Owner only: give a phone number a role. No account needed — pending:true means the invite is waiting on their first sign-in. On a recurring event this covers every upcoming date and rides along to dates created later. Posting a number that's already on the list changes its role instead of duplicating it.
curl -X POST https://api.partyirl.com/v1/events/taco-night-x7k2p9/hosts \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "phone": "+15125550100", "role": "DOOR" }'Response
201 Created
{ "slug": "…", "host": { "id": "cm…", "role": "DOOR",
"userId": null, "phoneMasked": "•••• 0100", "claimed": false, … },
"datesAffected": 8, "pending": true }Owner only: move someone between CO_HOST and DOOR. Applies across a series' upcoming dates.
curl -X PATCH https://api.partyirl.com/v1/events/taco-night-x7k2p9/hosts/HOST_ID \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "role": "CO_HOST" }'Response
{ "slug": "…", "host": { …updated… }, "datesAffected": 8 }Owner only: take the keys back. Access ends immediately across every upcoming date, and they're never notified. Their RSVP, if they have one, is untouched.
curl -X DELETE https://api.partyirl.com/v1/events/taco-night-x7k2p9/hosts/HOST_ID \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{ "slug": "…", "removed": true, "datesAffected": 8 }Owner only, ONE-WAY, confirm-gated: hand the event to a phone number. You drop to CO_HOST — you keep edit and guest access but lose delete, transfer, and the host list, and only the new owner can hand it back. If that number has no account yet the transfer parks (pending:true) and completes at their first sign-in; until then DELETE the same path to call it off. A recurring event moves as a whole: this date, every upcoming date, and the series itself. Past dates never move.
curl -X POST https://api.partyirl.com/v1/events/taco-night-x7k2p9/transfer \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "phone": "+15125550100", "confirm": true }'Response
{ "slug": "…", "pending": false, "phoneMasked": "•••• 0100",
"eventsTransferred": 8, "eventsScoped": 8,
"newOwner": { "id": "cm…", "displayName": "Maya", "handle": "maya" } }Owner only: call off a transfer that's still waiting on someone's first sign-in. Once it lands there is nothing to cancel — the new owner decides from there.
curl -X DELETE https://api.partyirl.com/v1/events/taco-night-x7k2p9/transfer \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{ "slug": "…", "cancelled": 8 }What this key may do on the event: role (OWNER · CO_HOST · DOOR · null) plus explicit capability flags. Check it before offering an action you'd only be refused at.
curl https://api.partyirl.com/v1/events/taco-night-x7k2p9/permissions \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{ "slug": "…", "permissions": {
"role": "DOOR", "canEdit": false, "canManageGuests": false,
"canCheckIn": true, "canManageCollaborators": false,
"canModerateWall": false, "canDelete": false,
"canTransfer": false, "canPostAsHost": false } }Work the door: mark a guest as arrived, or undo it with checked:false. Open to the owner, co-hosts, and DOOR collaborators. Idempotent — checking someone in twice is one arrival.
curl -X POST https://api.partyirl.com/v1/events/taco-night-x7k2p9/checkins \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "userId": "cm…" }'Response
201 Created
{ "slug": "…", "userId": "cm…", "checkedIn": true }Blocks
Your own door policy, across every event you host. Nothing to do with platform moderation — it never touches anyone's account, and the person blocked is never notified.
Everyone you've blocked from your events, newest first. reason is your own private note.
curl https://api.partyirl.com/v1/blocks \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{ "blocked": [{ "userId": "cm…", "handle": "maya",
"displayName": "Maya", "avatarUrl": null,
"avatarColor": "pool", "reason": "no-shows",
"createdAt": "2026-08-11T02:14:00.000Z" }] }Block someone from every event you host. Immediately removes their RSVPs on your UPCOMING events (the seats and plus-ones go back to the pool) and hides their comments on your events. Past events keep their history. Idempotent — re-posting just updates the reason.
curl -X POST https://api.partyirl.com/v1/blocks \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "userId": "cm…", "reason": "kept no-showing" }'Response
201 Created
{ "blocked": true, "userId": "cm…", "displayName": "Maya",
"rsvpsRemoved": 2, "seatsFreed": 3, "commentsHidden": 4 }Reopen your door. They can RSVP and post again — but the RSVPs the block removed are NOT restored and the comments it hid are NOT unhidden.
curl -X DELETE https://api.partyirl.com/v1/blocks/cm… \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{ "blocked": false, "userId": "cm…" }Uploads
Import an image (≤10 MB). Metadata stripped, resized, re-encoded to CDN WebP. Send JSON {url} for a server-side fetch of a public https image, OR multipart/form-data with a "file" field. kind=poster (default, ≤1600×2000; use as poster backgroundImageUrl or an imagePoster) · kind=avatar (512px square; use with PATCH /v1/me).
curl -X POST https://api.partyirl.com/v1/uploads \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://example.com/flyer.jpg", "kind": "poster" }'
# or multipart:
curl -X POST https://api.partyirl.com/v1/uploads \
-H "Authorization: Bearer pk_live_YOUR_KEY" \
-F "file=@flyer.jpg" -F "kind=poster"Response
201 Created
{ "kind": "poster",
"url": "https://cdn…/posters/aB3….webp",
"thumbUrl": "https://cdn…/posters/aB3…-sm.webp",
"width": 1600, "height": 2000 }Discover
Search upcoming PUBLIC events. All filters optional.
curl "https://api.partyirl.com/v1/discover?query=tacos&city=Austin" \ -H "Authorization: Bearer pk_live_YOUR_KEY"
Response
{
"events": [{ "slug": "…", "title": "…", "startsAt": "…",
"timezone": "…", "categories": ["…"],
"locationName": "…", "city": "Austin", "state": "TX",
"goingCount": 12 }]
}Point Claude (or any MCP client) at https://api.partyirl.com/mcp (Streamable HTTP, same Bearer key) and it can throw parties for you.
Tools
Claude Code
claude mcp add --transport http partyirl https://api.partyirl.com/mcp \ --header "Authorization: Bearer pk_live_YOUR_KEY"
Claude Desktop
Settings → Developer → Edit Config, then add PartyIRL to claude_desktop_config.json (the mcp-remote bridge handles the Streamable HTTP connection):
{
"mcpServers": {
"partyirl": {
"command": "npx",
"args": [
"-y", "mcp-remote", "https://api.partyirl.com/mcp",
"--header", "Authorization: Bearer pk_live_YOUR_KEY"
]
}
}
}claude.ai (custom connector)
Rate limits
60 requests/minute per key (429 + Retry-After when you cross it). The app's own guardrails ride along: AI drafts are capped hourly and event creation daily. A key never gets more room than its owner.
Usage policy
Keys act as you, for things you'd do yourself: your events, your RSVPs, tools for your series. Don't spam feeds, scrape people's data, or automate RSVPs you don't mean. Moderation applies to API-created events exactly as in the app, and abusive keys (and accounts) get revoked.
Questions? It's early and things may move. Pin nothing to undocumented behavior.