Download OpenAPI specification:
Developer Documentation for Liftify's API
Welcome to the API documentation for Liftify, a comprehensive reputation management solution. Liftify is engineered to help businesses generate authentic reviews, enhance conversion rates, and ultimately drive revenue growth.
This platform provides an array of tools and features that empower users to effectively manage their online reputation, engage with customers, and gain valuable insights. With its user-friendly interface and robust functionality, Liftify simplifies the process of collecting and managing customer feedback, allowing businesses to focus on delivering exceptional service and achieving their growth objectives. Whether you're a small business owner or part of a large enterprise, Liftify offers scalable solutions tailored to meet your specific needs. Explore our API documentation to discover how Liftify can transform your approach to reputation management and contribute to your business success.
The Liftify's API can be accessed by a Bearer token that is used by our team. Add the token to the Authorization header of a request.
The API is reachable at https://app.liftify.com/api.
Retrieve a paginated list of customers with optional filtering by account and location.
Expandable fields: customer_campaigns, reviews
When expanded, customer_campaigns includes the full campaign object with campaign name, type, status, location, and timestamps. When not expanded, the field is omitted from the response.
When expanded, reviews includes the full review objects for each confirmed customer-review match. When not expanded (but expand options are present in the request), reviews returns an array of review_uuid strings. When no expand options are present, the reviews field is omitted from the response.
string or Array of strings The location ID in the format of "loc-" followed by the UUID. | |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
| has_reviews | boolean Filter customers that have or don't have confirmed review matches. When |
string or Array of strings Examples:
Filter customers by lifecycle status. Accepts a single value or an array of values; values are case-insensitive. When multiple values are provided, customers matching any of them are returned. Invalid values return a 400 response. | |
| last_activity_at_gt | string <date-time> Examples:
Return customers with a last_activity_at strictly greater than this value. This is an ISO 8601 date-time string. Ignored when last_activity_at_eq is present. |
| last_activity_at_gte | string <date-time> Examples:
Return customers with a last_activity_at greater than or equal to this value. This is an ISO 8601 date-time string. Ignored when last_activity_at_eq is present. |
| last_activity_at_lt | string <date-time> Examples:
Return customers with a last_activity_at strictly less than this value. This is an ISO 8601 date-time string. Ignored when last_activity_at_eq is present. |
| last_activity_at_lte | string <date-time> Examples:
Return customers with a last_activity_at less than or equal to this value. This is an ISO 8601 date-time string. Ignored when last_activity_at_eq is present. |
string or string Examples:
Filter customers whose last activity occurred on the specified date, ignoring the time portion. Accepts either an ISO‑8601 date (YYYY‑MM‑DD) or a full ISO‑8601 date-time; only the date portion is used for filtering. Precedence: When last_activity_at_eq is provided, all other date-time filters (last_activity_at_gt, last_activity_at_gte, last_activity_at_lt, last_activity_at_lte) are ignored. | |
| campaign_template_id | string Examples:
Return only customers that have at least one touchpoint belonging to this campaign (identified by its |
| touchpoint_sequence_order | integer >= 1 Examples:
Return only customers that have a touchpoint at this step of the campaign sequence (1-based). Requires |
string or Array of strings Examples:
Return only customers whose matching touchpoint is in one of these delivery states. Accepts a single value or an array of values; values are case-insensitive.
Requires |
| total_count | integer <int32> Total number of customers matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int8> Current page number |
Array of objects (CustomerListItem) |
{- "total_count": 150,
- "total_pages": 2,
- "current_page": 1,
- "customers": [
- {
- "customer_id": "cus-550e8400-e29b-41d4-a716-446655440000",
- "first_name": "Jane",
- "last_name": "Smith",
- "phone_number": "+15551234568",
- "lead_source": "google",
- "normalized_lead_source": "google",
- "lead_source_channel_type": "Google",
- "status": "active",
- "text_opt_in": true,
- "created_at": "2025-08-15T16:37:20Z",
- "updated_at": "2025-08-16T08:50:18Z",
- "account_id": "acc-test-402efb14-f779-4dfe-9a07-feb72602c8bb",
- "locations": [
- {
- "location_id": "loc-test-8c0a8daa-dbd8-4e7c-bd38-d810795512e3",
- "name": "Test Location"
}
], - "custom_fields": [
- {
- "name": "campaign",
- "value": "summer_promotion",
- "label": "Campaign",
- "type": "text"
}
]
}, - {
- "customer_id": "cus-660e8400-e29b-41d4-a716-446655440001",
- "first_name": "John",
- "last_name": "Doe",
- "phone_number": "+15551234567",
- "lead_source": "yelp",
- "normalized_lead_source": "yelp",
- "lead_source_channel_type": "Yelp",
- "status": "unsubscribed",
- "text_opt_in": false,
- "created_at": "2025-08-10T14:22:15Z",
- "updated_at": "2025-08-15T16:37:20Z",
- "account_id": "acc-test-402efb14-f779-4dfe-9a07-feb72602c8bb",
- "locations": [
- {
- "location_id": "loc-test-8c0a8daa-dbd8-4e7c-bd38-d810795512e3",
- "name": "Test Location"
}
], - "custom_fields": [ ]
}
]
}Create or update a Customer. This endpoint will NOT associated or start a campaign for a contact. A staus of unsubscribed will stop a campaign.
| account_id | string Account ID starts with "acc-" then a UUID. Required if location_name is present. |
| location_id required | string Location ID starts with "loc-" then a UUID. Required if account_id is blank. |
| location_name | string Location Name. Can be used instead of the Location ID if Account ID is present. |
| first_name | string First Name of the customer |
| last_name | string |
string <email> Required if customer_phone is blank. | |
| phone_number | string^\\+[1-9]\\d{1,14}$ Required if customer_email is blank. |
| lead_source | string or null (NormalizedLeadSource) Enum: "google" "facebook" "yelp" "bbb" "yellow pages" "angi" "homeadvisor" "nextdoor" "houzz" "trustpilot" "referral" "organic search" "direct" "email" "print" "broadcast" "event" "instagram" "linkedin" "twitter" "tiktok" "craigslist" "thumbtack" "porch" The canonical lead source value. Use these standardized values when creating or updating customers. These values are used for lead source-based review routing to match customers to appropriate review channels. Review Channel Platforms (map to specific review channels):
Generic Sources (do not map to specific review channels):
|
| text_opt_in | boolean Default: true Does the customer opt into receiving text messages |
object (CustomerCustomFields) Custom Fields in a object of name: value | |
| status | string Default: null Value: "unsubscribed" Customer status. If "unsubscribed", the customer will be fully unsubscribed from all categories. This takes precedence over unsubscribe_categories. Other status types will trigger an unauthorized error. |
| unsubscribe_categories | Array of strings (UnsubscribeCategory) Items Enum: "feedback_informational" "marketing" "transactional" "all" Categories to unsubscribe the customer from. Use "all" to unsubscribe from all categories. Only applies if status is not "unsubscribed". |
{- "account_id": "string",
- "location_id": "string",
- "location_name": "string",
- "first_name": "string",
- "last_name": "string",
- "phone_number": "+15555555555",
- "lead_source": "google",
- "text_opt_in": true,
- "custom_fields": {
- "campaign": "string",
- "parent_company": "string",
- "address_street": "string",
- "age": 0,
- "business_unit": "string",
- "crm": "string",
- "custom_Address": "string",
- "custom_CustomTextWithInstructions": "string",
- "custom_Date": "2019-08-24",
- "custom_DateAndTime": "2019-08-24T14:15:22Z",
- "customer_id": "string",
- "customer_review": true,
- "custom_LocationName": "string",
- "custom_ReservationType": "string",
- "employee": [
- "string"
], - "gender": "string",
- "income": 0,
- "invoice_amount": 0,
- "job_id": "string",
- "job_status": "string",
- "job_type": "string",
- "lead_source": "string",
- "lifetime_spend": 0,
- "nps_score": 0,
- "phone_number": "string",
- "race": "string",
- "repeat": true,
- "tags": [
- "string"
]
}, - "status": "unsubscribed",
- "unsubscribe_categories": [
- "feedback_informational"
]
}{- "account_id": "string",
- "location_id": "string",
- "status": "success",
- "message": "string"
}Retrieve a customer by their unique customer ID. The customer must belong to your account.
Expandable fields: customer_campaigns, reviews
| customer_id required | string The customer ID in the format of "cus-" followed by a UUID. |
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
| customer_id | string Customer ID starts with "cus-" then a UUID. Required if account_id is blank. |
| account_id | string Account ID starts with "acc-" then a UUID. Required if location_name is present. |
Array of objects | |
| first_name | string Customer's first name |
| last_name | string Customer's last name |
string <email> Customer's email address | |
| phone_number | string^\\+[1-9]\\d{1,14}$ A phone number in the E.144 format |
| lead_source | string or null (NormalizedLeadSource) Enum: "google" "facebook" "yelp" "bbb" "yellow pages" "angi" "homeadvisor" "nextdoor" "houzz" "trustpilot" "referral" "organic search" "direct" "email" "print" "broadcast" "event" "instagram" "linkedin" "twitter" "tiktok" "craigslist" "thumbtack" "porch" The canonical lead source value. Use these standardized values when creating or updating customers. These values are used for lead source-based review routing to match customers to appropriate review channels. Review Channel Platforms (map to specific review channels):
Generic Sources (do not map to specific review channels):
|
| normalized_lead_source | string or null (NormalizedLeadSource) Enum: "google" "facebook" "yelp" "bbb" "yellow pages" "angi" "homeadvisor" "nextdoor" "houzz" "trustpilot" "referral" "organic search" "direct" "email" "print" "broadcast" "event" "instagram" "linkedin" "twitter" "tiktok" "craigslist" "thumbtack" "porch" The canonical lead source value. Use these standardized values when creating or updating customers. These values are used for lead source-based review routing to match customers to appropriate review channels. Review Channel Platforms (map to specific review channels):
Generic Sources (do not map to specific review channels):
|
| lead_source_channel_type | string or null The review channel type name (e.g., "Google", "Yelp") if the lead source maps to a review channel |
| status | string Enum: "active" "unsubscribed" Customer status |
| text_opt_in | boolean Whether customer has opted in to receive text messages |
| created_at | string <date-time> When the customer was created |
| updated_at | string <date-time> When the customer was last updated |
Array of objects (CustomField) | |
| tags | Array of strings Names of tags applied to this customer. |
| last_activity_at | string <date-time> The most recent activity timestamp for the customer |
Array of integers or Array of CustomerCampaignItem (objects) Customer's campaign enrollments. Only present when expand options are used in the request.
Collapsed (expand options present but | |
Array of strings or Array of Review (objects) Confirmed review matches for this customer. Only present when expand options are used in the request.
Collapsed (expand options present but |
{- "customer_id": "cus-550e8400-e29b-41d4-a716-446655440000",
- "first_name": "Jane",
- "last_name": "Smith",
- "phone_number": "+15551234568",
- "lead_source": "google",
- "normalized_lead_source": "google",
- "lead_source_channel_type": "Google",
- "status": "active",
- "text_opt_in": true,
- "created_at": "2025-08-15T16:37:20Z",
- "updated_at": "2025-08-16T08:50:18Z",
- "last_activity_at": "2025-08-16T08:50:18Z",
- "account_id": "acc-test-402efb14-f779-4dfe-9a07-feb72602c8bb",
- "locations": [
- {
- "location_id": "loc-test-8c0a8daa-dbd8-4e7c-bd38-d810795512e3",
- "name": "Test Location"
}
], - "custom_fields": [
- {
- "name": "campaign",
- "value": "summer_promotion",
- "label": "Campaign",
- "type": "text"
}
]
}Retrieve a paginated list of campaigns associated with a customer, including their status.
| customer_id required | string The customer ID in the format of "cus-" followed by a UUID. |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| total_count | integer <int32> Total number of campaigns for the customer |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int8> Current page number |
Array of objects (CustomerCampaignItem) |
{- "total_count": 0,
- "total_pages": 0,
- "current_page": 0,
- "campaigns": [
- {
- "customer_campaign_id": 0,
- "campaign_template_id": 0,
- "campaign_name": "string",
- "campaign_type": "reviews",
- "status": "not_started",
- "active": true,
- "goal_met": true,
- "location": {
- "location_id": "string",
- "name": "string"
}, - "enrolled_at": "2019-08-24T14:15:22Z",
- "started_at": "2019-08-24T14:15:22Z",
- "completed_at": "2019-08-24T14:15:22Z",
- "exited_at": "2019-08-24T14:15:22Z",
- "exit_reason": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Retrieve a single customer campaign by its unique customer campaign ID. The customer campaign must belong to your account.
| customer_id required | string The customer ID in the format of "cus-" followed by a UUID. |
| customer_campaign_id required | number <int64> The customer campaign ID |
| customer_campaign_id | number <int64> Campaign template ID |
| campaign_template_id | number <int64> Campaign template ID |
| campaign_name | string Name of the campaign |
| campaign_type | string Enum: "reviews" "informational" "promotional" "transactional" Type of campaign |
| status | string Enum: "not_started" "started" "paused" "complete" "cancelled" Current status of the customer's campaign |
| active | boolean Whether the campaign is currently active |
| goal_met | boolean Whether the campaign goal was met |
object Location associated with this campaign | |
| enrolled_at | string or null <date-time> When the customer was enrolled in the campaign |
| started_at | string or null <date-time> When the campaign started for this customer |
| completed_at | string or null <date-time> When the campaign was completed |
| exited_at | string or null <date-time> When the customer exited the campaign |
| exit_reason | string or null Reason for exiting the campaign |
| created_at | string <date-time> When the campaign record was created |
| updated_at | string <date-time> When the campaign record was last updated |
{- "customer_campaign_id": 0,
- "campaign_template_id": 0,
- "campaign_name": "string",
- "campaign_type": "reviews",
- "status": "not_started",
- "active": true,
- "goal_met": true,
- "location": {
- "location_id": "string",
- "name": "string"
}, - "enrolled_at": "2019-08-24T14:15:22Z",
- "started_at": "2019-08-24T14:15:22Z",
- "completed_at": "2019-08-24T14:15:22Z",
- "exited_at": "2019-08-24T14:15:22Z",
- "exit_reason": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Retrieve a paginated list of touchpoints associated with a customer campaign, including their status. There is a hard limit of 100 touchpoints returned.
| customer_id required | string The customer ID in the format of "cus-" followed by a UUID. |
| customer_campaign_id required | number <int64> The customer campaign ID |
| status | string Enum: "scheduled" "queued" "sent" "delivered" "failed" "cancelled" "deferred" Current status of the touchpoint |
| sequence_order | number <int64> Sequence order of the touchpoint |
| days_after_previous | number <int64> Number of days after the previous touchpoint |
| scheduled_for | string <date-time> When the touchpoint is scheduled to be sent |
| sent_at | string or null <date-time> When the touchpoint was sent |
| channel | string Enum: "email" "sms" Channel for the touchpoint |
| delivered_at | string or null <date-time> When the touchpoint was delivered |
| has_error | boolean Whether the touchpoint has an error |
| error_message | string or null Error message for the touchpoint |
{- "status": "scheduled",
- "sequence_order": 0,
- "days_after_previous": 0,
- "scheduled_for": "2019-08-24T14:15:22Z",
- "sent_at": "2019-08-24T14:15:22Z",
- "channel": "email",
- "delivered_at": "2019-08-24T14:15:22Z",
- "has_error": true,
- "error_message": "string"
}Unsubscribe a Customer
| customer_id required | string A UUID prefixed with "cus-" |
Optional categories to unsubscribe from. If not provided, unsubscribes from all categories.
| unsubscribe_categories | Array of strings (UnsubscribeCategory) Items Enum: "feedback_informational" "marketing" "transactional" "all" Categories to unsubscribe from. Use "all" or omit this field to unsubscribe from all categories. |
| status | string Default: "success" Enum: "success" "error" |
| message | string Details about what categories were unsubscribed |
{- "unsubscribe_categories": [
- "feedback_informational"
]
}{- "status": "success",
- "message": "string"
}Import a customer to a Campaign
| account_id | string Account ID starts with "acc-" then a UUID. Required if location_name is present. |
| location_id required | string Location ID starts with "loc-" then a UUID. Required if account_id is blank. |
| location_name | string Location Name. Can be used instead of the Location ID if Account ID is present. |
| customer_first_name | string First Name of the customer |
| customer_last_name | string |
| customer_email | string <email> Required if customer_phone is blank. |
| customer_phone | string^\\+[1-9]\\d{1,14}$ Required if customer_email is blank. |
| lead_source | string or null (NormalizedLeadSource) Enum: "google" "facebook" "yelp" "bbb" "yellow pages" "angi" "homeadvisor" "nextdoor" "houzz" "trustpilot" "referral" "organic search" "direct" "email" "print" "broadcast" "event" "instagram" "linkedin" "twitter" "tiktok" "craigslist" "thumbtack" "porch" The canonical lead source value. Use these standardized values when creating or updating customers. These values are used for lead source-based review routing to match customers to appropriate review channels. Review Channel Platforms (map to specific review channels):
Generic Sources (do not map to specific review channels):
|
| text_opt_in | boolean Default: true Does the customer opt into receiving text messages |
| status | string Value: "unsubscribed" Customer status. If "unsubscribed", takes precedence over unsubscribe_categories and unsubscribes from all categories. |
| unsubscribe_categories | Array of strings (UnsubscribeCategory) Items Enum: "feedback_informational" "marketing" "transactional" "all" Categories to unsubscribe the customer from. Use "all" to unsubscribe from all categories. Only applies if status is not "unsubscribed". |
object (CustomerCustomFields) Custom Fields in a object of name: value. Unknown field names are automatically registered as new text custom fields for the account when the account's custom-field auto-registration setting is enabled. Auto-registered names must be snake_case: starting with a lowercase letter or underscore and containing only lowercase letters, numbers, and underscores. When auto-registration is disabled (the default) or the name is not snake_case, unknown field names are ignored. |
{- "account_id": "string",
- "location_id": "string",
- "location_name": "string",
- "customer_first_name": "string",
- "customer_last_name": "string",
- "customer_phone": "+15555555555",
- "lead_source": "google",
- "text_opt_in": true,
- "status": "unsubscribed",
- "unsubscribe_categories": [
- "feedback_informational"
], - "custom_fields": {
- "campaign": "string",
- "parent_company": "string",
- "address_street": "string",
- "age": 0,
- "business_unit": "string",
- "crm": "string",
- "custom_Address": "string",
- "custom_CustomTextWithInstructions": "string",
- "custom_Date": "2019-08-24",
- "custom_DateAndTime": "2019-08-24T14:15:22Z",
- "customer_id": "string",
- "customer_review": true,
- "custom_LocationName": "string",
- "custom_ReservationType": "string",
- "employee": [
- "string"
], - "gender": "string",
- "income": 0,
- "invoice_amount": 0,
- "job_id": "string",
- "job_status": "string",
- "job_type": "string",
- "lead_source": "string",
- "lifetime_spend": 0,
- "nps_score": 0,
- "phone_number": "string",
- "race": "string",
- "repeat": true,
- "tags": [
- "string"
]
}
}{- "status": "success",
- "sync_id": "string"
}Get the status of an import
| sync_id required | string |
| sync_id | string The sync ID that starts with "sync-" |
| status | string The current status of the import |
| customer_id | string Customer ID starts with "cus-" then a UUID. Required if account_id is blank. |
| location_id | string Location ID starts with "loc-" then a UUID. Required if account_id is blank. |
| campaign_ids | Array of numbers <int64> [ items <int64 > ] Array of campaign IDs created within 1 hour of the sync |
{- "sync_id": "sync-550e8400-e29b-41d4-a716-446655440000",
- "status": "completed",
- "customer_id": "cus-660e8400-e29b-41d4-a716-446655440001",
- "location_id": "loc-test-8c0a8daa-dbd8-4e7c-bd38-d810795512e3",
- "campaign_ids": [
- 123,
- 456
]
}Retrieve a paginated list of conversations for the authenticated account.
Conversations are scoped to the account attached to the Bearer token. The response intentionally omits account_id, provider identifiers, per-message source metadata, and multi-value campaign/channel arrays.
campaign is the latest campaign-sourced message's campaign template, or null when the conversation has no campaign-sourced message. campaign_template_id filters and responses use public cmp-* IDs.
Expandable fields: customer, location
When expanded, customer includes the full customer object with all fields. When not expanded, customer is a compact object with customer_id, first_name, and last_name.
When expanded, location includes the full location object with address, city, state, zipcode, country, phone number, timezone, and custom fields. When not expanded, location is a compact object with location_id and name.
string or Array of strings Filter conversations by status. Accepts one or more values; invalid values return a 400 response. | |
string or Array of strings The location ID in the format of "loc-" followed by the UUID. | |
| campaign_template_id | string^cmp-[A-Za-z0-9-]+$ Example: campaign_template_id=cmp-abc123 Filter conversations by the public campaign template ID in the format |
| channel_type | string Enum: "sms" "whatsapp" "email" Filter conversations that have at least one message on this API channel type. |
| created_at_gt | string <date-time> Return conversations created strictly after this ISO 8601 timestamp. Ignored when |
| created_at_gte | string <date-time> Return conversations created at or after this ISO 8601 timestamp. Ignored when |
| created_at_lt | string <date-time> Return conversations created strictly before this ISO 8601 timestamp. Ignored when |
| created_at_lte | string <date-time> Return conversations created at or before this ISO 8601 timestamp. Ignored when |
| created_at_eq | string <date-time> Return conversations created on the same date or instant as this ISO 8601 timestamp. When present, range filters for |
| last_message_at_gt | string <date-time> Return conversations whose latest message was sent strictly after this ISO 8601 timestamp. Ignored when |
| last_message_at_gte | string <date-time> Return conversations whose latest message was sent at or after this ISO 8601 timestamp. Ignored when |
| last_message_at_lt | string <date-time> Return conversations whose latest message was sent strictly before this ISO 8601 timestamp. Ignored when |
| last_message_at_lte | string <date-time> Return conversations whose latest message was sent at or before this ISO 8601 timestamp. Ignored when |
| last_message_at_eq | string <date-time> Return conversations whose latest message date or instant matches this ISO 8601 timestamp. When present, range filters for |
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| total_count required | integer <int32> Total number of conversations matching the filter criteria |
| total_pages required | integer <int32> Total number of pages available |
| current_page required | integer <int32> Current page number |
required | Array of objects (ConversationListItem) |
{- "total_count": 150,
- "total_pages": 2,
- "current_page": 1,
- "conversations": [
- {
- "conversation_id": 123,
- "status": "open",
- "customer": {
- "customer_id": "cus-abc123",
- "first_name": "John",
- "last_name": "Doe"
}, - "location": {
- "location_id": "loc-abc123",
- "name": "Main Street"
}, - "campaign": {
- "campaign_template_id": "cmp-abc123",
- "campaign_name": "Follow Up Campaign"
}, - "last_channel_type": "sms",
- "message_count": 5,
- "last_message_at": "2026-03-12T15:30:00Z",
- "last_message_preview": "Thanks for reaching out...",
- "created_at": "2026-03-10T10:00:00Z",
- "updated_at": "2026-03-12T15:30:00Z"
}
]
}Retrieve a paginated list of conversations for a single customer in the authenticated account.
The response keeps the same conversation contract as GET /conversations, except the top-level customer_id identifies the requested customer and each conversation item omits the embedded customer object.
Expandable fields: location
When expanded, location includes the full location object with address, city, state, zipcode, country, phone number, timezone, and custom fields. When not expanded, location is a compact object with location_id and name.
Because each item omits the embedded customer object, expand[]=customer is accepted but ignored on this endpoint.
| customer_id required | string The customer ID in the format of "cus-" followed by a UUID. |
string or Array of strings Filter conversations by status. Accepts one or more values; invalid values return a 400 response. | |
string or Array of strings The location ID in the format of "loc-" followed by the UUID. | |
| campaign_template_id | string^cmp-[A-Za-z0-9-]+$ Example: campaign_template_id=cmp-abc123 Filter conversations by the public campaign template ID in the format |
| channel_type | string Enum: "sms" "whatsapp" "email" Filter conversations that have at least one message on this API channel type. |
| created_at_gt | string <date-time> Return conversations created strictly after this ISO 8601 timestamp. Ignored when |
| created_at_gte | string <date-time> Return conversations created at or after this ISO 8601 timestamp. Ignored when |
| created_at_lt | string <date-time> Return conversations created strictly before this ISO 8601 timestamp. Ignored when |
| created_at_lte | string <date-time> Return conversations created at or before this ISO 8601 timestamp. Ignored when |
| created_at_eq | string <date-time> Return conversations created on the same date or instant as this ISO 8601 timestamp. When present, range filters for |
| last_message_at_gt | string <date-time> Return conversations whose latest message was sent strictly after this ISO 8601 timestamp. Ignored when |
| last_message_at_gte | string <date-time> Return conversations whose latest message was sent at or after this ISO 8601 timestamp. Ignored when |
| last_message_at_lt | string <date-time> Return conversations whose latest message was sent strictly before this ISO 8601 timestamp. Ignored when |
| last_message_at_lte | string <date-time> Return conversations whose latest message was sent at or before this ISO 8601 timestamp. Ignored when |
| last_message_at_eq | string <date-time> Return conversations whose latest message date or instant matches this ISO 8601 timestamp. When present, range filters for |
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| customer_id required | string Customer ID starts with "cus-" then a UUID. Required if account_id is blank. |
| total_count required | integer <int32> Total number of conversations for the customer matching the filter criteria |
| total_pages required | integer <int32> Total number of pages available |
| current_page required | integer <int32> Current page number |
required | Array of objects (CustomerConversationListItem) |
{- "customer_id": "cus-abc123",
- "total_count": 3,
- "total_pages": 1,
- "current_page": 1,
- "conversations": [
- {
- "conversation_id": 123,
- "status": "open",
- "location": {
- "location_id": "loc-abc123",
- "name": "Main Street"
}, - "campaign": {
- "campaign_template_id": "cmp-abc123",
- "campaign_name": "Follow Up Campaign"
}, - "last_channel_type": "sms",
- "message_count": 5,
- "last_message_at": "2026-03-12T15:30:00Z",
- "last_message_preview": "Thanks for reaching out...",
- "created_at": "2026-03-10T10:00:00Z",
- "updated_at": "2026-03-12T15:30:00Z"
}
]
}Retrieve a paginated list of messages for a customer's conversation.
Message body is plaintext. Email HTML bodies are converted to plaintext before serialization. read_at is the Liftify internal inbox read state, not an external provider or customer read receipt. Provider IDs such as Twilio SIDs and provider message IDs are intentionally omitted.
| customer_id required | string The customer ID in the format of "cus-" followed by a UUID. |
| conversation_id required | integer <int64> Numeric conversation identifier from the conversations list response. |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| customer_id required | string Customer ID starts with "cus-" then a UUID. Required if account_id is blank. |
| conversation_id required | integer <int64> Numeric conversation identifier from the conversations list response |
| total_count required | integer <int32> Total number of messages in the conversation |
| total_pages required | integer <int32> Total number of pages available |
| current_page required | integer <int32> Current page number |
required | Array of objects (ConversationMessage) |
{- "customer_id": "cus-abc123",
- "conversation_id": 123,
- "total_count": 12,
- "total_pages": 1,
- "current_page": 1,
- "messages": [
- {
- "message_id": 789,
- "direction": "outbound",
- "body": "Hi John, how was your experience?",
- "channel_type": "sms",
- "status": "delivered",
- "sent_at": "2026-03-10T10:00:00Z",
- "delivered_at": "2026-03-10T10:00:05Z",
- "read_at": null,
- "created_at": "2026-03-10T10:00:00Z"
}
]
}Retrieve a paginated list of surveys for the authenticated account. Use the optional status filter to retrieve surveys in a specific state.
Expandable fields: versions, versions.questions
When expanded, versions includes the full survey version objects with version number, provider, and timestamps. When not expanded, versions returns an array of version public_id strings.
When versions.questions is expanded, each version includes the full question objects with question key, type, text, metadata, and scoring information. When not expanded, questions returns an array of question public_id strings within each version.
| status | string Enum: "draft" "active" "archived" Filter surveys by status. |
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| created_at_gt | string <date-time> Return surveys with a created_at strictly greater than this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_gte | string <date-time> Return surveys with a created_at greater than or equal to this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_lt | string <date-time> Return surveys with a created_at strictly less than this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_lte | string <date-time> Return surveys with a created_at less than or equal to this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
string or string Filter surveys created on the specified date, ignoring the time portion. Accepts either an ISO-8601 date (YYYY-MM-DD) or a full ISO-8601 date-time; only the date portion is used for filtering. Precedence: When created_at_eq is provided, all other date-time filters (created_at_gt, created_at_gte, created_at_lt, created_at_lte) are ignored. |
| total_count | integer <int32> Total number of surveys matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int8> Current page number |
Array of objects (SurveyItem) |
{- "total_count": 5,
- "total_pages": 1,
- "current_page": 1,
- "surveys": [
- {
- "public_id": "550e8400-e29b-41d4-a716-446655440000",
- "name": "Customer Satisfaction Survey",
- "status": "active",
- "provider": "liftify",
- "created_at": "2025-08-15T16:37:20Z",
- "updated_at": "2025-08-16T08:50:18Z",
- "versions": [
- "660e8400-e29b-41d4-a716-446655440001"
]
}
]
}Retrieve a single survey by its public UUID. The survey must belong to your account.
Expandable fields: versions, versions.questions
When expanded, versions includes the full survey version objects. When not expanded, versions returns an array of version public_id strings.
| id required | string <uuid> The survey public ID (UUID). |
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
| public_id | string <uuid> Unique public identifier for the survey (UUID) |
| name | string Survey name |
| status | string Enum: "draft" "active" "archived" Current status of the survey |
| provider | string Enum: "liftify" "birdeye" Survey provider |
Array of strings or Array of SurveyVersionItem (objects) Survey versions. Always present in the response.
Collapsed (default or | |
| created_at | string <date-time> When the survey was created |
| updated_at | string <date-time> When the survey was last updated |
{- "public_id": "550e8400-e29b-41d4-a716-446655440000",
- "name": "Customer Satisfaction Survey",
- "status": "active",
- "provider": "liftify",
- "created_at": "2025-08-15T16:37:20Z",
- "updated_at": "2025-08-16T08:50:18Z",
- "versions": [
- "660e8400-e29b-41d4-a716-446655440001"
]
}Retrieve a paginated list of responses for a specific survey. The survey must belong to your account.
Expandable fields: answers, customer, location, survey, survey_version, survey_version.questions
Includable fields: customer_snapshot
When included (include[]=customer_snapshot), each response carries the raw contact snapshot captured when it was ingested or submitted, exactly as stored — contact details plus the original inbound contact payload (original_contact) with custom fields keyed by the labels they arrived with. Values reflect survey time, independent of later edits to the customer record. Include is purely additive: no default fields are removed or reshaped, and it composes with expand. When not requested, the field is omitted.
When expanded, answers includes the full answer objects with question key, question text, answer value, question type, and conditional flags. When not expanded (but expand options are present), answers returns an array of answer public_id strings. When no expand options are present, the answers field is omitted.
When expanded, customer includes the full customer object. When not expanded, customer_id is returned as a string (nullable).
When expanded, location includes the full location object. When not expanded, location_id is returned as a string.
When expanded, survey includes the full survey object. When not expanded, survey_id is returned as a string.
When expanded, survey_version includes the full survey version object. When not expanded, survey_version_id is returned as a string. Use survey_version.questions to also expand questions within the version.
| survey_id required | string <uuid> The survey public ID (UUID). |
| completion_status | string Enum: "pending" "partial" "complete" Filter responses by completion status. |
string or Array of strings The location ID in the format of "loc-" followed by the UUID. | |
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
| include | Array of strings Opt into raw fields that are omitted from the response by default (e.g. Include is purely additive: the default payload is unchanged, and each requested field is added
to every response object. It is distinct from Error handling: Unknown include values return a |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| created_at_gt | string <date-time> Return responses with a created_at strictly greater than this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_gte | string <date-time> Return responses with a created_at greater than or equal to this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_lt | string <date-time> Return responses with a created_at strictly less than this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_lte | string <date-time> Return responses with a created_at less than or equal to this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
string or string Filter responses created on the specified date, ignoring the time portion. Precedence: When created_at_eq is provided, all other date-time filters are ignored. | |
| response_date_gt | string <date-time> Return responses completed strictly after this value. This is an ISO 8601 date-time string.
Responses the customer has not completed (null |
| response_date_gte | string <date-time> Return responses completed at or after this value. This is an ISO 8601 date-time string.
Responses the customer has not completed (null |
| response_date_lt | string <date-time> Return responses completed strictly before this value. This is an ISO 8601 date-time string.
Responses the customer has not completed (null |
| response_date_lte | string <date-time> Return responses completed at or before this value. This is an ISO 8601 date-time string.
Responses the customer has not completed (null |
string or string Filter responses completed on the specified date, ignoring the time portion.
Responses the customer has not completed (null Precedence: When response_date_eq is provided, all other response_date filters are ignored. |
| total_count | integer <int32> Total number of responses matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int8> Current page number |
Array of objects (SurveyResponseItem) |
{- "total_count": 25,
- "total_pages": 1,
- "current_page": 1,
- "responses": [
- {
- "public_id": "770e8400-e29b-41d4-a716-446655440002",
- "completion_status": "complete",
- "overall_score": 4.5,
- "nps_score": 9,
- "provider": "liftify",
- "anonymous": false,
- "customer_display_name": "John D.",
- "request_date": "2025-08-14T09:00:00Z",
- "response_date": "2025-08-16T08:50:18Z",
- "created_at": "2025-08-15T16:37:20Z",
- "updated_at": "2025-08-16T08:50:18Z"
}
]
}Import multiple surveys with responses in a single request using NDJSON (Newline-Delimited JSON) format. Each line of the request body must be a valid JSON object containing a survey definition and optional responses.
NDJSON Format: Each line is a separate JSON object. Lines are delimited by newline characters (\n).
Processing: Each line is processed asynchronously by a background worker. Use the returned sync_id
values to track the status of each import via the /surveys/import/{sync_id}/status endpoint.
De-duplication: The system automatically detects and skips duplicate payloads within a 10-second window.
Fingerprint is generated from: survey external_id, response external_response_id, and contact email/phone.
Duplicate responses return skipped status without error.
Survey Versioning: When a survey schema changes (questions added/removed/modified), a new version is automatically created. Existing responses remain linked to their original version.
NDJSON format where each line contains a complete survey import payload.
Each line must have a survey key with the survey definition.
required | object (SurveyDefinition) Survey definition containing structure and questions |
Array of objects (SurveyResponsePayload) Optional array of survey responses to import with the survey |
"{\"survey\":{\"external_id\":\"survey_001\",\"name\":\"Customer Satisfaction Survey\",\"provider\":\"birdeye\",\"pages\":[{\"page_key\":\"page_1\",\"page_number\":1,\"questions\":[{\"question_key\":\"q1\",\"text\":\"How satisfied are you?\",\"type\":\"nps\",\"metadata\":{\"promoter_threshold\":9,\"detractor_threshold\":6}}]}]},\"responses\":[{\"contact\":{\"first_name\":\"John\",\"last_name\":\"Doe\",\"email\":\"[email protected]\"},\"location\":{\"external_id\":\"loc_123\"},\"external_response_id\":\"resp_001\",\"response_date\":\"2025-01-15T10:30:00Z\",\"answers\":[{\"question_key\":\"q1\",\"answer_value\":9}]}]}\n"{- "sync_ids": [
- "sync-550e8400-e29b-41d4-a716-446655440000",
- "sync-660e8400-e29b-41d4-a716-446655440001"
], - "message": "2 surveys queued for import"
}Retrieve the status of a survey import operation using the sync_id returned from the import endpoint.
Status Flow:
pending: Import is queued and being processedsuccess: Import completed successfullypartial: Import completed with some records skipped (e.g., duplicates)error: Import failed with errorsNote: Once a SyncHistory record exists, the pending Redis key is automatically cleaned up.
| sync_id required | string Example: sync-550e8400-e29b-41d4-a716-446655440000 The sync ID returned from the import endpoint (prefixed with "sync-") |
| sync_id required | string The sync ID prefixed with "sync-" |
| status required | string Enum: "success" "partial" The status of the import operation |
| source required | string Value: "survey_import" The source of the sync operation |
| action | string The action performed |
| location_id | string Location ID starts with "loc-" then a UUID. Required if account_id is blank. |
| customer_id | string Customer ID starts with "cus-" then a UUID. Required if account_id is blank. |
object Additional result data from the import | |
| created_at required | string <date-time> When the sync operation was created |
| updated_at required | string <date-time> When the sync operation was last updated |
{- "sync_id": "sync-550e8400-e29b-41d4-a716-446655440000",
- "status": "success",
- "source": "survey_import",
- "action": "survey_ingestion",
- "location_id": "loc-test-8c0a8daa-dbd8-4e7c-bd38-d810795512e3",
- "customer_id": "cus-660e8400-e29b-41d4-a716-446655440001",
- "created_at": "2025-01-15T10:30:00Z",
- "updated_at": "2025-01-15T10:30:05Z",
- "result": {
- "surveys_created": 1,
- "responses_processed": 5
}
}Retrieve a paginated list of survey responses for the authenticated account. At least one filter is required: survey_id or location_id.
Expandable fields: answers, customer, location, survey, survey_version, survey_version.questions
Includable fields: customer_snapshot
See /surveys/{survey_id}/responses for detailed expand and include behavior descriptions.
| survey_id | string <uuid> Filter responses by survey public ID (UUID). Required if |
string or Array of strings The location ID in the format of "loc-" followed by the UUID. | |
| completion_status | string Enum: "pending" "partial" "complete" Filter responses by completion status. |
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
| include | Array of strings Opt into raw fields that are omitted from the response by default (e.g. Include is purely additive: the default payload is unchanged, and each requested field is added
to every response object. It is distinct from Error handling: Unknown include values return a |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| created_at_gt | string <date-time> Return responses with a created_at strictly greater than this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_gte | string <date-time> Return responses with a created_at greater than or equal to this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_lt | string <date-time> Return responses with a created_at strictly less than this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_lte | string <date-time> Return responses with a created_at less than or equal to this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
string or string Filter responses created on the specified date, ignoring the time portion. Precedence: When created_at_eq is provided, all other date-time filters are ignored. | |
| response_date_gt | string <date-time> Return responses completed strictly after this value. This is an ISO 8601 date-time string.
Responses the customer has not completed (null |
| response_date_gte | string <date-time> Return responses completed at or after this value. This is an ISO 8601 date-time string.
Responses the customer has not completed (null |
| response_date_lt | string <date-time> Return responses completed strictly before this value. This is an ISO 8601 date-time string.
Responses the customer has not completed (null |
| response_date_lte | string <date-time> Return responses completed at or before this value. This is an ISO 8601 date-time string.
Responses the customer has not completed (null |
string or string Filter responses completed on the specified date, ignoring the time portion.
Responses the customer has not completed (null Precedence: When response_date_eq is provided, all other response_date filters are ignored. |
| total_count | integer <int32> Total number of responses matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int8> Current page number |
Array of objects (SurveyResponseItem) |
{- "total_count": 25,
- "total_pages": 1,
- "current_page": 1,
- "responses": [
- {
- "public_id": "770e8400-e29b-41d4-a716-446655440002",
- "completion_status": "complete",
- "overall_score": 4.5,
- "nps_score": 9,
- "provider": "liftify",
- "anonymous": false,
- "customer_display_name": "John D.",
- "request_date": "2025-08-14T09:00:00Z",
- "response_date": "2025-08-16T08:50:18Z",
- "created_at": "2025-08-15T16:37:20Z",
- "updated_at": "2025-08-16T08:50:18Z"
}
]
}Retrieve a single survey response by its public UUID. The response must belong to your account.
Expandable fields: answers, customer, location, survey, survey_version, survey_version.questions
Includable fields: customer_snapshot
See /surveys/{survey_id}/responses for detailed expand and include behavior descriptions.
| id required | string <uuid> The survey response public ID (UUID). |
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
| include | Array of strings Opt into raw fields that are omitted from the response by default (e.g. Include is purely additive: the default payload is unchanged, and each requested field is added
to every response object. It is distinct from Error handling: Unknown include values return a |
| public_id | string <uuid> Unique public identifier for the response (UUID) |
| completion_status | string Enum: "pending" "partial" "complete" Response completion status |
| overall_score | number or null <float> Overall satisfaction score if applicable |
| nps_score | integer or null [ 0 .. 10 ] NPS score (0-10) if the survey contains an NPS question |
| provider | string Enum: "liftify" "birdeye" Survey provider |
| anonymous | boolean Whether the response is anonymous |
| customer_display_name | string or null Display name for the customer (e.g., "John D.") |
(string or null) or (CustomerListItem (object or null)) The matched customer for this response. Null if anonymous/unmatched.
Collapsed (default): The customer_id string (e.g., | |
string or LocationItem (object) The location for this response.
Collapsed (default): The location_id string.
Expanded ( | |
string or SurveyItem (object) The survey for this response.
Collapsed (default): The survey public_id string.
Expanded ( | |
string or SurveyVersionItem (object) The survey version for this response.
Collapsed (default): The survey version public_id string.
Expanded ( | |
Array of strings or Array of SurveyAnswerItem (objects) Answers to this survey response. Only present when expand options are used in the request.
Collapsed (expand options present but | |
object or null The raw contact snapshot captured when the response was ingested or submitted, exactly
as stored — contact details plus the original inbound contact payload ( | |
| request_date | string or null <date-time> When the survey was sent to the customer. Null when the send time is unknown. |
| response_date | string or null <date-time> When the customer completed the survey. Null for responses the customer has not finished. |
| created_at | string <date-time> When the response was created |
| updated_at | string <date-time> When the response was last updated |
{- "public_id": "770e8400-e29b-41d4-a716-446655440002",
- "completion_status": "complete",
- "overall_score": 4.5,
- "nps_score": 9,
- "provider": "liftify",
- "anonymous": false,
- "customer_display_name": "John D.",
- "request_date": "2025-08-14T09:00:00Z",
- "response_date": "2025-08-16T08:50:18Z",
- "created_at": "2025-08-15T16:37:20Z",
- "updated_at": "2025-08-16T08:50:18Z"
}Retrieve all reviews for your entire account. Results are sorted by most recent review date.
Expandable fields: location, customer
When expanded, location includes the full location object with address, city, state, zipcode, country, phone number, timezone, and custom fields. When not expanded, location is a compact object with only location_id and name.
When expanded, customer includes the full customer object (nullable). When not expanded, customer_id is returned as a string (nullable) — the customer_id from the first confirmed match, or null if no confirmed match exists.
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
string or Array of strings The location ID in the format of "loc-" followed by the UUID. | |
| has_customer | boolean Filter reviews that have or don't have a confirmed customer match. When |
string or Array of strings Filter reviews matched to specific customer(s). Accepts a single customer ID or an array of customer IDs. Format is "cus-" followed by a UUID. | |
string or Array of strings Filter by review provider. Accepts a single provider or an array of providers. | |
| has_reply | boolean Filter results to include only reviews with a reply |
integer or Array of integers Filter results to include only reviews matching any of the specified star ratings. Can be a single value or an array of values. | |
| review_date_time_gt | string <date-time> Examples:
Return reviews with a review_date_time strictly greater than this value. This is an ISO 8601 date-time string. Ignored when review_date_time_eq is present. |
| review_date_time_gte | string <date-time> Examples:
Return reviews with a review_date_time greater than or equal to this value. This is an ISO 8601 date-time string. Ignored when review_date_time_eq is present. |
| review_date_time_lt | string <date-time> Examples:
Return reviews with a review_date_time strictly less than this value. This is an ISO 8601 date-time string. Ignored when review_date_time_eq is present. |
| review_date_time_lte | string <date-time> Examples:
Return reviews with a review_date_time less than or equal to this value. This is an ISO 8601 date-time string. Ignored when review_date_time_eq is present. |
string or string Examples:
Filter reviews that occurred on the specified date, ignoring the time portion. Accepts either an ISO‑8601 date (YYYY‑MM‑DD) or a full ISO‑8601 date-time; only the date portion is used for filtering. Precedence: When review_date_time_eq is provided, all other date-time filters (review_date_time_gt, review_date_time_gte, review_date_time_lt, review_date_time_lte) are ignored. | |
| is_archived | boolean Filters the result set by archive state.
|
| include_archived | boolean When |
| potential_violation | boolean Filters by AI content-policy violation flag. |
| violation_status | Array of strings Items Enum: "none" "flagged" "reported" "removed" "dismissed" Filters by violation lifecycle status. Accepts one value or an array. Only honored when the account has violation detection enabled — ignored otherwise. |
| violation_category | Array of strings Items Enum: "low_quality_information" "fake_or_deceptive" "profanity" "bullying_or_harassment" "discrimination_or_hate_speech" "personal_information" Filters by AI-assigned violation category. Accepts one value or an array. Only honored when the account has violation detection enabled — ignored otherwise. |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
Array of objects (Review) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Array
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{- "reviews": [
- {
- "account_id": "string",
- "review_id": "string",
- "location": {
- "location_id": "string",
- "name": "string"
}, - "customer_id": "string",
- "customer": {
- "customer_id": "string",
- "account_id": "string",
- "locations": [
- {
- "location_id": "string",
- "name": "string"
}
], - "first_name": "string",
- "last_name": "string",
- "phone_number": "+15555555555",
- "lead_source": "google",
- "normalized_lead_source": "google",
- "lead_source_channel_type": "Google",
- "status": "active",
- "text_opt_in": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "custom_fields": [
- {
- "label": "string",
- "name": "string",
- "value": null,
- "type": "text"
}
], - "tags": [
- "VIP",
- "Dissatisfied"
], - "last_activity_at": "2019-08-24T14:15:22Z",
- "customer_campaigns": [
- 0
], - "reviews": [
- "string"
]
}, - "reviewer_display_name": "string",
- "reviewer_profile_photo_url": "string",
- "star_rating": 0,
- "comment": "string",
- "reply_comment": "string",
- "reply_date_time": "2019-08-24T14:15:22Z",
- "review_date_time": "2019-08-24T14:15:22Z",
- "has_reply": true,
- "provider": "google",
- "archived_at": "2019-08-24T14:15:22Z",
- "first_missing_at": "2019-08-24T14:15:22Z",
- "potential_violation": true,
- "violation_category": "low_quality_information",
- "violation_reason": "string",
- "violation_status": "none",
- "violation_reported_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}Retrieve all unsubscribed customers for your entire account. Returns both fully unsubscribed customers and partially unsubscribed customers (with category-specific unsubscribe preferences). Results are sorted by most recent unsubscribe date.
| account_id required | string The account ID in the format of "acc-" followed by the UUID. |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| start_date | string <date-time> Filter results to include only unsubscribes from this date onwards |
| end_date | string <date-time> Filter results to include only unsubscribes up to this date |
| total_count | integer <int32> |
| total_pages | integer <int32> |
| current_page | integer <int8> |
Array of objects (LocationUnSubscribeItem) |
{- "total_count": 2,
- "total_pages": 1,
- "current_page": 1,
- "customers": [
- {
- "first_name": "Jane",
- "last_name": "Smith",
- "phone": "+15551234568",
- "created_at": "2025-08-15T16:37:20Z",
- "unsubscribe_type": "partial",
- "unsubscribed_date": "2025-08-16T08:50:18Z",
- "unsubscribe_categories": [
- "marketing"
], - "account": {
- "name": "Test Company",
- "id": "acc-test-402efb14-f779-4dfe-9a07-feb72602c8bb"
}, - "location": {
- "name": "Test Location",
- "id": "loc-test-8c0a8daa-dbd8-4e7c-bd38-d810795512e3"
}, - "custom_fields": { }
}, - {
- "first_name": "John",
- "last_name": "Doe",
- "phone": "+15551234567",
- "created_at": "2025-08-15T16:37:20Z",
- "unsubscribe_type": "full",
- "unsubscribed_date": "2025-08-15T16:37:20Z",
- "unsubscribe_categories": [
- "feedback_informational",
- "marketing",
- "transactional"
], - "account": {
- "name": "Test Company",
- "id": "acc-test-402efb14-f779-4dfe-9a07-feb72602c8bb"
}, - "location": {
- "name": "Test Location",
- "id": "loc-test-8c0a8daa-dbd8-4e7c-bd38-d810795512e3"
}, - "custom_fields": { }
}
]
}Retrieve all unsubscribed customers for a specific location. Returns both fully unsubscribed customers and partially unsubscribed customers (with category-specific unsubscribe preferences). Results are sorted by most recent unsubscribe date.
| location_id required | string The location ID in the format of "loc-" followed by the UUID. |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| start_date | string <date-time> Filter results to include only unsubscribes from this date onwards |
| end_date | string <date-time> Filter results to include only unsubscribes up to this date |
| total_count | integer <int32> |
| total_pages | integer <int32> |
| current_page | integer <int8> |
Array of objects (LocationUnSubscribeItem) |
{- "total_count": 2,
- "total_pages": 1,
- "current_page": 1,
- "customers": [
- {
- "first_name": "Jane",
- "last_name": "Smith",
- "phone": "+15551234568",
- "created_at": "2025-08-15T16:37:20Z",
- "unsubscribe_type": "partial",
- "unsubscribed_date": "2025-08-16T08:50:18Z",
- "unsubscribe_categories": [
- "marketing"
], - "account": {
- "name": "Test Company",
- "id": "acc-test-402efb14-f779-4dfe-9a07-feb72602c8bb"
}, - "location": {
- "name": "Test Location",
- "id": "loc-test-8c0a8daa-dbd8-4e7c-bd38-d810795512e3"
}, - "custom_fields": { }
}, - {
- "first_name": "John",
- "last_name": "Doe",
- "phone": "+15551234567",
- "created_at": "2025-08-15T16:37:20Z",
- "unsubscribe_type": "full",
- "unsubscribed_date": "2025-08-15T16:37:20Z",
- "unsubscribe_categories": [
- "feedback_informational",
- "marketing",
- "transactional"
], - "account": {
- "name": "Test Company",
- "id": "acc-test-402efb14-f779-4dfe-9a07-feb72602c8bb"
}, - "location": {
- "name": "Test Location",
- "id": "loc-test-8c0a8daa-dbd8-4e7c-bd38-d810795512e3"
}, - "custom_fields": { }
}
]
}Retrieve a paginated list of tickets for the authenticated account with optional filtering.
Expandable fields: customer, location
When expanded, customer includes the full customer object with all fields. When not expanded, customer is a compact object with full_name, email, and phone_number.
When expanded, location includes the full location object with address, city, state, zipcode, country, phone number, timezone, and custom fields. When not expanded, location is a compact object with only name.
string or Array of strings The location ID in the format of "loc-" followed by the UUID. | |
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
| status | string Filter tickets by status name. |
| status_type | string Filter tickets by status type. |
| assigned_to | string Filter tickets by assigned user ID. Use "unassigned" to find tickets without an assignee. |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| created_at_gt | string <date-time> Return tickets with a created_at strictly greater than this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_gte | string <date-time> Return tickets with a created_at greater than or equal to this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_lt | string <date-time> Return tickets with a created_at strictly less than this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
| created_at_lte | string <date-time> Return tickets with a created_at less than or equal to this value. This is an ISO 8601 date-time string. Ignored when created_at_eq is present. |
string or string Filter tickets created on the specified date, ignoring the time portion. Precedence: When created_at_eq is provided, all other date-time filters are ignored. |
| total_count | integer <int32> Total number of tickets matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int8> Current page number |
Array of objects (TicketItem) |
{- "total_count": 0,
- "total_pages": 0,
- "current_page": 0,
- "tickets": [
- {
- "id": 0,
- "ticket_id": "string",
- "name": "string",
- "description": "string",
- "status": {
- "name": "string",
- "color": "string",
- "status_type": "string"
}, - "location": {
- "name": "string"
}, - "source_type": "review",
- "source_id": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "closed_at": "2019-08-24T14:15:22Z"
}
]
}Retrieve a single ticket by its ticket ID. The ticket must belong to your account.
Expandable fields: customer, location
| ticket_id required | string The ticket ID. |
| expand | Array of strings Expand related objects inline instead of returning IDs. Pass one or more association names
to include the full object in the response. Use dot-notation for nested expansion
(e.g., Limits: Maximum 10 expand paths per request, maximum 3 levels of nesting depth. Without expand: Related objects are either omitted or rendered as compact inline objects (e.g., With expand: Related objects are rendered as full API objects with all their fields. Error handling: Invalid expand paths return a |
| id | integer <int64> Internal ticket ID |
| ticket_id | string Public ticket ID |
| name | string Ticket name/title |
| description | string or null Ticket description |
object or null Current ticket status (always rendered as inline object) | |
object or LocationItem (object) The location associated with this ticket.
Default: Compact object with | |
(object or null) or (CustomerListItem (object or null)) The customer associated with this ticket.
Default: Compact object with | |
object or null Assigned user (always rendered as inline object) | |
| source_type | string Enum: "review" "survey" "manual" Source of the ticket |
| source_id | string or null ID of the source object (review or survey response) |
| created_at | string <date-time> When the ticket was created |
| updated_at | string <date-time> When the ticket was last updated |
| closed_at | string or null <date-time> When the ticket entered a done (closed) status |
{- "id": 0,
- "ticket_id": "string",
- "name": "string",
- "description": "string",
- "status": {
- "name": "string",
- "color": "string",
- "status_type": "string"
}, - "location": {
- "name": "string"
}, - "source_type": "review",
- "source_id": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "closed_at": "2019-08-24T14:15:22Z"
}Retrieve a paginated list of all locations for the authenticated account. Since API keys are account-scoped, all account locations are accessible. Use the optional location_ids filter to retrieve a specific subset.
string or Array of strings Filter results to include only the specified location IDs. Accepts a single location ID or an array of location IDs. | |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| total_count | integer <int32> Total number of locations matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int8> Current page number |
Array of objects (LocationItem) |
{- "total_count": 3,
- "total_pages": 1,
- "current_page": 1,
- "locations": [
- {
- "location_id": "loc-test-8c0a8daa-dbd8-4e7c-bd38-d810795512e3",
- "name": "Downtown Office",
- "address": "123 Main St",
- "city": "Springfield",
- "state": "IL",
- "zipcode": "62701",
- "country": "US",
- "phone_number": "+15551234567",
- "timezone": "America/Chicago",
- "custom_fields": [
- {
- "name": "brand",
- "label": "Brand",
- "value": "Acme Corp",
- "type": "text"
}
]
}
]
}Retrieve a paginated list of all active, non-archived campaign templates for the authenticated account. A campaign is considered active when it is assigned to at least one location with an active, non-archived configuration.
string or Array of strings Filter results to include only campaigns assigned to the specified locations. Accepts a single location ID or an array of location IDs. | |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| total_count | integer <int32> Total number of active campaigns matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int8> Current page number |
Array of objects (CampaignTemplateItem) |
{- "total_count": 2,
- "total_pages": 1,
- "current_page": 1,
- "campaigns": [
- {
- "campaign_template_id": "550e8400-e29b-41d4-a716-446655440000",
- "name": "Post-Service Review Request",
- "description": "Automated review request sent after service completion",
- "campaign_type": "reviews",
- "campaign_category": "feedback_informational",
- "send_immediately": false,
- "block_if_in_other_campaign": true,
- "created_at": "2025-08-15T16:37:20Z",
- "updated_at": "2025-08-16T08:50:18Z"
}
]
}Retrieve a paginated list of external systems configured for the authenticated account.
An external system represents a third-party integration (e.g. ServiceTitan, HubSpot) that maps Liftify records — customers, tickets, locations, etc. — to identifiers in the external system.
| status | string Enum: "active" "inactive" Filter by active state. Accepts |
| search | string Substring search against |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| total_count | integer <int32> Total number of external systems matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int8> Current page number |
Array of objects (ExternalSystemItem) |
{- "total_count": 1,
- "total_pages": 1,
- "current_page": 1,
- "external_systems": [
- {
- "id": 1,
- "slug": "servicetitan",
- "display_name": "ServiceTitan",
- "description": "ServiceTitan integration for job and customer sync",
- "active": true,
- "created_at": "2026-04-15T16:37:20Z",
- "updated_at": "2026-04-15T16:37:20Z"
}
]
}Retrieve a single external system by its slug. The system must belong to your account; matching slugs in other accounts return 404.
| slug required | string The external system's slug (e.g. |
| id | integer Internal numeric identifier |
| slug | string Public, immutable identifier used as the external system's stable handle (e.g. |
| display_name | string Human-readable name of the integration |
| description | string or null Optional free-text description of the integration |
| active | boolean Whether the system is currently enabled for the account |
| created_at | string <date-time> When the external system entry was created (ISO 8601) |
| updated_at | string <date-time> When the external system entry was last updated (ISO 8601) |
{- "id": 0,
- "slug": "string",
- "display_name": "string",
- "description": "string",
- "active": true,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Retrieve a paginated list of external alias mappings for the authenticated account.
Filter combinations express both inbound and outbound resolution:
external_system_slug, external_entity_type, and external_id.aliasable_type and aliasable_id.external_entity_type is normalized to lowercase server-side (Job and job both match a stored value of job). aliasable_type is the literal Ruby class name (Ticket, Customer, Location, Review, Conversation, User) and is not normalized — ?aliasable_type=ticket returns nothing if the stored value is Ticket.
| external_system_slug | string Filter by the slug of the related external system. |
| external_entity_type | string Filter by the kind of external record (e.g. |
| external_id | string Filter by the identifier in the external system. Coerced to string before comparison. |
| external_ids | string Example: external_ids=54607865,54688362 Bulk filter — return only aliases whose external_id is in this list. Accepts a comma-separated string or repeated array params. Maximum 500 ids per request (400 above the cap). Takes precedence over external_id when both are supplied; a supplied-but-empty list matches nothing. |
| aliasable_type | string Enum: "Customer" "Location" "Review" "Ticket" "Conversation" "User" Filter by the Liftify record's polymorphic class name. Case-sensitive — must match the stored value exactly (e.g. |
| aliasable_id | integer Filter by the Liftify record's primary key. |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| total_count | integer <int32> Total number of external aliases matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int8> Current page number |
Array of objects (ExternalAliasItem) |
{- "total_count": 1,
- "total_pages": 1,
- "current_page": 1,
- "external_aliases": [
- {
- "id": 42,
- "external_system_slug": "servicetitan",
- "external_entity_type": "job",
- "external_id": "12345",
- "created_at": "2026-04-15T16:37:20Z"
}
]
}Manage service-address Sites (list, retrieve, create, update) — writes flow through a dedup pipeline that honors external-system IDs and normalized addresses
Retrieve a paginated list of Sites for the authenticated account.
Filter combinations:
customer_id (the public cus- identifier) to restrict results to sites currently linked to that customer.external_system (slug) together with external_id to look up the Site that maps to that external record. Optionally narrow further with external_entity_type (defaults to site).address_substring to match against address_line1, address_line2, or the deterministic normalized_address. Case-insensitive (ILIKE).Archived sites are excluded by default.
| customer_id | string Filter to sites currently linked to the specified Customer (public |
| external_system | string Slug of the external system (e.g. |
| external_id | string External identifier to look up. Combine with |
| external_entity_type | string Default: "site" External entity type (defaults to |
| address_substring | string Case-insensitive substring matched against |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| total_count | integer <int32> Total number of sites matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int32> Current page number |
Array of objects (SiteListItem) |
{- "total_count": 1,
- "total_pages": 1,
- "current_page": 1,
- "sites": [
- {
- "id": 42,
- "name": "Smith Residence",
- "address_line1": "123 Main St",
- "city": "Seattle",
- "region": "WA",
- "postal_code": "98101",
- "country": "US"
}
]
}Create a Site, routed through a dedup pipeline:
external_id.external_system + external_id.external_id are supplied and already map to a Site in this account, that Site is returned (200 OK, no new alias row created).200 OK). This step only runs when address_line1, city, region, and postal_code are all present.external_id is supplied an ExternalAlias row is registered in the same transaction (201 Created).Sites are account-isolated: identical addresses in two different accounts produce two distinct Sites. Address fields are optional — a Site may be created with a partial address or none at all — but the request must carry some identity: a site object whose attributes are all blank, with no external_id, is rejected with 422.
object | |
object or null Optional external-system reference. Used as the primary dedup key on create and as an alias-upsert on update. |
object (Site) Full representation of a Site used in show/create/update responses. | |||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||
object (Site) Full representation of a Site used in show/create/update responses. | |||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||
{- "site": {
- "name": "string",
- "address_line1": "string",
- "address_line2": "string",
- "city": "string",
- "region": "string",
- "postal_code": "string",
- "country": "US",
- "access_notes": "string"
}, - "external_id": {
- "external_system": "string",
- "external_entity_type": "site",
- "external_id": "string"
}
}{- "site": {
- "id": 0,
- "name": "string",
- "address_line1": "string",
- "address_line2": "string",
- "city": "string",
- "region": "string",
- "postal_code": "string",
- "country": "string",
- "access_notes": "string",
- "normalized_address": "string",
- "account_id": "string",
- "archived_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "external_aliases": [
- {
- "external_system_slug": "string",
- "external_entity_type": "string",
- "external_id": "string"
}
]
}
}Retrieve a Site by its integer primary key. The Site must belong to your account; cross-account IDs return 404.
| id required | integer <int64> Integer primary key of the Site |
object (Site) Full representation of a Site used in show/create/update responses. | |||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||
{- "site": {
- "id": 0,
- "name": "string",
- "address_line1": "string",
- "address_line2": "string",
- "city": "string",
- "region": "string",
- "postal_code": "string",
- "country": "string",
- "access_notes": "string",
- "normalized_address": "string",
- "account_id": "string",
- "archived_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "external_aliases": [
- {
- "external_system_slug": "string",
- "external_entity_type": "string",
- "external_id": "string"
}
]
}
}Update mutable Site attributes. Idempotent: applying the same payload twice yields the same final state.
An optional external_id object can be supplied to register a new ExternalAlias against the Site; the operation is itself idempotent on the alias tuple (re-posting the same external_system + external_id does not create a duplicate alias row).
| id required | integer <int64> Integer primary key of the Site |
object | |
object or null Optional external-system reference. Used as the primary dedup key on create and as an alias-upsert on update. |
object (Site) Full representation of a Site used in show/create/update responses. | |||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||
{- "site": {
- "name": "string",
- "address_line1": "string",
- "address_line2": "string",
- "city": "string",
- "region": "string",
- "postal_code": "string",
- "country": "US",
- "access_notes": "string"
}, - "external_id": {
- "external_system": "string",
- "external_entity_type": "site",
- "external_id": "string"
}
}{- "site": {
- "id": 0,
- "name": "string",
- "address_line1": "string",
- "address_line2": "string",
- "city": "string",
- "region": "string",
- "postal_code": "string",
- "country": "string",
- "access_notes": "string",
- "normalized_address": "string",
- "account_id": "string",
- "archived_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "external_aliases": [
- {
- "external_system_slug": "string",
- "external_entity_type": "string",
- "external_id": "string"
}
]
}
}Queue an asynchronous CSV snapshot of every active Site in the authenticated account. Returns 202 Accepted with an export object whose token is the public handle for the status-poll and download endpoints. Requires an account API key — the read-only all-access pass cannot queue exports. Exports are capped at a per-account row limit; when the cap drops matching records the status response sets truncated to true.
{- "export": {
- "token": "0123456789abcdef0123456789abcdef",
- "report_type": "site_csv",
- "status": "pending",
- "record_count": 0,
- "truncated": true,
- "error_message": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "download_url": "string"
}
}Retrieve the status of a Site CSV export by token. When the export is completed and unexpired, the payload includes a short-lived signed download_url.
| token required | string Export token returned by the queue endpoint — the public handle for one CSV export run. |
object (CsvExport) One entity CSV export run. | |||||||||||||||||
| |||||||||||||||||
{- "export": {
- "token": "0123456789abcdef0123456789abcdef",
- "report_type": "site_csv",
- "status": "pending",
- "record_count": 0,
- "truncated": true,
- "error_message": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "download_url": "string"
}
}Redirects to a time-limited signed object-storage URL for the completed export file.
| token required | string Export token returned by the queue endpoint — the public handle for one CSV export run. |
{- "status": "success",
- "message": "string",
- "code": 0,
- "error": "string"
}Manage Jobs (list, retrieve, create, update) — writes route through an alias-only resolver; without an external_id, every POST creates a new Job
Retrieve a paginated list of Jobs for the authenticated account. All responses respect tenant isolation — Jobs are scoped to the bearer token's account.
Filter combinations:
customer (the public cus- identifier) to restrict to Jobs whose customer_id resolves to that Customer in this account.site (Site's integer primary key; Site has no string public_id) to restrict to Jobs whose site_id resolves to that Site in this account.location (the public loc- identifier) to restrict to Jobs at that Location.status to match against Job#job_status literally.job_date_from and/or job_date_to as ISO 8601 dates (YYYY-MM-DD). Both bounds are inclusive.external_system (slug) together with external_id to look up Jobs that map to that external record. Optionally narrow further with external_entity_type (defaults to job). Unlike Sites listing, when no alias resolves to a Job in this account the response is 404 Not Found rather than an empty list.Cross-account ids supplied for customer, site, or location return an empty result set, never records owned by another account.
| customer | string Filter to Jobs whose Customer matches the supplied public |
| site | integer <int64> Filter to Jobs whose Site matches the supplied integer primary key. Site has no string public_id — its integer |
| location | string Filter to Jobs at the Location matching the supplied public |
| status | string Filter to Jobs whose |
| job_date_from | string <date> Inclusive lower bound on |
| job_date_to | string <date> Inclusive upper bound on |
| external_system | string Slug of the external system (e.g. |
| external_id | string External identifier to look up. Combine with |
| external_entity_type | string Default: "job" External entity type (defaults to |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| total_count | integer <int32> Total number of jobs matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int32> Current page number |
Array of objects (JobListItem) |
{- "total_count": 1,
- "total_pages": 1,
- "current_page": 1,
- "jobs": [
- {
- "id": 87,
- "public_id": "job-2c1bd9e6-7c52-4f08-9b86-2c0e3a8a7c11",
- "name": "Spring HVAC tune-up",
- "job_status": "completed",
- "job_date": "2026-05-12",
- "customer_id": "cus-1d0e6e2b-8b1f-44a8-9c39-12f7c1a93b22",
- "location_id": "loc-9c2c4f7e-c1ba-4d2e-9a18-66f0c9c1d101",
- "site_id": 42,
- "invoice_amount": 489.5,
- "currency": "USD"
}
]
}Create a Job, routed through the JobResolver pipeline:
external_id.external_system + external_id.external_id are supplied and already map to a Job in this account, that Job is returned (200 OK, no new alias row created).external_id is supplied an ExternalAlias row is registered in the same transaction (201 Created).Unlike Sites, Jobs have no natural-key dedup. Without an external_id payload, every POST creates a new Job — even if a Job with identical attributes already exists.
Jobs are account-isolated: identical external_id tuples across two different accounts produce two distinct Jobs.
object | |
object or null Optional external-system reference. Used as the primary dedup key on create and as an alias-upsert on update. Both |
object (Job) Full representation of a Job used in show/create/update responses (rendered from | |||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||
object (Job) Full representation of a Job used in show/create/update responses (rendered from | |||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||
{- "job": {
- "customer_id": 0,
- "location_id": 0,
- "site_id": 0,
- "source": "string",
- "name": "string",
- "job_type": "string",
- "job_status": "string",
- "business_unit": "string",
- "description": "string",
- "invoice_amount": 0,
- "currency": "USD",
- "scheduled_date": "2019-08-24",
- "completed_date": "2019-08-24",
- "job_date": "2019-08-24",
- "review_request_opt_out": false
}, - "external_id": {
- "external_system": "string",
- "external_entity_type": "job",
- "external_id": "string"
}
}{- "job": {
- "id": 0,
- "public_id": "string",
- "name": "string",
- "job_status": "string",
- "job_date": "2019-08-24",
- "customer_id": "string",
- "location_id": "string",
- "site_id": 0,
- "invoice_amount": 0,
- "currency": "USD",
- "source": "string",
- "job_type": "string",
- "business_unit": "string",
- "description": "string",
- "scheduled_date": "2019-08-24",
- "completed_date": "2019-08-24",
- "review_request_opt_out": false,
- "visit_count": 0,
- "account_id": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "custom_attributes": [
- {
- "name": "string",
- "label": "string",
- "value": "string",
- "type": "string"
}
], - "external_aliases": [
- {
- "external_system_slug": "string",
- "external_entity_type": "string",
- "external_id": "string"
}
]
}
}Retrieve a Job by its integer primary key. The Job must belong to your account; cross-account IDs return 404.
| id required | integer <int64> Integer primary key of the Job |
object (Job) Full representation of a Job used in show/create/update responses (rendered from | |||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||
{- "job": {
- "id": 0,
- "public_id": "string",
- "name": "string",
- "job_status": "string",
- "job_date": "2019-08-24",
- "customer_id": "string",
- "location_id": "string",
- "site_id": 0,
- "invoice_amount": 0,
- "currency": "USD",
- "source": "string",
- "job_type": "string",
- "business_unit": "string",
- "description": "string",
- "scheduled_date": "2019-08-24",
- "completed_date": "2019-08-24",
- "review_request_opt_out": false,
- "visit_count": 0,
- "account_id": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "custom_attributes": [
- {
- "name": "string",
- "label": "string",
- "value": "string",
- "type": "string"
}
], - "external_aliases": [
- {
- "external_system_slug": "string",
- "external_entity_type": "string",
- "external_id": "string"
}
]
}
}Update mutable Job attributes. Idempotent: applying the same payload twice yields the same final state.
customer_id is immutable after create — any PATCH that attempts to change it is rejected with 422 by a model-level validator.
An optional external_id object can be supplied to register a new ExternalAlias against the Job; the operation is itself idempotent on the alias tuple (re-posting the same external_system + external_id does not create a duplicate alias row).
The shared JobRequestBody schema lists customer_id and location_id as required — that constraint applies to POST only (site_id is optional everywhere; a Job without one is site-less). On PATCH both are optional and any subset of the writable attributes is accepted.
| id required | integer <int64> Integer primary key of the Job |
object | |
object or null Optional external-system reference. Used as the primary dedup key on create and as an alias-upsert on update. Both |
object (Job) Full representation of a Job used in show/create/update responses (rendered from | |||||||||||||||||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||||||||||||||||
{- "job": {
- "customer_id": 0,
- "location_id": 0,
- "site_id": 0,
- "source": "string",
- "name": "string",
- "job_type": "string",
- "job_status": "string",
- "business_unit": "string",
- "description": "string",
- "invoice_amount": 0,
- "currency": "USD",
- "scheduled_date": "2019-08-24",
- "completed_date": "2019-08-24",
- "job_date": "2019-08-24",
- "review_request_opt_out": false
}, - "external_id": {
- "external_system": "string",
- "external_entity_type": "job",
- "external_id": "string"
}
}{- "job": {
- "id": 0,
- "public_id": "string",
- "name": "string",
- "job_status": "string",
- "job_date": "2019-08-24",
- "customer_id": "string",
- "location_id": "string",
- "site_id": 0,
- "invoice_amount": 0,
- "currency": "USD",
- "source": "string",
- "job_type": "string",
- "business_unit": "string",
- "description": "string",
- "scheduled_date": "2019-08-24",
- "completed_date": "2019-08-24",
- "review_request_opt_out": false,
- "visit_count": 0,
- "account_id": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "custom_attributes": [
- {
- "name": "string",
- "label": "string",
- "value": "string",
- "type": "string"
}
], - "external_aliases": [
- {
- "external_system_slug": "string",
- "external_entity_type": "string",
- "external_id": "string"
}
]
}
}Queue an asynchronous CSV snapshot of every Job in the authenticated account. Returns 202 Accepted with an export object whose token is the public handle for the status-poll and download endpoints. Requires an account API key — the read-only all-access pass cannot queue exports. Exports are capped at a per-account row limit; when the cap drops matching records the status response sets truncated to true.
{- "export": {
- "token": "0123456789abcdef0123456789abcdef",
- "report_type": "site_csv",
- "status": "pending",
- "record_count": 0,
- "truncated": true,
- "error_message": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "download_url": "string"
}
}Retrieve the status of a Job CSV export by token. When the export is completed and unexpired, the payload includes a short-lived signed download_url.
| token required | string Export token returned by the queue endpoint — the public handle for one CSV export run. |
object (CsvExport) One entity CSV export run. | |||||||||||||||||
| |||||||||||||||||
{- "export": {
- "token": "0123456789abcdef0123456789abcdef",
- "report_type": "site_csv",
- "status": "pending",
- "record_count": 0,
- "truncated": true,
- "error_message": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "download_url": "string"
}
}Redirects to a time-limited signed object-storage URL for the completed export file.
| token required | string Export token returned by the queue endpoint — the public handle for one CSV export run. |
{- "status": "success",
- "message": "string",
- "code": 0,
- "error": "string"
}Inbound integration envelopes — batch-ingest external objects (customers, sites, jobs, employees, tag types) via a single-shot or accumulating workflow. ServiceTitan producers may additionally send raw context kinds (contacts, invoices, appointment assignments, business units, job types, memberships) plus technicians/locations aliases; context kinds are stored for wave-0 assembly and never upserted. Every POST creates a new envelope; resubmitting a source_event_id creates a correction linked to the original via original_envelope_id. Object fields are consumed by the wave-0 transformer selected via external_system — slugs with a registered transformer (currently servicetitan) use that vendor's vocabulary; any other slug uses the generic pass-through transformer, which expects canonical Liftify field names (see the GenericEnvelope*Object schemas).
Create an inbound integration envelope. Two operating modes share this endpoint:
objects together with auto_seal: true. In one request the envelope is created, items are appended, the envelope is sealed, and an ingestion worker is enqueued. Responds 202 Accepted with status: "pending".objects (or send an empty block) and leave auto_seal unset/false. The envelope is created in the building state (201 Created); append items via POST /v1/integrations/envelopes/{id}/items and finalize with POST /v1/integrations/envelopes/{id}/seal.Corrections: every POST creates a new envelope, even when source_event_id repeats — so a corrected payload can be resubmitted and reprocessed. A repeat submission is a correction that links back to the original request via original_envelope_id (the earliest envelope for that source_event_id); the first submission omits this field.
Each object under objects.<kind> must carry a non-blank external_id — it becomes the item's idempotency key. All other fields on each object are free-form and flow through to the downstream transformer verbatim.
| external_system required | string Slug of the external system the payload originates from. Must reference an active system in your account. Slugs with a registered transformer (e.g. |
| source_event_id required | string Caller-supplied identifier of the source event. Not unique — re-posting the same value creates a new envelope (a correction) that links back to the original via |
| schema_version | string Value: "1" Payload schema version. Defaults to |
| mode | string Enum: "single_shot" "accumulating" Operating mode. Defaults to |
| auto_seal | boolean When |
| sync_run_id | integer <int64> Optional id of the platform sync run this envelope belongs to, echoed from the sync trigger payload. Groups the envelope's ingestion under that run for tracking. Must reference a sync run in your account for the same |
object (EnvelopeObjects) Inbound objects grouped by kind. Kebab-case kind keys (e.g. |
object (IntegrationEnvelope) Lifecycle and counter metadata for an inbound integration envelope. The raw per-object payloads are never exposed. | |||||||||||||||||||||||
| |||||||||||||||||||||||
{- "external_system": "servicetitan",
- "source_event_id": "evt-9f2c1a7e-44b0-4c2a-9d3e-7a1b2c3d4e5f",
- "schema_version": "1",
- "mode": "single_shot",
- "auto_seal": true,
- "objects": {
- "customers": [
- {
- "external_id": "st-cust-1001",
- "firstName": "Jane",
- "lastName": "Smith"
}
], - "jobs": [
- {
- "external_id": "st-job-5001",
- "customerId": "st-cust-1001",
- "status": "completed"
}
]
}
}{- "envelope": {
- "id": 1024,
- "status": "pending",
- "mode": "single_shot",
- "schema_version": "1",
- "item_count": 3,
- "received_at": "2026-06-23T15:04:05Z",
- "sealed_at": "2026-06-23T15:04:06Z",
- "started_at": null,
- "finished_at": null
}
}Retrieve an envelope by its integer primary key. The envelope must belong to your account; cross-account IDs return 404.
| id required | integer <int64> Integer primary key of the envelope |
object (IntegrationEnvelope) Lifecycle and counter metadata for an inbound integration envelope. The raw per-object payloads are never exposed. | |||||||||||||||||||||||
| |||||||||||||||||||||||
{- "envelope": {
- "id": 1024,
- "status": "pending",
- "mode": "single_shot",
- "schema_version": "1",
- "item_count": 3,
- "received_at": "2026-06-23T15:04:05Z",
- "sealed_at": "2026-06-23T15:04:06Z",
- "started_at": null,
- "finished_at": null
}
}Discard a building envelope and destroy its items. Only envelopes still in the building state can be discarded — once sealed (or in any other state) the envelope is locked and this returns 409.
| id required | integer <int64> Integer primary key of the envelope |
{- "status": "success",
- "message": "string",
- "code": 0,
- "error": "string"
}Append objects to a building envelope. Items are upserted idempotently on (envelope, kind, external_id) — re-posting the same external_id updates the stored payload rather than creating a duplicate.
Only building envelopes accept items; appending to a sealed (or otherwise locked) envelope returns 409. The request must contain at least one object, and every object must carry a non-blank external_id.
| id required | integer <int64> Integer primary key of the envelope |
required | object (EnvelopeObjects) Inbound objects grouped by kind. Kebab-case kind keys (e.g. | ||||||||||||||||||||||||||
| |||||||||||||||||||||||||||
object (IntegrationEnvelope) Lifecycle and counter metadata for an inbound integration envelope. The raw per-object payloads are never exposed. | |||||||||||||||||||||||
| |||||||||||||||||||||||
{- "objects": {
- "customers": [
- {
- "external_id": "st-cust-1002",
- "firstName": "John",
- "lastName": "Doe"
}
], - "sites": [
- {
- "external_id": "st-site-3001",
- "addressLine1": "123 Main St"
}
]
}
}{- "envelope": {
- "id": 1024,
- "status": "pending",
- "mode": "single_shot",
- "schema_version": "1",
- "item_count": 3,
- "received_at": "2026-06-23T15:04:05Z",
- "sealed_at": "2026-06-23T15:04:06Z",
- "started_at": null,
- "finished_at": null
}
}Seal a building envelope, transitioning it to pending and enqueuing the ingestion worker. Responds 202 Accepted.
Idempotency: re-sealing an envelope already past building (e.g. pending, processing, or a terminal-success state) is a no-op success (202). Sealing an expired or discarded envelope returns 409; sealing an envelope with no items returns 422.
| id required | integer <int64> Integer primary key of the envelope |
{- "envelope": {
- "id": 1024,
- "status": "pending",
- "mode": "single_shot",
- "schema_version": "1",
- "item_count": 3,
- "received_at": "2026-06-23T15:04:05Z",
- "sealed_at": "2026-06-23T15:04:06Z",
- "started_at": null,
- "finished_at": null
}
}Report-back endpoint for the platform-triggered sync processor. One POST per sync run:
status: "completed" advances the tenant's export-feed cursors — only the feeds present under cursors are advanced; an omitted feed's old cursor replays on the next run — stamps last_synced_at, and completes the sync run.status: "failed" marks the sync run failed with error_message and leaves all cursors untouched.Idempotency: a run already in a terminal state answers 200 without changes, so duplicate deliveries are harmless. The sync run must belong to your account; cross-account ids return 404.
| id required | integer <int64> Integer id of the sync run (from the sync trigger payload) |
| status required | string Enum: "completed" "failed" Outcome of the processor run. |
object Per-feed continuation cursors to advance (feed name => continueFrom). Only supplied feeds are advanced. | |
| error_message | string Human-readable failure detail (used with the |
| backlogged_feeds | Array of strings Feeds that hit their per-run drain cap and are still catching up (used with the |
| c4_overflow | integer >= 0 Count of customer creates deferred past the processor's per-run contact fan-out cap (used with the |
object | |||||
| |||||
{- "status": "completed",
- "cursors": {
- "jobs": "2026-07-09T17:00:00Z",
- "invoices": "2026-07-09T16:58:12Z"
}, - "backlogged_feeds": [
- "invoices"
], - "c4_overflow": 0
}{- "sync_run": {
- "id": 0,
- "status": "pending"
}
}Retrieve a paginated list of Employees for the authenticated account.
Filter combinations:
external_system (slug) together with external_id to look up the Employee that maps to that external record. Optionally narrow further with external_entity_type (defaults to employee). When no alias resolves the response is 200 OK with an empty employees list (parity with Sites listing).user_id (the Liftify internal User integer id) to return the Employee that is linked to that User (or an empty list).location (the public loc- identifier) to restrict to Employees at that Location, via active JobEmployee assignments or direct location assignment.name to substring-match (case-insensitive) against first_name, last_name, or the concatenated full name.Cross-account ids supplied for location return an empty result set, never records owned by another account.
| external_system | string Slug of the external system (e.g. |
| external_id | string External identifier to look up. Combine with |
| external_entity_type | string Default: "employee" External entity type (defaults to |
| user_id | integer <int64> Filter to the Employee linked to the supplied Liftify User integer id. |
| location | string Filter to Employees at the Location matching the supplied public |
| name | string Case-insensitive substring matched against |
| page | integer >= 1 Default: 1 Page number for pagination |
| size | integer [ 1 .. 1000 ] Default: 100 Number of items per page |
| total_count | integer <int32> Total number of employees matching the filter criteria |
| total_pages | integer <int32> Total number of pages available |
| current_page | integer <int32> Current page number |
Array of objects (EmployeeListItem) |
{- "total_count": 1,
- "total_pages": 1,
- "current_page": 1,
- "employees": [
- {
- "id": 42,
- "employee_id": "emp-2c1bd9e6-7c52-4f08-9b86-2c0e3a8a7c11",
- "first_name": "Pat",
- "last_name": "Lee",
- "active": true,
- "title": "Senior Technician"
}
]
}Create an Employee, routed through the EmployeeResolver pipeline:
external_id.external_system + external_id.external_id are supplied and already map to an Employee in this account, that Employee is returned (200 OK, no new alias row created).employee.user_id is supplied and an Employee in this account is already linked to that User, that Employee is returned (200 OK).first_name + last_name exactly match an active Employee in this account (case-insensitive), that Employee is returned (200 OK).200 OK.external_id is supplied an ExternalAlias row is registered in the same transaction (201 Created).Employees are account-isolated: identical external_id tuples across two different accounts produce two distinct Employees.
object | |
object or null Optional external-system reference. Used as the primary dedup key on create and as an alias-upsert on update. Both |
object (Employee) Full representation of an Employee used in show/create/update responses (rendered from | |||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||
object (Employee) Full representation of an Employee used in show/create/update responses (rendered from | |||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||
{- "employee": {
- "first_name": "string",
- "last_name": "string",
- "email": "string",
- "phone": "string",
- "title": "string",
- "department": "string",
- "source": "string",
- "active": true,
- "user_id": 0
}, - "external_id": {
- "external_system": "string",
- "external_entity_type": "employee",
- "external_id": "string"
}
}{- "employee": {
- "id": 0,
- "employee_id": "string",
- "first_name": "string",
- "last_name": "string",
- "email": "string",
- "active": true,
- "title": "string",
- "phone": "string",
- "source": "string",
- "account_id": "string",
- "user_id": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "merged_into_id": 0,
- "merged_at": "2019-08-24T14:15:22Z",
- "external_aliases": [
- {
- "external_system_slug": "string",
- "external_entity_type": "string",
- "external_id": "string"
}
]
}
}Retrieve an Employee by its integer primary key. The Employee must belong to your account;
cross-account IDs return 404.
This endpoint also resolves an Employee that has been merged into another as a duplicate —
it is the only endpoint that does. The response carries merged_into_id / merged_at so a
caller holding the merged id can follow the pointer to the surviving Employee. Merged
Employees are omitted from the listing endpoint and rejected by the update endpoint.
| id required | integer <int64> Integer primary key of the Employee |
object (Employee) Full representation of an Employee used in show/create/update responses (rendered from | |||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||
{- "employee": {
- "id": 0,
- "employee_id": "string",
- "first_name": "string",
- "last_name": "string",
- "email": "string",
- "active": true,
- "title": "string",
- "phone": "string",
- "source": "string",
- "account_id": "string",
- "user_id": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "merged_into_id": 0,
- "merged_at": "2019-08-24T14:15:22Z",
- "external_aliases": [
- {
- "external_system_slug": "string",
- "external_entity_type": "string",
- "external_id": "string"
}
]
}
}Update mutable Employee attributes. Idempotent: applying the same payload twice yields the same final state and does not republish EmployeeUpdated.
An optional external_id object can be supplied to register a new ExternalAlias against the Employee; the operation is itself idempotent on the alias tuple (re-posting the same external_system + external_id does not create a duplicate alias row).
| id required | integer <int64> Integer primary key of the Employee |
object | |
object or null Optional external-system reference. Used as the primary dedup key on create and as an alias-upsert on update. Both |
object (Employee) Full representation of an Employee used in show/create/update responses (rendered from | |||||||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||||||
{- "employee": {
- "first_name": "string",
- "last_name": "string",
- "email": "string",
- "phone": "string",
- "title": "string",
- "department": "string",
- "source": "string",
- "active": true,
- "user_id": 0
}, - "external_id": {
- "external_system": "string",
- "external_entity_type": "employee",
- "external_id": "string"
}
}{- "employee": {
- "id": 0,
- "employee_id": "string",
- "first_name": "string",
- "last_name": "string",
- "email": "string",
- "active": true,
- "title": "string",
- "phone": "string",
- "source": "string",
- "account_id": "string",
- "user_id": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z",
- "merged_into_id": 0,
- "merged_at": "2019-08-24T14:15:22Z",
- "external_aliases": [
- {
- "external_system_slug": "string",
- "external_entity_type": "string",
- "external_id": "string"
}
]
}
}Queue an asynchronous CSV snapshot of every Employee in the authenticated account. Returns 202 Accepted with an export object whose token is the public handle for the status-poll and download endpoints. Requires an account API key — the read-only all-access pass cannot queue exports. Exports are capped at a per-account row limit; when the cap drops matching records the status response sets truncated to true.
{- "export": {
- "token": "0123456789abcdef0123456789abcdef",
- "report_type": "site_csv",
- "status": "pending",
- "record_count": 0,
- "truncated": true,
- "error_message": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "download_url": "string"
}
}Retrieve the status of an Employee CSV export by token. When the export is completed and unexpired, the payload includes a short-lived signed download_url.
| token required | string Export token returned by the queue endpoint — the public handle for one CSV export run. |
object (CsvExport) One entity CSV export run. | |||||||||||||||||
| |||||||||||||||||
{- "export": {
- "token": "0123456789abcdef0123456789abcdef",
- "report_type": "site_csv",
- "status": "pending",
- "record_count": 0,
- "truncated": true,
- "error_message": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "download_url": "string"
}
}Redirects to a time-limited signed object-storage URL for the completed export file.
| token required | string Export token returned by the queue endpoint — the public handle for one CSV export run. |
{- "status": "success",
- "message": "string",
- "code": 0,
- "error": "string"
}