Getting started with the Public API

Learn how to use iwasthere organizer features via API: create events, upload photos/videos, poll status, get share links, and check plan limits.

1. Issue an API key

Sign in and create a key on the developer page. The raw key is shown only once: /dashboard/developer

2. Create your first event

Create an event with your key. Share the returned shareLink with participants:

curl -X POST https://iwasthere.pics/api/public/v1/events \
  -H "Authorization: Bearer iwt_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"My Event"}'

Example response:

{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "shareLink": "https://iwasthere.pics/e/abc123",
  "quota": { "events": { "used": 1, "limit": 3 } }
}

3. Upload photos

Get an upload URL from photos/presign, PUT to S3, then call photos/complete to start indexing. Poll indexingStatus in the photos list.

Full workflow (copy & run)

End-to-end example from creating an event to uploading photos and confirming indexing. Requires jq.

KEY="iwt_YOUR_KEY"; BASE="https://iwasthere.pics/api/public/v1"

# 1) Create event → capture id, shareLink
EV=$(curl -s -X POST "$BASE/events" -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" -d '{"name":"My Event"}')
EVENT_ID=$(echo "$EV" | jq -r .id)

# 2) Get a presigned upload URL per file
PRE=$(curl -s -X POST "$BASE/events/$EVENT_ID/photos/presign" -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"files":[{"name":"IMG_0001.jpg","size":3145728,"type":"image/jpeg"}]}')
URL=$(echo "$PRE" | jq -r '.uploads[0].url')
PHOTO_ID=$(echo "$PRE" | jq -r '.uploads[0].photoId')
S3KEY=$(echo "$PRE" | jq -r '.uploads[0].s3Key')

# 3) PUT the original directly to S3 (no auth header; match Content-Type)
curl -s -X PUT "$URL" -H "Content-Type: image/jpeg" --data-binary @IMG_0001.jpg

# 4) Complete → triggers thumbnail & face indexing
curl -s -X POST "$BASE/events/$EVENT_ID/photos/complete" -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d "{\"uploaded\":[{\"photoId\":\"$PHOTO_ID\",\"s3Key\":\"$S3KEY\",\"fileSize\":3145728}]}"

# 5) Poll until every indexingStatus is done
curl -s "$BASE/events/$EVENT_ID/photos" -H "Authorization: Bearer $KEY" | jq '.photos[].indexingStatus'

# 6) Share the shareLink with participants

Handling plan limits

When a limit is exceeded, the 403 response includes an upgrade field (message, url). Relay it to the user as-is.

{
  "error": "PHOTO_LIMIT_EXCEEDED", "current": 50, "limit": 50,
  "upgrade": {
    "message": "The free plan allows up to 50 photos per event. Pro allows up to 500.",
    "url": "https://iwasthere.pics/dashboard/plan"
  }
}

Face search is not provided

Participant face search is never exposed via the public API. The server does not verify liveness, so exposing it would allow searching with someone else's face photo.