Zapier integration reference

Authentication, scopes, endpoints, webhook lifecycle, operation contracts, examples, and retry behavior for the First AI Employee Zapier integration v1.0.1.

View all 10 operationsReview authentication
Version
1.0.1

Saved private draft

Triggers
5

REST hooks

Actions and searches
3 + 2

Five inbound operations

Authentication
OAuth 2.0

Authorization code

What this integration exposes

Version 1.0.1 is the private Zapier Platform integration for First AI Employee. It exposes five REST hook triggers, three create actions, and two searches. Every request is tenant-scoped by the OAuth grant. Callers never supply a business or customer ID.

Official paths

OAuth and the Zapier API are served from https://api.firstaiemployee.com. The authenticated base path is https://api.firstaiemployee.com/api/zapier.

  • Every event payload is flat and has a stable top-level id so Zapier can deduplicate it.
  • Event timestamps use ISO 8601 UTC strings. Appointments preserve their local date and time together with the account IANA time zone.
  • Contacts and Requests endpoints honor whether those Front Desk modules are available on the authorized account.

Authentication and scopes

Zapier uses the OAuth 2.0 authorization-code grant as a registered confidential client. The account owner reviews the requested scopes on the First AI Employee consent page. The Zapier client authenticates at the token endpoint with its registered client credentials. PKCE is accepted when supplied, but it is not mandatory for this confidential Zapier client.

Request and response
GET https://api.firstaiemployee.com/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=YOUR_REGISTERED_REDIRECT_URI
  &response_type=code
  &scope=leads%3Aread%20calls%3Aread%20bookings%3Aread%20bookings%3Awrite%20contacts%3Aread%20contacts%3Awrite%20requests%3Aread%20requests%3Awrite
  &state=RANDOM_CSRF_VALUE

Eight requested scopes

ScopeAccess
leads:readRead new lead events and trigger samples.
calls:readRead completed calls, including transcript text.
bookings:readRead booking events and find exact bookings.
bookings:writeCreate a booking or captured appointment request.
contacts:readRead contact events and find a contact by phone.
contacts:writeCreate or reuse a contact by normalized phone.
requests:readRead customer Request events and trigger samples.
requests:writeCreate an idempotent Request for an existing contact.

Scopes are enforced both when a subscription is created and when each event is delivered. Reauthorization never silently widens an existing grant.

OAuth endpoints and token lifecycle

Access tokens last one hour. Refresh tokens rotate on every successful use and expire after 90 days of inactivity. Reusing an authorization code or an already-used refresh token revokes the grant because replay cannot be distinguished from credential theft.

Request and response
POST https://api.firstaiemployee.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&code=ONE_TIME_AUTHORIZATION_CODE
&redirect_uri=YOUR_REGISTERED_REDIRECT_URI

200 OK
{
  "access_token": "REDACTED",
  "refresh_token": "REDACTED",
  "token_type": "bearer",
  "expires_in": 3600,
  "scope": "leads:read calls:read bookings:read bookings:write contacts:read contacts:write requests:read requests:write"
}
Rotating refresh
POST https://api.firstaiemployee.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&refresh_token=CURRENT_REFRESH_TOKEN

200 OK
{
  "access_token": "REDACTED",
  "refresh_token": "NEW_ROTATED_REFRESH_TOKEN",
  "token_type": "bearer",
  "expires_in": 3600,
  "scope": "..."
}

Protocol endpoints

MethodPathAuthenticationPurpose
GET/oauth/authorizeBrowser sessionStart the authorization-code flow and render owner consent.
POST/oauth/authorizeBrowser session + CSRFSubmit the owner consent form. Browser-only, not a partner API call.
GET/oauth/resumeSigned resume tokenResume the same authorization request after sign-in. Browser-only.
POST/oauth/tokenConfidential clientExchange a code or rotate a refresh token.
  • redirect_uri must exactly match one of the client registered redirect URIs.
  • Authorization codes are single-use. Do not resubmit a code exchange after an ambiguous result.
  • Persist the new refresh_token from every successful response before refreshing again.
  • A 401 can mean the access token expired. A successful refresh and retry leave the connection active. If /oauth/token returns invalid_grant because authorization was revoked, reconnect that saved account.
  • Each saved connection has its own grant. Reconnecting one does not repair other revoked connections. Check the authorized business before publishing the Zap.
  • A 403 can mean insufficient scopes or an unavailable module. Check error and error_description before reauthorizing.

Trigger and webhook lifecycle

All five triggers use the same subscription lifecycle. Zapier creates the subscription when a Zap is turned on, receives flat JSON events, and deletes the subscription when the Zap is turned off.

  1. When a Zap is turned on, Zapier sends POST /api/zapier/hooks with targetUrl and one of the five supported events.
  2. First AI Employee requires HTTPS on the exact hooks.zapier.com host, checks the event scope, and returns 201 with the subscription ID.
  3. When the event occurs, First AI Employee posts one flat JSON payload to the Zapier URL. A write originating from that same grant is not echoed back to the same connection.
  4. When the Zap is turned off, Zapier sends DELETE /api/zapier/hooks/{id} and receives 204.
Subscribe
POST https://api.firstaiemployee.com/api/zapier/hooks
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json

{
  "targetUrl": "https://hooks.zapier.com/hooks/standard/REDACTED/",
  "event": "case.created"
}

201 Created
{ "id": "SUBSCRIPTION_UUID", "event": "case.created" }
Event delivery
POST https://hooks.zapier.com/hooks/standard/REDACTED/
Content-Type: application/json

{
  "id": "REQUEST_UUID",
  "eventId": "REQUEST_UUID",
  "event": "case.created",
  "source": "First AI Employee",
  "occurredAt": "2026-08-31T12:00:00.000Z",
  "businessName": "Example Service Company",
  "requestId": "REQUEST_UUID",
  "contactId": "CONTACT_UUID",
  "jobId": null,
  "summary": "Customer needs a repair estimate",
  "description": "Call before arriving.",
  "category": "quote",
  "priority": "normal",
  "status": "open",
  "requestSource": "zapier",
  "firstResponseTargetAt": null,
  "resolutionTargetAt": null
}

Current delivery is a single best-effort POST with an eight-second timeout. A non-2xx response or network failure is logged and never blocks the customer record being saved. This route does not currently provide a server-side redelivery queue.

Operation coverage for v1.0.1

These are the ten visible Zapier operations and the exact API contracts behind them. Trigger test endpoints return up to three recent records or one clearly marked synthetic sample when the account has no matching records.

TypeOperationMethod and pathScopeInputResult and behavior
TriggerNew Leadnew_leadlead.createdGET
/api/zapier/leads
leads:readNoneLead or clearly marked sample array with id, contact, call, outcome, and occurredAt fields.
Subscribes through the shared REST hook lifecycle and emits after a completed lead call.
TriggerNew Bookingnew_bookingbooking.createdGET
/api/zapier/bookings
bookings:readNoneBooking or clearly marked sample array with date, time, timeZone, status, and calendarWritten.
Emits when an appointment is recorded, whether it was written to a calendar or only captured.
TriggerCompleted Callcall_completedcall.completedGET
/api/zapier/calls
calls:readNoneCall or clearly marked sample array with summary, transcript, intent, outcome, duration, and occurredAt.
Uses a separate permission because the payload can contain sensitive transcript text.
TriggerNew Contactcontact_createdcontact.createdGET
/api/zapier/contacts
contacts:readNoneContact or clearly marked sample array with contactId, identity, source, stage, and occurredAt.
Available when the Front Desk Contacts module is enabled for the account.
TriggerNew Requestcase_createdcase.createdGET
/api/zapier/requests
requests:readNoneRequest or clearly marked sample array with requestId, contactId, summary, priority, status, and occurredAt.
The customer-facing name is Request. The stable wire event remains case.created.
ActionCreate Bookingcreate_bookingPOST
/api/zapier/bookings
bookings:writename, date (YYYY-MM-DD), time (HH:MM), optional reasonstatus, detail, name, date, time, reason
A captured status means the appointment was recorded but no calendar write occurred.
ActionCreate or Update Contactcreate_contactPOST
/api/zapier/contacts
contacts:writephone, optional name, optional emailContact fields plus created, reused, and filledBlankFields
Normalizes the phone, reuses an exact existing contact, and only fills blank name or email fields.
ActionCreate Requestcreate_requestPOST
/api/zapier/requests
requests:writededuplicationKey (sent as sourceRecordId), contactId, summary, optional jobId, description, category, priorityRequest fields plus created and replayed
Deduplication uses the source record ID within the same OAuth grant. Reuse it only for identical details; reconnecting does not preserve this deduplication boundary.
SearchFind Contactfind_contactGET
/api/zapier/contacts/find?phone={phone}
contacts:readphoneOne-item contact array or an empty array
Matches the normalized phone exactly and supports Zapier find-or-create flows.
SearchFind Bookingfind_bookingGET
/api/zapier/bookings/find?name={name}&date={date}&time={time}
bookings:readname, date (YYYY-MM-DD), time (HH:MM)One-item booking array or an empty array
Matches exact structured name, date, and time fields. Legacy prose summaries are not guessed.

Authenticated endpoint inventory

MethodPathAuthenticationPurpose
GET/api/zapier/meBearerTest the connection and return the authorized business and scopes.
POST/api/zapier/hooksBearer + event scopeSubscribe the Zapier target URL to one supported event.
DELETE/api/zapier/hooks/{id}BearerRemove the exact subscription for this connection.
GET/api/zapier/leadsleads:readNew Lead trigger sample or recent records.
GET/api/zapier/callscalls:readCompleted Call trigger sample or recent records.
GET/api/zapier/bookingsbookings:readNew Booking trigger sample or recent records.
POST/api/zapier/bookingsbookings:writeCreate Booking action.
GET/api/zapier/bookings/findbookings:readFind Booking search.
GET/api/zapier/contactscontacts:readNew Contact trigger sample or recent records.
POST/api/zapier/contactscontacts:writeCreate or Update Contact action.
GET/api/zapier/contacts/findcontacts:readFind Contact search.
GET/api/zapier/requestsrequests:readNew Request trigger sample or recent records.
POST/api/zapier/requestsrequests:writeCreate Request action.

Request and response examples

The examples use placeholders and example data. They do not contain production credentials or customer records. All API calls use JSON except the OAuth token endpoint, which uses form encoding.

Verify a live Zap

  1. Test the connection and confirm the correct business. Review every action and its destination before turning the Zap on.
  2. An editor test retrieves a sample for field mapping. To verify delivery, publish and enable the Zap, then generate a controlled event in that same account.
  3. In Zap History, confirm the trigger and actions succeeded. Keep the Zap enabled and its successful run history available during review.
  4. To test New Contact or New Request, create the record from the dashboard or through another connection authorized to the same account. Writes are not echoed to their own grant.
  5. Find Booking searches the 200 most recent booking events using structured name, date, and time. A synthetic trigger test does not save an appointment that the search can find.

Create or reuse a contact

Request and response
POST https://api.firstaiemployee.com/api/zapier/contacts
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json

{
  "phone": "+12025550123",
  "name": "Jordan Lee",
  "email": "[email protected]"
}

201 Created
{
  "id": "CONTACT_UUID",
  "contactId": "CONTACT_UUID",
  "contactName": "Jordan Lee",
  "contactPhone": "+12025550123",
  "contactEmail": "[email protected]",
  "created": true,
  "reused": false,
  "filledBlankFields": []
}

Create a booking

Request and response
POST https://api.firstaiemployee.com/api/zapier/bookings
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json

{
  "name": "Jordan Lee",
  "date": "2026-09-02",
  "time": "15:00",
  "reason": "Estimate visit"
}

201 Created
{
  "status": "booked",
  "detail": null,
  "name": "Jordan Lee",
  "date": "2026-09-02",
  "time": "15:00",
  "reason": "Estimate visit"
}

Create an idempotent Request

Request and response
POST https://api.firstaiemployee.com/api/zapier/requests
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json

{
  "sourceRecordId": "ticket-90210",
  "contactId": "CONTACT_UUID",
  "jobId": null,
  "summary": "Customer needs a repair estimate",
  "description": "Call before arriving.",
  "category": "quote",
  "priority": "normal"
}

201 Created
{
  "id": "REQUEST_UUID",
  "requestId": "REQUEST_UUID",
  "created": true,
  "replayed": false
}

Find exact records

Request and response
GET https://api.firstaiemployee.com/api/zapier/contacts/find?phone=%2B12025550123
Authorization: Bearer ACCESS_TOKEN

200 OK
[{ "id": "CONTACT_UUID", "contactId": "CONTACT_UUID", "contactPhone": "+12025550123" }]

GET https://api.firstaiemployee.com/api/zapier/bookings/find?name=Jordan%20Lee&date=2026-09-02&time=15%3A00
Authorization: Bearer ACCESS_TOKEN

200 OK
[{ "id": "BOOKING_ID", "contactName": "Jordan Lee", "appointmentDate": "2026-09-02", "appointmentTime": "15:00" }]
  • Request categories are general, appointment, service, quote, billing, complaint, and other.
  • Request priorities are low, normal, and high. Omitted values default to general and normal.
  • Searches return a one-item array for an exact match and an empty array when no record matches.

Errors, retries, and idempotency

Errors use a stable error code and a human-readable error_description. Field validation errors may also include field. Retry safety differs by action, so do not treat every write as generically retryable.

Response
409 Conflict
Content-Type: application/json

{
  "error": "idempotency_key_reused",
  "error_description": "That Source Record ID was already used with different request details."
}

Statuses and recovery

StatusCommon codesResponse
400invalid_request, invalid_event, invalid_targetCorrect the fields, event, or target URL. Do not retry the same request.
401invalid_tokenRefresh once. If refresh fails, reconnect the account.
403insufficient_scope, front_desk_module_disabled, front_desk_dependency_disabled, front_desk_basic_not_includedFor missing scopes, reauthorize. For module errors, check Front Desk availability and settings.
404not_found, account_not_foundStop the task and confirm the record and account still exist.
409slot_taken, idempotency_key_reused, write_blockedChange the input or resolve the conflict. Do not repeat the same write.
503unavailable, front_desk_module_state_unavailableBooking service or module state is unavailable. Retry with bounded backoff; contact support if it persists.

Action-specific retry safety

  • Create or Update Contact is safe to repeat with the same normalized phone. It reuses the contact and only fills blank fields.
  • Create Request is safe to repeat within the same OAuth grant with the same Deduplication Key, sent as sourceRecordId, and identical details. It returns 200 with replayed: true and Idempotency-Replayed: true. Different details with the same key return 409. After reconnecting, check whether the Request already exists before retrying: a new grant can create a duplicate.
  • Create Booking has no general idempotency key. After an ambiguous timeout, use Find Booking with the exact name, date, and time before creating again.
  • GET requests may be retried with bounded backoff after transient failures. Do not retry 400, 403, 404, or 409 without changing the state or input.

Version, revocation, and support

This reference covers Zapier integration version 1.0.1. Customers can revoke a connection from Connected Apps in the First AI Employee dashboard. Revocation stops authenticated requests and webhook fan-out for that grant.

Access boundaries

This surface does not expose a public /oauth/revoke endpoint. The customer revokes from the dashboard. When a grant is revoked, its tokens stop working and its subscriptions stop receiving events.

Test data

Trigger test endpoints return clearly labeled synthetic data only when no real records exist. The examples on this page are synthetic too.

Integration support: [email protected]