Zidi
API Reference
Zidi is a video platform for sales and marketing teams: record and share videos, send them as personalised campaigns, and track how each recipient engages. This is the public REST API that powers the Zidi integrations, including the Zidi app for Zapier. Every endpoint below is served over HTTPS from https://app.zidi.ai.
Integration access requires a Zidi Pro plan. All responses are JSON.
Authentication
Zidi is an OAuth 2.0 provider and implements the authorization code grant with refresh tokens (RFC 6749). Access tokens are bearer tokens valid for one hour; refresh tokens rotate on every use, and a rotated token presented again is treated as replay and revokes the whole grant (RFC 9700 §4.13.2). Tokens carry the scopes read, write and webhooks.
A refresh token that has not been used for 365 days expires, and the connection has to be reconnected before it works again.
/api/zapier/auth/authorizeauth: SessionStarts the flow. Required query parameters: client_id, redirect_uri (must exactly match the registered value) and state. Signed-out users are sent to sign in first, then to a branded consent screen naming the account and the scopes being granted. An account that is not on the Pro plan is shown an upgrade page instead of the consent screen. Approving redirects back to your redirect_uri with code and the original state. Cancelling returns error=access_denied instead.
/api/zapier/auth/tokenauth: Basic or bodyForm-encoded. Client credentials go in an HTTP Basic header or as client_id / client_secret body fields. Two grants are supported.
POST /api/zapier/auth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=<code from /authorize>
&redirect_uri=<same value used at /authorize>
# or
grant_type=refresh_token
&refresh_token=<refresh token>{
"access_token": "b3c1…",
"refresh_token": "9f2a…",
"expires_in": 3600,
"token_type": "Bearer"
}redirect_uri is required on the authorization code grant and must match the value used at /authorize. Failures use the standard OAuth error codes — invalid_grant, invalid_client, unsupported_grant_type.
/api/zapier/auth/meauth: BearerConnection test. Returns the authenticated account, which integrations use to label the connection.
{
"id": "cku1…",
"name": "Alex Rivera",
"email": "[email protected]",
"workspaceId": "2e0d6168-735e-424e-87f5-2978eb0e5c94"
}Making requests
Every endpoint below authenticates with the access token as a bearer credential. There is no API-key alternative.
curl https://app.zidi.ai/api/zapier/triggers/new-video \
-H "Authorization: Bearer <access_token>"A missing, expired or revoked token — or an account no longer on a Pro plan — returns 401 with {"error":"Unauthorized"}.
Polling endpoints
Each endpoint returns a JSON array of the account's most recent records, newest first, capped at 100. They are the polling counterpart to the webhook subscriptions below — integrations use them to fetch sample data while a user builds an automation, and to populate record pickers.
/api/zapier/triggers/new-videoauth: BearerVideos in the account, newest first.
[
{
"id": "b705b483-5aef-4993-ba13-317db07f0b5a",
"title": "Q3 product walkthrough",
"videoUrl": "https://app.zidi.ai/preview/b705b483-5aef-4993-ba13-317db07f0b5a",
"sourceUrl": "https://…signed download link, valid 7 days…",
"views": 12,
"duration": 126,
"sourceType": "UPLOAD",
"timestamp": "2026-08-14T08:42:20.358Z"
}
]/api/zapier/triggers/video-viewedauth: BearerIdentified views. Triggers only fire for viewers Zidi can identify — anonymous views are excluded.
[
{
"id": "cmst207pe000b1anpqcuckn2u",
"videoId": "b705b483-5aef-4993-ba13-317db07f0b5a",
"videoTitle": "Q3 product walkthrough",
"viewerEmail": "[email protected]",
"viewerName": "Alex Rivera",
"company": "Example Inc",
"campaignName": "Q3 outreach",
"watchDurationSec": 100,
"percentWatched": 100,
"totalViews": 3,
"timestamp": "2026-08-14T14:40:03.842Z"
}
]/api/zapier/triggers/cta-clickedauth: BearerCall-to-action clicks. CTA copy is configured per video.
[
{
"id": "cta-campaign-MGwwynLzOBFwcbhQ",
"ctaId": "campaign-MGwwynLzOBFwcbhQ",
"ctaLabel": "Book a demo",
"ctaUrl": "https://example.com/demo",
"videoId": "b705b483-5aef-4993-ba13-317db07f0b5a",
"videoTitle": "Q3 product walkthrough",
"viewerEmail": "[email protected]",
"viewerName": "Alex Rivera",
"company": "Example Inc",
"campaignName": "Q3 outreach",
"timestamp": "2026-08-14T08:46:16.769Z"
}
]/api/zapier/triggers/campaign-launchedauth: BearerCampaigns that have been launched, most recent first.
[
{
"id": "9f76b2b6-acb1-42c8-9cbb-d0ede7d0a659",
"campaignId": "9f76b2b6-acb1-42c8-9cbb-d0ede7d0a659",
"campaignName": "Q3 outreach",
"status": "ACTIVE",
"videoId": "b705b483-5aef-4993-ba13-317db07f0b5a",
"videoTitle": "Q3 product walkthrough",
"recipientCount": 42,
"timestamp": "2026-08-14T08:43:52.998Z"
}
]/api/zapier/triggers/engagement-threshold?thresholdPercent=50auth: BearerViews that reached a watch-percentage threshold. thresholdPercent is optional and defaults to 50; values are clamped to 0–100. Zidi records milestones at 50%, 80% and 100%, and thresholdCrossed reports the highest milestone that view reached.
[
{
"id": "cmst207pe000b1anpqcuckn2u",
"videoId": "b705b483-5aef-4993-ba13-317db07f0b5a",
"videoTitle": "Q3 product walkthrough",
"viewerEmail": "[email protected]",
"viewerName": "Alex Rivera",
"company": "Example Inc",
"campaignName": "Q3 outreach",
"percentWatched": 82.5,
"watchDurationSec": 95,
"thresholdCrossed": 80,
"thresholdPercent": 50,
"timestamp": "2026-08-14T14:40:03.842Z"
}
]Webhook subscriptions
For real-time delivery, subscribe a HTTPS endpoint to an event type. Zidi then POSTs each matching event to that URL. Subscriptions are scoped to the authenticated account.
/api/zapier/webhooks/subscribeauth: Bearer{
"hookUrl": "https://hooks.example.com/abc123",
"triggerType": "engagement.threshold",
"inputFields": { "thresholdPercent": 80 }
}triggerType is one of video.uploaded, video.viewed, cta.clicked, campaign.launched or engagement.threshold. inputFields is only meaningful for engagement.threshold, where thresholdPercent filters which milestones are delivered.
hookUrl must be HTTPS. URLs that resolve to loopback, private or link-local addresses are rejected, and the resolved address is re-checked and pinned at delivery time.
{ "id": "cmsvbrrd600031hpey38yswlm" }/api/zapier/webhooks/unsubscribeauth: BearerPass the subscription id returned by subscribe. Responds {"success":true}.
{ "id": "cmsvbrrd600031hpey38yswlm" }Webhook delivery
Deliveries are HTTP POSTs with a JSON body carrying the same fields as the matching polling endpoint, so an automation mapped against polled sample data finds the same keys on a live delivery.
POST /your-endpoint
Content-Type: application/json
X-Zidi-Signature: 3f9a… # HMAC-SHA256 of the raw body, hex
X-Zidi-Timestamp: 2026-08-16T08:29:15.297ZVerify a delivery by computing HMAC-SHA256(raw_body, workspace_secret) and comparing it to X-Zidi-Signature in constant time. The timestamp is also inside the signed body, so a captured payload cannot be replayed with a fresher header.
Deliveries pause while the workspace is not on the Pro plan and resume automatically once it is on Pro again. Your webhook subscriptions are kept. If you downgraded your plan, reconnect your Zidi account in Zapier first — as you also must after the idle expiry described under Authentication above, which is the other reason a connection stops working.
Retries use exponential backoff over roughly twenty minutes on 5xx and network failures. A 410 Gone response deactivates the subscription — return it when the destination is permanently gone. Other 4xx responses are treated as terminal for that delivery.
Read actions
Lookup endpoints for enriching an automation with data about a specific video or campaign.
/api/zapier/actions/video/{videoId}auth: BearerDetails for one video the authenticated account owns.
{
"id": "b705b483-5aef-4993-ba13-317db07f0b5a",
"title": "Q3 product walkthrough",
"description": null,
"sourceUrl": "https://…signed download link, valid 7 days…",
"previewUrl": "https://app.zidi.ai/preview/b705b483-5aef-4993-ba13-317db07f0b5a",
"views": 12,
"duration": 126,
"sourceType": "UPLOAD",
"ctaLabel": "Book a demo",
"ctaUrl": "https://example.com/demo",
"createdAt": "2026-08-14T08:42:20.358Z"
}/api/zapier/actions/video/{videoId}/engagementauth: BearerAggregate engagement statistics for one video.
{
"videoId": "b705b483-5aef-4993-ba13-317db07f0b5a",
"videoTitle": "Q3 product walkthrough",
"totalViews": 12,
"uniqueViewers": 9,
"averageWatchPercent": 63.4,
"totalWatchTimeSec": 1840,
"ctaClicks": 3
}/api/zapier/actions/campaign/{campaignId}/recipientsauth: BearerCampaign recipients with their engagement. Paginate with page (default 1) and pageSize (default 50, maximum 100).
{
"campaignId": "9f76b2b6-acb1-42c8-9cbb-d0ede7d0a659",
"campaignName": "Q3 outreach",
"recipients": [
{
"id": "8f010ba4-9d8c-420a-8112-df1bc6afcd33",
"email": "[email protected]",
"personalizedUrl": "https://app.zidi.ai/c/yA4Co_A06u5S3kff",
"tokens": { "firstName": "Alex", "company": "Example Inc" },
"totalViews": 1,
"watchPercent": 100,
"ctaClicked": true,
"firstViewedAt": "2026-08-16T08:02:02.121Z",
"lastViewedAt": "2026-08-16T08:02:17.332Z"
}
],
"pagination": { "page": 1, "pageSize": 50, "total": 1, "totalPages": 1 }
}An id that does not exist, is malformed, or belongs to another account returns 404 — the API does not distinguish those cases.
Errors and limits
Errors are JSON with an error field and a matching HTTP status.
| Status | Meaning |
|---|---|
| 400 | Malformed body, missing field, or invalid parameter |
| 401 | Missing, expired or revoked token, or no Pro plan |
| 404 | Record not found, or not owned by this account |
| 429 | Rate limited — see the Retry-After header |
The OAuth endpoints allow 10 requests per minute per IP address. Polling endpoints return at most 100 records per call.
Recipient privacy
Campaigns carry an owner-controlled setting for whether recipient identity may leave Zidi. When it is off, events and recipient listings withhold the email address and merge fields, substituting a stable recipientHash so automations can still deduplicate a person across events. Engagement statistics and the personalised link are always included, since neither is derived from identity.
Triggers fire only for viewers Zidi can identify; anonymous views never produce an event.