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.

GET/api/zapier/auth/authorizeauth: Session

Starts 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.

POST/api/zapier/auth/tokenauth: Basic or body

Form-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.

GET/api/zapier/auth/meauth: Bearer

Connection 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.

GET/api/zapier/triggers/new-videoauth: Bearer

Videos 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"
  }
]
GET/api/zapier/triggers/video-viewedauth: Bearer

Identified 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"
  }
]
GET/api/zapier/triggers/cta-clickedauth: Bearer

Call-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"
  }
]
GET/api/zapier/triggers/campaign-launchedauth: Bearer

Campaigns 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"
  }
]
GET/api/zapier/triggers/engagement-threshold?thresholdPercent=50auth: Bearer

Views 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.

POST/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" }
DELETE/api/zapier/webhooks/unsubscribeauth: Bearer

Pass 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.297Z

Verify 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.

GET/api/zapier/actions/video/{videoId}auth: Bearer

Details 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"
}
GET/api/zapier/actions/video/{videoId}/engagementauth: Bearer

Aggregate 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
}
GET/api/zapier/actions/campaign/{campaignId}/recipientsauth: Bearer

Campaign 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.

StatusMeaning
400Malformed body, missing field, or invalid parameter
401Missing, expired or revoked token, or no Pro plan
404Record not found, or not owned by this account
429Rate 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.