Skip to main content

Guest Management

Manage podcast guests, LinkedIn profile data, and episode associations.

List Guests

Retrieve all guests with optional filtering, searching, and sorting.
GET /api/sanity/guests
curl "https://production.youvebeenheard.com/api/sanity/guests?status=recorded&limit=50" \
  -H "Cookie: auth_token=<token>"

Query Parameters

status
string
Filter by guest statusOptions: booked, recorded, published, cancelled, all
inCircle
boolean
Filter by “In Circle” statusOptions: true, false
Search across name, position, company, and email
limit
number
default:"100"
Maximum results to return (max: 500)
offset
number
default:"0"
Number of results to skip for pagination
sortField
string
default:"name"
Field to sort byOptions: name, status, linkedinFollowers, inCircle, episodes
sortDirection
string
default:"asc"
Sort directionOptions: asc, desc

Response

{
  "guests": [
    {
      "_id": "guest_123",
      "_type": "guest",
      "name": "Chris Pacifico",
      "position": "Chief Information Officer",
      "company": "TechCorp Inc.",
      "email": "[email protected]",
      "emailAlt": "[email protected]",
      "mobile": "+1-555-0123",
      "address": "San Francisco, CA",
      "linkedinUrl": "https://www.linkedin.com/in/chris-pacifico/",
      "linkedinFollowers": 12500,
      "inCircle": true,
      "status": "recorded",
      "isRepeatGuest": false,
      "episodeRefs": [
        {"_type": "reference", "_ref": "episode_abc123"}
      ],
      "shareLinks": [
        {
          "_key": "share_1",
          "shareToken": "xyz789",
          "episodeId": "episode_abc123",
          "createdAt": "2024-03-10T09:00:00Z"
        }
      ],
      "notes": "Interested in discussing AI in enterprise IT",
      "importedEpisodeNumber": 385,
      "transcript": "Full transcript if uploaded...",
      "_createdAt": "2024-01-15T10:00:00Z",
      "_updatedAt": "2024-03-10T14:30:00Z",
      "latestEpisode": {
        "_id": "episode_abc123",
        "releaseDate": "2024-03-15",
        "episodeNumber": 385
      }
    }
  ],
  "totalCount": 250,
  "limit": 50,
  "offset": 0
}
guests
array
Array of guest objects with episode references expanded
totalCount
number
Total number of guests matching the filter
limit
number
Limit applied to this request
offset
number
Offset applied to this request

Get Guest

Retrieve a single guest by ID with expanded episode references.
GET /api/sanity/guests/:id
id
string
required
Guest ID
curl https://production.youvebeenheard.com/api/sanity/guests/guest_123 \
  -H "Cookie: auth_token=<token>"

Response

{
  "_id": "guest_123",
  "name": "Chris Pacifico",
  "position": "Chief Information Officer",
  "company": "TechCorp Inc.",
  "linkedinUrl": "https://www.linkedin.com/in/chris-pacifico/",
  "linkedinFollowers": 12500,
  "inCircle": true,
  "status": "recorded",
  "episodeRefs": [
    {
      "_id": "episode_abc123",
      "metadata": {
        "title": "Episode 385",
        "episodeNumber": 385
      },
      "status": "complete",
      "shareToken": "xyz789",
      "createdAt": "2024-03-10T08:00:00Z"
    }
  ],
  "shareLinks": [],
  "notes": "Great guest, interested in return appearance"
}

Error Responses

StatusErrorDescription
400Guest ID is requiredMissing ID parameter
404Guest not foundGuest does not exist
401UnauthorizedNot authenticated

Create Guest

Create a new guest profile.
POST /api/sanity/guests
curl -X POST https://production.youvebeenheard.com/api/sanity/guests \
  -H "Content-Type: application/json" \
  -H "Cookie: auth_token=<token>" \
  -d '{
    "name": "Chris Pacifico",
    "position": "CIO",
    "company": "TechCorp",
    "email": "[email protected]",
    "linkedinUrl": "https://www.linkedin.com/in/chris-pacifico/",
    "linkedinFollowers": 12500,
    "status": "booked"
  }'

Request

name
string
required
Guest full name
position
string
Job title
company
string
Company name
email
string
Primary email address
emailAlt
string
Alternative email address
mobile
string
Mobile phone number
address
string
Mailing address or location
linkedinUrl
string
LinkedIn profile URL
linkedinFollowers
number
default:"0"
LinkedIn follower count
inCircle
boolean
default:"false"
“In Circle” status for special guests
status
string
default:"booked"
Guest statusOptions: booked, recorded, published, cancelled
notes
string
Internal notes about the guest
importedEpisodeNumber
number
Episode number if imported from external system

Response

{
  "_id": "guest_new123",
  "_type": "guest",
  "name": "Chris Pacifico",
  "position": "CIO",
  "company": "TechCorp",
  "email": "[email protected]",
  "linkedinUrl": "https://www.linkedin.com/in/chris-pacifico/",
  "linkedinFollowers": 12500,
  "inCircle": false,
  "status": "booked",
  "isRepeatGuest": false,
  "episodeRefs": [],
  "shareLinks": []
}
YBH Sales Dashboard Sync: New guests are automatically synced to the YBH sales dashboard (if configured). Check logs for sync status.

Update Guest

Update guest information. Only provided fields are updated.
PATCH /api/sanity/guests/:id
id
string
required
Guest ID
curl -X PATCH https://production.youvebeenheard.com/api/sanity/guests/guest_123 \
  -H "Content-Type: application/json" \
  -H "Cookie: auth_token=<token>" \
  -d '{
    "status": "recorded",
    "linkedinFollowers": 13000,
    "notes": "Recorded episode 385, great conversation"
  }'

Request Fields

All fields from Create Guest are supported. Only include fields to update.
episodeRefs
array
Episode references
[
  {
    "_type": "reference",
    "_ref": "episode_abc123",
    "_key": "ref_1"
  }
]
Share link records
[
  {
    "_key": "share_1",
    "shareToken": "xyz789",
    "episodeId": "episode_abc123",
    "createdAt": "2024-03-10T09:00:00Z"
  }
]
transcript
string
Episode transcript (if uploaded before episode creation)

Response

Returns the updated guest object with expanded episode references (same structure as Get Guest).
Field Removal: To remove a field, set it to null or undefined. The API uses Sanity’s .unset() method for null values.

Delete Guest

Delete a guest profile.
DELETE /api/sanity/guests/:id
id
string
required
Guest ID
curl -X DELETE https://production.youvebeenheard.com/api/sanity/guests/guest_123 \
  -H "Cookie: auth_token=<token>"

Response

{
  "success": true,
  "id": "guest_123"
}
Permanent Deletion: This action cannot be undone. Episode references to this guest will remain but will not resolve.

Bulk Delete

Delete all guests (requires explicit confirmation).
DELETE /api/sanity/guests?confirm=true
confirm
string
required
Must be "true" to proceed
curl -X DELETE "https://production.youvebeenheard.com/api/sanity/guests?confirm=true" \
  -H "Cookie: auth_token=<token>"

Response

{
  "deleted": 250,
  "message": "Deleted 250 guests"
}
Safety Limit: Maximum 500 guests can be deleted at once. This prevents accidental mass deletion.

Guest Status Workflow

Guests progress through these statuses:
StatusDescription
bookedGuest confirmed, not yet recorded
recordedEpisode recorded, not published
publishedEpisode live on podcast
cancelledGuest cancelled or rescheduled

”In Circle” Status

The inCircle flag marks VIP guests or special relationships:
// Mark as VIP
await updateGuest(guestId, { inCircle: true })

// Filter for VIP guests
const vips = await fetch('/api/sanity/guests?inCircle=true')
Use for:
  • Repeat guests
  • Strategic partnerships
  • High-priority relationships

Search Examples

const results = await fetch('/api/sanity/guests?search=Chris')

Episode Association

Link guests to episodes:
// 1. Create episode with guest reference
const episode = await fetch('/api/sanity/episodes', {
  method: 'POST',
  body: JSON.stringify({
    guestId: 'guest_123',  // Pre-fills metadata from guest
    transcript: '...'
  })
})

// 2. Or update episode to add guest reference
await fetch(`/api/sanity/episodes/${episodeId}`, {
  method: 'PATCH',
  body: JSON.stringify({
    guestRef: {
      _type: 'reference',
      _ref: 'guest_123'
    }
  })
})
The guest’s episodeRefs array is automatically updated.

Build docs developers (and LLMs) love