Integrations
Third-party CRM, calendar, telephony, and scheduling APIs.
Base URL: https://events.pana.space/api
Product guides: Integrations overview — connect Calendly, Google Calendar, Microsoft Calendar, HubSpot, Attio, Pipedrive, Salesforce, Zoho CRM, Microsoft Dynamics 365, Knowlarity, Slack, and Microsoft Teams from Settings → Integrations. Email sending uses mailboxes.
Full schemas: Interactive API explorer
Platform API (recommended)
Workspace-scoped routes require JWT auth and workspace admin for connect; member for callback and list.
Base path:
/api/v1/{workspace_id}/integrations/
Global connection routes (no workspace in path):
/api/v1/integrations/connections/{connection_id}/
List catalog
GET /api/v1/{workspace_id}/integrations/catalog/
Authorization: Bearer <token>
Response (200 OK)
{
"version": "a1b2c3d4e5f6g7h8",
"providers": [
{
"key": "hubspot",
"name": "HubSpot",
"category": "crm",
"logo_url": "/integrations/hubspot.svg",
"auth_type": "oauth2",
"tier": 3,
"cardinality": "one_per_workspace",
"capabilities": ["sync_contacts", "push_leads", "receive_webhooks"],
"config_schema": {
"type": "object",
"properties": {
"default_sync_event_id": { "type": "string", "format": "uuid" }
}
},
"oauth": {
"scopes": [
"crm.objects.contacts.read",
"crm.objects.contacts.write",
"crm.objects.deals.read"
]
},
"enabled": true,
"coming_soon": false,
"connected": true
}
]
}
List connections
GET /api/v1/{workspace_id}/integrations/connections/?page=1&page_size=50
Authorization: Bearer <token>
Credentials are never returned.
Response (200 OK)
{
"count": 1,
"page": 1,
"page_size": 50,
"results": [
{
"id": "880e8400-e29b-41d4-a716-446655440010",
"provider_key": "hubspot",
"auth_type": "oauth2",
"status": "connected",
"external_account_id": "",
"scopes": ["crm.objects.contacts.read", "oauth"],
"config": {
"hubspot_portal_id": "12345678"
},
"expires_at": "2026-07-06T14:30:00+00:00",
"last_sync_at": "2026-07-06T12:00:00+00:00",
"last_error": null,
"created_at": "2026-06-01T09:00:00+00:00",
"updated_at": "2026-07-06T12:00:00+00:00",
"created_by_id": "660e8400-e29b-41d4-a716-446655440001"
}
]
}
Start OAuth connect
POST /api/v1/{workspace_id}/integrations/{provider_key}/connect/
Authorization: Bearer <token>
Content-Type: application/json
Provider keys: hubspot, pipedrive, salesforce, calendly, google-calendar, knowlarity, slack
Request body (HubSpot — platform OAuth app)
Credentials come from backend env (HUBSPOT_CLIENT_ID / HUBSPOT_CLIENT_SECRET). Do not send client_id in the body.
{
"redirect_uri": "https://events.pana.space/auth/oauth/callback?provider=hubspot",
"app_domain": "https://events.pana.space"
}
Request body (Pipedrive — platform OAuth app)
Credentials come from backend env (PIPEDRIVE_CLIENT_ID / PIPEDRIVE_CLIENT_SECRET).
{
"redirect_uri": "https://events.pana.space/auth/oauth/callback?provider=pipedrive",
"app_domain": "https://events.pana.space"
}
Request body (Google Calendar — platform OAuth app)
Credentials come from backend env (GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET). Send "provider": "google" so the backend uses the calendar OAuth flow.
{
"provider": "google",
"redirect_uri": "https://events.pana.space/auth/oauth/callback/?provider=google-calendar",
"app_domain": "https://events.pana.space"
}
Request body (Slack — platform OAuth app)
Credentials come from backend env (SLACK_CLIENT_ID / SLACK_CLIENT_SECRET).
{
"redirect_uri": "https://events.pana.space/auth/oauth/callback?provider=slack",
"app_domain": "https://events.pana.space"
}
Request body (Calendly — backend OAuth callback)
Calendly redirects to the API host, not the frontend OAuth callback page.
{
"redirect_uri": "https://eventsapi.pana.space/api/v1/integrations/calendly/callback/",
"app_domain": "https://events.pana.space/events/{workspace_id}/settings/integrations"
}
app_domain is where the backend sends the user after OAuth completes (?calendly=connected).
Request body (Salesforce — per-workspace Connected App)
{
"redirect_uri": "https://events.pana.space/auth/oauth/callback?provider=salesforce",
"client_id": "3MVG9HtWXcDGV.nHyoaWmEQn51.tnGc2WbLMf_UGwN8Rx4xMiJ4P4xLiU8TmU1JuEAGzaHp8nPLdvijJT90m1",
"client_secret": "YOUR_CONSUMER_SECRET"
}
Request body (Knowlarity — API key)
{
"knowlarity_number": "+919876543210",
"sr_api_key": "your-super-receptionist-key",
"x_api_key": "your-channel-api-key"
}
Response (200 OK)
{
"auth_url": "https://app.hubspot.com/oauth/authorize?client_id=…&redirect_uri=…&state=…"
}
Redirect the user to auth_url in the browser.
Calendly exception: OAuth completes on the backend (GET …/calendly/callback/). The user is redirected to app_domain?calendly=connected — no frontend POST …/callback/ step. See Calendly guide.
Complete OAuth callback
After the provider redirects to your frontend callback page, POST the authorization code:
POST /api/v1/{workspace_id}/integrations/{provider_key}/callback/
Authorization: Bearer <token>
Content-Type: application/json
Request body (HubSpot)
{
"code": "authorization_code_from_provider",
"state": "oauth_state_from_connect_response",
"redirect_uri": "https://events.pana.space/auth/oauth/callback?provider=hubspot"
}
Request body (Pipedrive)
{
"code": "authorization_code_from_provider",
"state": "oauth_state_from_connect_response",
"redirect_uri": "https://events.pana.space/auth/oauth/callback?provider=pipedrive"
}
Request body (Google Calendar)
Include "provider": "google".
{
"code": "authorization_code_from_google",
"state": "oauth_state_from_connect_response",
"redirect_uri": "https://events.pana.space/auth/oauth/callback/?provider=google-calendar",
"provider": "google"
}
Response (200 OK) — Google Calendar
{
"connected": true,
"connection_id": "880e8400-e29b-41d4-a716-446655440010",
"message": "Google Calendar connected successfully",
"app_domain": "https://events.pana.space"
}
Salesforce may include:
{
"webhook_base_url": "https://eventsapi.pana.space"
}
Response (200 OK)
{
"connected": true,
"connection_id": "880e8400-e29b-41d4-a716-446655440010",
"message": "HubSpot connected successfully",
"app_domain": "https://events.pana.space"
}
Sync connection
POST /api/v1/integrations/connections/{connection_id}/sync/
Authorization: Bearer <token>
Content-Type: application/json
Request body (CRM sync to event)
{
"event_id": "550e8400-e29b-41d4-a716-446655440000"
}
Queue async sync (Celery):
{
"event_id": "550e8400-e29b-41d4-a716-446655440000",
"background": true
}
Response (200 OK)
{
"created": 12,
"updated": 5,
"total": 17,
"connection": {
"id": "880e8400-e29b-41d4-a716-446655440010",
"provider_key": "hubspot",
"status": "connected",
"last_sync_at": "2026-07-06T12:05:00+00:00"
}
}
Response (202 Accepted) — background sync
{
"status": "queued",
"connection_id": "880e8400-e29b-41d4-a716-446655440010"
}
Disconnect
DELETE /api/v1/integrations/connections/{connection_id}/
Authorization: Bearer <token>
Returns 204 No Content on success.
Register CRM webhook (HubSpot / Pipedrive)
After connect, register the inbound webhook with the provider (Pana UI does this for Pipedrive automatically; HubSpot uses Copy webhook or this API):
POST /api/v1/integrations/connections/{connection_id}/actions/register-webhook/
Authorization: Bearer <token>
Content-Type: application/json
Request body
{
"webhook_base_url": "https://eventsapi.pana.space"
}
Optional — omit to derive the URL from the incoming request host.
Response (200 OK)
{
"registered": true,
"webhook_url": "https://eventsapi.pana.space/api/v1/integrations/webhooks/pipedrive/550e8400-e29b-41d4-a716-446655440000/"
}
Inbound webhooks (from CRM / telephony)
POST /api/v1/integrations/webhooks/{provider_key}/{workspace_id}/
Public — no JWT. Provider-specific payload and signature verification.
| Provider | Example URL |
|---|---|
| HubSpot | https://eventsapi.pana.space/api/v1/integrations/webhooks/hubspot/{workspace_id}/ |
| Pipedrive | https://eventsapi.pana.space/api/v1/integrations/webhooks/pipedrive/{workspace_id}/ |
| Calendly | https://eventsapi.pana.space/api/v1/integrations/calendly/webhook/ |
Legacy aliases (/api/v1/integrations/hubspot/webhook/{workspace_id}/, etc.) still work but prefer the unified HubSpot/Pipedrive paths above. Calendly uses the dedicated /calendly/webhook/ route.
Set INTEGRATIONS_ASYNC_WEBHOOKS=true on the backend to queue processing via Celery.
OAuth redirect URLs
Frontend callback (HubSpot, Pipedrive, Salesforce, Google Calendar, Slack)
Register these in each provider’s developer console (production):
| Provider | Callback URL |
|---|---|
| HubSpot | https://events.pana.space/auth/oauth/callback?provider=hubspot |
| Pipedrive | https://events.pana.space/auth/oauth/callback?provider=pipedrive |
| Salesforce | https://events.pana.space/auth/oauth/callback?provider=salesforce |
| Google Calendar | https://events.pana.space/auth/oauth/callback/?provider=google-calendar |
| Slack | https://events.pana.space/auth/oauth/callback?provider=slack |
Local development: replace host with http://localhost:3000.
Backend callback (Calendly only)
Calendly OAuth completes on the API host:
https://eventsapi.pana.space/api/v1/integrations/calendly/callback/
Local: http://localhost:8000/api/v1/integrations/calendly/callback/
Set API_BASE_URL or CALENDLY_CALLBACK_URL on the backend if the public API origin differs from the request host. See Calendly guide.
Connect flow summary
Standard OAuth (HubSpot, Pipedrive, Salesforce, Google Calendar, Slack):
POST …/{provider_key}/connect/→{ "auth_url": "…" }- User completes OAuth in browser
- Frontend receives
code+stateat/auth/oauth/callback?provider=… POST …/{provider_key}/callback/→{ "connected": true, "connection_id": "…" }GET …/connections/→ list connections (no secrets)POST …/connections/{id}/sync/→ sync data (CRM contacts or Calendly bookings)
Calendly:
POST …/calendly/connect/with backendredirect_uriandapp_domain- User completes OAuth at Calendly
GET …/calendly/callback/on the API (backend exchanges code, registers webhook)- Browser redirect to
app_domain?calendly=connected
Knowlarity: API-key connect via connect body — no OAuth redirect.
Legacy per-provider routes
These remain for backward compatibility. New clients should use the platform API above.
Base path: /api/v1/integrations/
Most routes require JWT auth. OAuth callbacks and provider webhooks are public.
Google Places
GET /api/v1/integrations/google-places/autocomplete/
GET /api/v1/integrations/google-places/details/
Google Calendar
Prefer platform connect/callback with provider_key=google-calendar and "provider": "google" in the body.
Legacy calendar routes (Google / Outlook):
POST /api/v1/integrations/calendar/connect/
POST /api/v1/integrations/calendar/callback/
GET /api/v1/integrations/calendar/status/
POST /api/v1/integrations/calendar/disconnect/
POST /api/v1/integrations/calendar/create-demo-event/
Connect (platform) — returns { "auth_url": "https://accounts.google.com/o/oauth2/v2/auth?…" }.
Callback (platform) — include "provider": "google".
Create demo event — { "workspace_id": "<uuid>", "start_time": "…", "end_time": "…", "attendee_email": "…" } creates a Google Calendar event with Meet link.
Pana event sync — when a workspace event has calendar_sync_enabled, create/update triggers Google Calendar sync. Virtual, hybrid, and webinar events also receive a Google Meet link on the calendar entry. The Meet URL is saved on the event as custom_fields_data.google_calendar_meet_link.
Setup guide: Google Calendar integration
Calendly
Prefer platform connect (POST …/calendly/connect/) with backend redirect_uri. OAuth callback is GET on the API — not the frontend OAuth page.
POST /api/v1/{workspace_id}/integrations/calendly/connect/
GET /api/v1/integrations/calendly/callback/
GET /api/v1/integrations/calendly/status/
POST /api/v1/integrations/calendly/disconnect/
GET /api/v1/integrations/calendly/sync/
POST /api/v1/integrations/calendly/webhook/
GET /api/v1/integrations/calendly/event-types/
GET /api/v1/integrations/calendly/available-times/
POST /api/v1/integrations/calendly/create-meeting/
POST /api/v1/integrations/calendly/create-booking/
Connect — { "redirect_uri": "https://eventsapi.pana.space/api/v1/integrations/calendly/callback/", "app_domain": "https://events.pana.space/…" }.
Sync — GET …/sync/?workspace_id=<uuid> or platform POST …/connections/{id}/sync/.
Webhook — Calendly POSTs invitee events to …/calendly/webhook/ (registered automatically on connect).
Setup guide: Calendly integration
HubSpot
Legacy workspace-agnostic routes. Prefer platform connect/callback with provider_key=hubspot.
POST /api/v1/integrations/hubspot/connect/
POST /api/v1/integrations/hubspot/callback/
GET /api/v1/integrations/hubspot/status/
POST /api/v1/integrations/hubspot/disconnect/
POST /api/v1/integrations/hubspot/sync/
GET /api/v1/integrations/hubspot/meetings/
POST /api/v1/integrations/hubspot/webhook/{workspace_id}/
POST /api/v1/integrations/hubspot/register-webhook/
Connect — same body as platform API; returns { "auth_url": "…" }.
Sync — { "event_id": "<uuid>", "auto_sync": true } to set default 30-minute auto-sync event.
Meetings — GET …/meetings/?workspace_id=<uuid>&start=<iso>&end=<iso>&sync_demo_bookings=true returns HubSpot CRM meetings for the date range. When sync_demo_bookings=true (default), upserts matching rows in Demo Bookings (source=hubspot, keyed by hubspot_meeting_id). Response includes optional demo_booking_sync: { created, updated }.
Setup guide: HubSpot integration
Pipedrive
Legacy workspace-agnostic routes. Prefer platform connect/callback with provider_key=pipedrive.
POST /api/v1/integrations/pipedrive/connect/
POST /api/v1/integrations/pipedrive/callback/
GET /api/v1/integrations/pipedrive/status/
POST /api/v1/integrations/pipedrive/disconnect/
POST /api/v1/integrations/pipedrive/sync/
POST /api/v1/integrations/pipedrive/webhook/{workspace_id}/
POST /api/v1/integrations/pipedrive/register-webhook/
Connect — same body as platform API; returns { "auth_url": "https://oauth.pipedrive.com/oauth/authorize?…" }.
Sync — { "event_id": "<uuid>" } imports persons as leads on that event.
Setup guide: Pipedrive integration
Salesforce
POST /api/v1/integrations/salesforce/connect/
POST /api/v1/integrations/salesforce/callback/
GET /api/v1/integrations/salesforce/status/
POST /api/v1/integrations/salesforce/disconnect/
POST /api/v1/integrations/salesforce/sync/
POST /api/v1/integrations/salesforce/webhook/{workspace_id}/
POST /api/v1/integrations/salesforce/setup-webhook/
Knowlarity (telephony)
POST /api/v1/integrations/knowlarity/connect/
GET /api/v1/integrations/knowlarity/status/
POST /api/v1/integrations/knowlarity/disconnect/
POST /api/v1/integrations/knowlarity/register-notifications/
POST /api/v1/integrations/knowlarity/webhook/{workspace_id}/
Slack
Legacy workspace-agnostic routes. Prefer platform connect/callback with provider_key=slack.
POST /api/v1/integrations/slack/connect/
POST /api/v1/integrations/slack/callback/
GET /api/v1/integrations/slack/status/
POST /api/v1/integrations/slack/disconnect/
GET /api/v1/integrations/slack/channels/
POST /api/v1/integrations/slack/test-notification/
POST /api/v1/integrations/webhooks/slack/{workspace_id}/
Connect — body includes redirect_uri (frontend callback with ?provider=slack). Returns { "auth_url": "https://slack.com/oauth/v2/authorize?…" }.
Callback — exchange code + state after OAuth. Stores bot token and default_channel from Slack’s incoming_webhook payload in Connection.config.
Test notification — POST …/test-notification/ with { "workspace_id": "<uuid>", "channel": "<channel_id>", "message": "…" }. Requires an active Slack connection.
Inbound webhook — optional Events API endpoint at POST …/webhooks/slack/{workspace_id}/. Requires SLACK_SIGNING_SECRET for signature verification in production.
Setup guide: Slack integration
Environment variables
Backend operator configuration is documented in backend/.env.example. Key variables:
| Variable | Providers |
|---|---|
HUBSPOT_CLIENT_ID, HUBSPOT_CLIENT_SECRET | HubSpot |
PIPEDRIVE_CLIENT_ID, PIPEDRIVE_CLIENT_SECRET | Pipedrive |
SALESFORCE_CLIENT_ID, SALESFORCE_CLIENT_SECRET | Salesforce (optional fallback) |
GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET | Google Calendar (prefer over GOOGLE_OAUTH_*) |
CALENDLY_CLIENT_ID, CALENDLY_CLIENT_SECRET | Calendly |
API_BASE_URL | Calendly OAuth/webhook public API origin (e.g. https://eventsapi.pana.space) |
CALENDLY_CALLBACK_URL | Calendly OAuth redirect override (optional) |
CALENDLY_WEBHOOK_SIGNING_KEY | Calendly inbound webhook signature verification |
SLACK_CLIENT_ID, SLACK_CLIENT_SECRET, SLACK_SIGNING_SECRET | Slack |
Salesforce workspaces can also store per-workspace Consumer Key/Secret via the connect API.
Outbound webhooks (your app)
For your webhook subscriptions (lead.created, etc.), use Developers → Webhooks — separate from CRM inbound webhooks above.