Calendly
Connect a Calendly account and your agents can offer real availability, book the meeting, and read back what is already scheduled, all during the call.
How it works
Connect a Calendly account once, choose which agents may use it, and give each one a read or a write grant. During a call the agent can offer real availability and read what is already booked, and with write it can book the meeting, all against your live account. The invitee gets Calendly's own confirmation email, and the meeting lands on the calendar behind the event type. The grant is the whole story, and everything below follows from it.
Connect your Calendly account
There are two ways in, and both end as the same connection. A personal access token is the whole integration for a team automating its own calendar: create one in Calendly's API settings and send it. It does not expire. OAuth is how someone else's Calendly becomes the connected account: call the authorize endpoint, send them to the URL it returns, and the callback finishes the connection as whoever consented. Connecting needs an API key with integrations:write; reading connections back needs integrations:read. Reconnecting Calendly replaces your previous connection.
curl -X POST https://api.aethexai.com/api/v1/integrations \
-H "X-API-Key: $AETHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "calendly",
"auth_type": "api_key",
"access_token": "<your-calendly-token>",
"display_name": "Sales calendar"
}'
# 201 Created. The access token is never returned.
# Note the "id" it returns; every call below takes it.
export CONNECTION_ID=<the "id" from the response>What your agent can do
What an agent can reach depends on the level it was granted, and that is settled when the call is assembled: an action outside the grant is never offered to the model. A read-only agent does not decline to book, it has no notion of booking to decline. These are the tools, and the grant each one needs.
| Tool | What it does | Grant |
|---|---|---|
calendly_list_event_types | Lists your active meeting types with each one's length and description. Availability and booking both start from one, so this runs first. | read |
calendly_list_available_times | Returns bookable start times for a meeting type, up to 7 days ahead. Times come back in UTC and the agent converts them to the caller's timezone. | read |
calendly_list_upcoming_meetings | Lists meetings still to come, soonest first, and can be narrowed to one invitee's email address. | read |
calendly_book_meeting | Books one of those times for the caller, after the agent has confirmed the time, name and email out loud. Success returns Calendly's own cancel and reschedule links. | write |
enabled_tools narrows it, and it is set at connect time, so decide it on the first connect rather than reconnecting to add it later, since reconnecting revokes the connection you already granted and hands you a new id.curl -X POST https://api.aethexai.com/api/v1/integrations \
-H "X-API-Key: $AETHEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "calendly",
"auth_type": "api_key",
"access_token": "<your-calendly-token>",
"agents": [ { "agent_id": "<agent-uuid>", "access": "write" } ],
"config": {
"enabled_tools": [
"calendly_list_event_types",
"calendly_list_available_times",
"calendly_book_meeting"
]
}
}'What a booking needs
Calendly refuses a booking that does not match the event type's own configuration, so Aethex reads that configuration first and tells the agent what to collect while the caller is still on the line.
| What | Needed | Notes |
|---|---|---|
| Name and email | Always | The email is where Calendly sends the confirmation and the calendar invite. |
| Timezone | Optional | Defaults to your Calendly profile timezone, or UTC. Pass the caller's when you know it. |
| Location | Sometimes | Needed when the event type offers a choice, or asks for a phone number or address only the caller can give. |
| Required questions | Sometimes | Any questions configured on the event type must be answered, or the booking is refused. |
Read it back, and revoke it
Two questions come up as soon as an agent is live. To check a grant took, read it back with GET /api/v1/integrations/{id}/agents, which needs integrations:read; none of the read endpoints ever return the credential. To turn it off, DELETE /api/v1/integrations/{id} needs integrations:write, and it is idempotent, answering 204 whether the connection was active, already revoked, or never yours. Revoking takes effect immediately, including on calls already in progress.
# Which agents can use this connection, and at what level
curl https://api.aethexai.com/api/v1/integrations/$CONNECTION_ID/agents \
-H "X-API-Key: $AETHEX_API_KEY"
# Revoke it. Idempotent: 204 whether it was active or already gone.
curl -X DELETE https://api.aethexai.com/api/v1/integrations/$CONNECTION_ID \
-H "X-API-Key: $AETHEX_API_KEY"When a call fails
The three calls here are connecting, setting agents, and revoking, and they do not fail the same way, so read the label on each card. 401 and 403 apply to everything, reads included, and fire before any handler runs. Past that, connecting can return any of 404, 409, 422, 429 or 503, setting agents returns only 404 or 409, and revoking is idempotent and answers 204.
Every call on this page, before any handler runs. No X-API-Key header, or a key that is invalid, revoked or expired.
Send a live key. Missing API key means the header never arrived; Invalid or expired API key means it did not match.
Every call, before any handler runs. The key is valid but lacks the scope this call needs: integrations:write to connect, set agents or revoke, integrations:read for the reads.
The detail names the missing scope. Scopes are fixed at key creation, so mint a key that carries it rather than widening this one.
Connecting and setting agents. The connection is not yours or no longer active, or an agent_id is not one of your agents.
Check the connection id from the connect response, and that every agent_id is an agent on this tenant. A foreign id is deliberately indistinguishable from a missing one.
Connecting and setting agents. A concurrent request changed the same connection or the same grants.
Re-read the connection, then re-send. The grant body is declarative, so a retry converges rather than compounding.
Connecting, when Calendly rejects the credential Aethex validated. Any call carrying a body can also return a plain schema 422 for a malformed field.
Read the detail. A schema 422 names the field to fix; a connect 422 means the credential was refused, so reissue the personal access token from Calendly's API settings.
Connect only. More than 10 connect attempts in 60 seconds from one tenant.
Wait for the window in the Retry-After header. Connecting is a one-time setup, so this usually means a retry loop worth fixing.
Connect only. Calendly was unreachable, the encryption key is missing on this deployment, or the rate limiter is offline.
Retry, and read the detail for which of the three you hit. A Calendly outage clears on its own; a missing key or offline limiter is ours and keeps failing until fixed.
Notes and limits
A few things worth knowing before you plan around them.
| Limit | What it means |
|---|---|
| Seven days is the ceiling | Calendly refuses an availability search wider than a week, so an agent cannot offer a slot three weeks out. |
| No cancel or reschedule | Neither is offered as an action. The agent hands over Calendly's own cancel and reschedule links from the booking instead. |
| Reconnecting clears grants | Reconnecting Calendly revokes the previous connection and starts with no agent, so nothing carries over. Grant them again afterwards. |
| Grants apply at call start | Removing a grant takes effect on the next call, not one already in progress. Disconnecting bites immediately. |
| One account per connection | Every action runs as the user the credential belongs to, over that user's active event types. A connection never sees a second calendar. |
