One account can manage many hosts — each an independently-bookable principal with its own calendar, availability, and bookings. Use this when you run a roster of people on shared infrastructure: an L&D org with many coaches, an agency booking on behalf of its clients, a marketplace of practitioners.
Each host has its own principal_id. You query that host's availability and book against it; the booking is attributed to that host and written to their calendar. Your account's API key carries delegated authority over every host it manages — a few keys cover hundreds of hosts.
Teams vs hosts. Team Scheduling finds a slot where several people are all free (one meeting, many attendees) — supply-side coordination. Multi-host is the opposite: many independent bookable people under one account, each booked separately — demand-side delegation. Reach for teams to coordinate a group; reach for hosts to operate a roster.
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/hosts | Provision a host principal |
| GET | /v1/hosts | List managed hosts (with calendar status) |
| POST | /v1/hosts/:id/connect-link | Get a calendar-connect URL for a host |
| DELETE | /v1/hosts/:id | Unlink a host (revokes delegated authority) |
| POST | /v1/calendars/google/connect-guest-link | Get a single-use calendar-connect URL for a customer |
Availability and booking use the existing endpoints with the host's principal_id:
| Method | Path | Purpose |
|---|---|---|
| GET | /v1/availability/slots?principal_id=… | A single host's free/busy |
| GET | /v1/availability/mutual?principal_ids=… | Free time shared by a host and your customers |
| POST | /v1/bookings (principal_id) |
Book against a specific host |
| GET | /v1/bookings?principal_id=… | List one host's bookings |
curl -X POST https://api.vennio.app/v1/hosts \
-H "Authorization: Bearer $VENNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "display_name": "Coach Alice" }'
// Response
{
"host": {
"principal_id": "903f701d-…",
"display_name": "Coach Alice",
"status": "active",
"calendar_connected": false,
"created_at": "2026-06-24T10:30:54Z"
}
}
The host connects their own calendar — you never handle their credentials.
curl -X POST https://api.vennio.app/v1/hosts/903f701d-…/connect-link \
-H "Authorization: Bearer $VENNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "redirect_url": "https://app.example.com/connected" }'
// Response — send connect_url to the host (single-use, expires in 5 min)
{
"principal_id": "903f701d-…",
"connect_url": "https://api.vennio.app/v1/calendars/google/connect?token=…",
"expires_in": 300
}
Email or message connect_url to the host. When they complete it, calendar_connected flips to true in GET /v1/hosts.
curl -G "https://api.vennio.app/v1/availability/slots" \
-H "Authorization: Bearer $VENNIO_API_KEY" \
--data-urlencode "principal_id=903f701d-…" \
--data-urlencode "duration_minutes=30" \
--data-urlencode "from=2026-07-01T09:00:00Z" \
--data-urlencode "to=2026-07-04T17:00:00Z" \
--data-urlencode "timezone=Europe/London"
Each host returns its own free/busy — no merging across the roster.
To find time that suits both a host and a customer, pass both to /v1/availability/mutual:
curl -G "https://api.vennio.app/v1/availability/mutual" \
-H "Authorization: Bearer $VENNIO_API_KEY" \
--data-urlencode "principal_ids=903f701d-…,5b2e9c14-…" \
--data-urlencode "duration_minutes=30" \
--data-urlencode "from=2026-07-01T09:00:00Z" \
--data-urlencode "to=2026-07-04T17:00:00Z"
Hosts your account manages need no consent. Every other principal in the list must be connected to your account or have granted it consent. Consent belongs to the account, not to a host: a customer who connects once can be queried alongside any of your hosts.
To query a customer without a Vennio account, have them connect their Google Calendar to your account. Mint a single-use connect link from your server with your secret key:
curl -X POST https://api.vennio.app/v1/calendars/google/connect-guest-link \
-H "Authorization: Bearer $VENNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"redirect_url": "https://yourapp.com/connected",
"reference": "trip_8812"
}'
{
"connect_url": "https://api.vennio.app/v1/calendars/google/connect?token=…",
"expires_in": 300
}
Mint on click, redirect immediately. Call this when the customer clicks "Connect calendar", then redirect their browser to connect_url. The link works once and expires after 5 minutes, so don't email it or put it in a page.
principal_id.redirect_url must be on your redirect whitelist. It's checked when you mint the link.reference is your own ID for this customer or order. It's bound into the link and comes back to you.When the customer finishes Google sign-in:
consent.granted to your webhooks with grantor_id (the customer's principal ID), source: "calendar_connect", connection_id and your reference. Store grantor_id against your own record.redirect_url?google_connected=true&principal_id=…&reference=…. Use it for the UI, but confirm the principal against the webhook or GET /v1/network/connections before trusting it: anyone can craft that URL.curl -X POST https://api.vennio.app/v1/bookings \
-H "Authorization: Bearer $VENNIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"principal_id": "903f701d-…",
"customer_email": "jane@example.com",
"customer_name": "Jane Doe",
"start_time": "2026-07-01T13:00:00Z",
"end_time": "2026-07-01T13:30:00Z"
}'
The booking's business_id (and principal_id) is the host — attribution is automatic, and the calendar event lands on the host's calendar.
import { Vennio } from '@vennio/sdk';
const vennio = new Vennio(process.env.VENNIO_API_KEY!);
const host = await vennio.hosts.create({ display_name: 'Coach Alice' });
const link = await vennio.hosts.createConnectLink(host.principal_id);
// → email link.connect_url to the coach
const result = await vennio.bookings.create({
principal_id: host.principal_id,
customer_email: 'jane@example.com',
customer_name: 'Jane Doe',
start_time: '2026-07-01T13:00:00Z',
end_time: '2026-07-01T13:30:00Z',
});
AI agents can do the same over MCP with the provision_host, list_hosts, create_host_connect_link, and create_booking (with principal_id) tools.
principal_id returns 403.DELETE /v1/hosts/:id removes delegated authority; the host's profile, calendar, and past bookings are retained.