Developers · Zapier integration
Zapier Integration API Reference
API base URL
https://secure-api-v1.liendeadline.com
Token, refresh, connection test, triggers and action
Authorization host
https://liendeadline.com
Browser step only: /api/zapier/oauth/authorize
Authentication
OAuth 2.0 authorization code with refresh tokens
JSON over HTTPS
Overview
The integration uses two hosts. The authorization request is a browser step on the website host, https://liendeadline.com, which receives the user’s LienDeadline sign-in session and forwards the request to the API. Every other request goes directly to the API host, https://secure-api-v1.liendeadline.com.
Use HTTPS for every request; the API host redirects plain-HTTP requests to HTTPS. Request and response bodies are JSON, and the token endpoint also accepts form-encoded bodies.
Data routes act on the LienDeadline user who authorized the connection. Every LienDeadline plan includes Zapier access.
| Method | Endpoint | Credential | Used for |
|---|---|---|---|
| GET | /api/zapier/oauth/authorizeliendeadline.com | LienDeadline sign-in session | Start OAuth authorization in the user’s browser |
| POST | /api/zapier/oauth/tokensecure-api-v1.liendeadline.com | OAuth client ID and secret | Exchange an authorization code or a refresh token |
| POST | /api/zapier/oauth/refreshsecure-api-v1.liendeadline.com | OAuth client ID and secret | Refresh tokens; same as the token endpoint with grant_type=refresh_token |
| GET | /api/zapier/statussecure-api-v1.liendeadline.com | Bearer access token | Connection test and connection label |
| GET | /api/zapier/v2/triggers/upcomingsecure-api-v1.liendeadline.com | Bearer access token | Upcoming Deadline trigger |
| GET | /api/zapier/v2/triggers/reminderssecure-api-v1.liendeadline.com | Bearer access token | Deadline Reminder trigger |
| POST | /api/zapier/webhook/invoicesecure-api-v1.liendeadline.com | Bearer access token | Create Deadline Project From Invoice action |
Authentication: OAuth 2.0
The integration uses the OAuth 2.0 authorization code grant with refresh tokens. The client secret is used only in server-to-server token requests. LienDeadline stores hashes of authorization codes, access tokens and refresh tokens, not the tokens themselves.
2. Token request
https://secure-api-v1.liendeadline.com/api/zapier/oauth/tokenExchange the authorization code for tokens, and later refresh them. This is a server-to-server request to the API host. Send parameters as application/x-www-form-urlencoded, as the Zapier app does, or as a JSON object with Content-Type: application/json. Authenticate the client with client_id and client_secret in the body or with HTTP Basic authentication; body values take precedence.
| Parameter | Grant type | Description |
|---|---|---|
grant_type | Both | authorization_code or refresh_token. |
code | authorization_code | The code from the authorization redirect. |
redirect_uri | authorization_code | Must match the redirect_uri sent in the authorization request. |
refresh_token | refresh_token | The most recent refresh token issued to the connection. |
client_id | Both | Required unless sent with HTTP Basic authentication. |
client_secret | Both | Required unless sent with HTTP Basic authentication. |
curl -X POST "https://secure-api-v1.liendeadline.com/api/zapier/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Accept: application/json" \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "code=AUTHORIZATION_CODE" \
--data-urlencode "redirect_uri=REDIRECT_URI" \
--data-urlencode "client_id=YOUR_CLIENT_ID" \
--data-urlencode "client_secret=YOUR_CLIENT_SECRET"curl -X POST "https://secure-api-v1.liendeadline.com/api/zapier/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Accept: application/json" \
--data-urlencode "grant_type=refresh_token" \
--data-urlencode "refresh_token=REFRESH_TOKEN" \
--data-urlencode "client_id=YOUR_CLIENT_ID" \
--data-urlencode "client_secret=YOUR_CLIENT_SECRET"{
"access_token": "ACCESS_TOKEN",
"token_type": "Bearer",
"refresh_token": "REFRESH_TOKEN",
"expires_in": 3600,
"scope": "zapier:read zapier:write",
"email": "ops@example.com"
}| Field | Type | Description |
|---|---|---|
access_token | string | Opaque bearer token for the data routes. |
token_type | string | Always Bearer. |
refresh_token | string | Opaque token for the next refresh. Every successful token request returns a new one. |
expires_in | integer | Access-token lifetime in seconds; 3600 by default. |
scope | string | The scope recorded at authorization, or an empty string. |
email | string | Email address of the LienDeadline account that authorized the connection. |
Refresh alias
https://secure-api-v1.liendeadline.com/api/zapier/oauth/refreshAccepts the same parameters and returns the same responses as the token endpoint, with grant_type set to refresh_token. The Zapier app refreshes through /api/zapier/oauth/token.
Token lifecycle
- Access tokens expire after
expires_inseconds. When a data route returns401, the Zapier integration refreshes the access token automatically. - Refresh tokens are valid for 180 days by default and rotate: each successful refresh revokes the refresh token it used and returns a new one. A reused, revoked or expired refresh token returns
invalid_grant. - Each LienDeadline user has one active Zapier access token. Issuing a new access token, by code exchange or by refresh, revokes the previous one.
- Completing a new authorization also revokes the user’s earlier refresh tokens, so an older Zapier connection to the same LienDeadline user stops working until it is reconnected.
OAuth errors
The token and refresh endpoints return errors as JSON with error and error_description.
| Status | error | When |
|---|---|---|
| 400 | invalid_request | A required parameter is missing: code or redirect_uri for authorization_code, or refresh_token for refresh_token. The authorization endpoint also returns it for a missing or unaccepted redirect_uri. |
| 400 | invalid_grant | The authorization code is invalid, expired, already used or was issued for another redirect_uri, or the refresh token is invalid, expired or already used. |
| 400 | unsupported_grant_type | grant_type is not authorization_code or refresh_token. |
| 401 | invalid_client | The client ID or client secret is missing or wrong. Client authentication is checked before the grant. |
| 500 | server_error | OAuth is not configured on the server. |
{
"error": "invalid_grant",
"error_description": "Invalid, expired, or already used authorization code."
}Calling the data routes
Send the access token in the Authorization header. A missing, unknown, expired or revoked token returns 401 with {"detail": "Unauthorized"}.
Authorization: Bearer ACCESS_TOKENConnection test
Connection status
https://secure-api-v1.liendeadline.com/api/zapier/statusZapier calls this route to test the connection and uses email as the connection label.
curl "https://secure-api-v1.liendeadline.com/api/zapier/status" \
-H "Authorization: Bearer ACCESS_TOKEN"{
"connected": true,
"token_last4": "a1b2",
"token_created_at": "2026-10-01T15:30:00+00:00",
"auth_mode": "oauth2",
"oauth_ready": true,
"email": "ops@example.com"
}| Field | Type | Description |
|---|---|---|
connected | boolean | true when the user has an active access token. |
token_last4 | string | Last four characters of the active access token. |
token_created_at | string | ISO 8601 time the active access token was issued. |
auth_mode | string | Always oauth2. |
oauth_ready | boolean | Always true. |
email | string | Email address of the LienDeadline account that authorized the connection. |
Triggers
Both triggers are polling endpoints that return a top-level JSON array. They cover projects that belong to the connected LienDeadline user. Invoices imported from QuickBooks are included only after their project type is confirmed. Dates are calculated in UTC.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer, 1–500 | 50 | Maximum number of items returned. |
days_ahead | integer, 1–365 | 30 (upcoming), 14 (reminders) | Window in days from today. Deadlines from today through today plus days_ahead are included. |
since | ISO 8601 date-time | None | Only include projects updated at or after this time. |
A value outside these ranges, or a since value that is not a date-time, returns 422.
Upcoming Deadline
https://secure-api-v1.liendeadline.com/api/zapier/v2/triggers/upcomingReturns one item per project whose lien filing deadline falls inside the window, most recently updated projects first. deadline_date is the lien filing deadline.
curl -G "https://secure-api-v1.liendeadline.com/api/zapier/v2/triggers/upcoming" \
-H "Authorization: Bearer ACCESS_TOKEN" \
--data-urlencode "limit=50" \
--data-urlencode "days_ahead=30"Deadline Reminder
https://secure-api-v1.liendeadline.com/api/zapier/v2/triggers/remindersReturns an item when a project’s preliminary notice or lien filing deadline is exactly one of the project’s reminder days away (1, 7 or 30 days), most recently updated projects first. deadline_date is the deadline that matched.
Only projects with Zapier reminders turned on in LienDeadline are included. Projects created by the action start with Zapier reminders turned off. A reminder day larger than days_ahead never matches, so set days_ahead to 30 or more to receive 30-day reminders.
Trigger item fields
| Field | Type | Description |
|---|---|---|
id | string | Deduplication key: a 32-character hash of the trigger type, deadline type, project, deadline date, days remaining and the project’s last update time. |
trigger_type | string | upcoming_deadline or deadline_reminder. |
account_id | string or null | LienDeadline account that owns the project. |
project_id | string | LienDeadline project ID. |
project_name | string | Project name, or an empty string. |
customer_name | string | Client name saved on the project, or an empty string. |
state | string | Project state, normally a two-letter code such as TX. |
deadline_date | string | Deadline date, YYYY-MM-DD. |
days_until_deadline | integer | Days from today (UTC) to deadline_date. |
source_updated_at | string | ISO 8601 time the project was last updated, or its creation time when no update is recorded. |
updated_at | string | Same value as source_updated_at. |
deep_link_url | string | Link to the project in the LienDeadline dashboard. Opening it requires signing in. |
Zapier skips items whose id it has already seen. Because the id includes the days remaining, an upcoming deadline gets a new id on each day it stays in the window, and editing a project also produces a new id. A reminder item appears only on the day its reminder is due.
[
{
"id": "0f1e2d3c4b5a69788796a5b4c3d2e1f0",
"trigger_type": "upcoming_deadline",
"account_id": "00000000-0000-4000-8000-000000000001",
"project_id": "00000000-0000-4000-8000-000000000002",
"project_name": "Example Warehouse Retrofit",
"customer_name": "Example Supply Co.",
"state": "TX",
"deadline_date": "2027-01-15",
"days_until_deadline": 103,
"source_updated_at": "2026-10-01T15:30:00+00:00",
"updated_at": "2026-10-01T15:30:00+00:00",
"deep_link_url": "https://liendeadline.com/dashboard?project=00000000-0000-4000-8000-000000000002"
}
]Action: Create Deadline Project From Invoice
Create a deadline project
https://secure-api-v1.liendeadline.com/api/zapier/webhook/invoiceCalculates the preliminary notice and lien filing deadlines for an invoice and saves the result as a project in the connected LienDeadline account.
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer ACCESS_TOKEN |
Content-Type | Yes | application/json |
X-Zapier-Event-Id | No | Idempotency key. See Retries and duplicates below. |
| Body field | Type | Required | Description |
|---|---|---|---|
state | string | Yes | Two-letter code or full name of one of the 50 states or DC, in any letter case. |
invoice_date | string | Yes | YYYY-MM-DD or MM/DD/YYYY. Saved and returned as YYYY-MM-DD. |
invoice_amount_cents | integer | One amount | Invoice amount in cents, 0 or more. The Zapier action sends this field. |
invoice_amount | number | One amount | Invoice amount in dollars, 0 or more. Used only when invoice_amount_cents is absent. |
project_name | string | No | Project name. |
client_name | string | No | Client name. Triggers return it as customer_name. |
project_type | string | No | Commercial (default) or Residential. |
role | string | No | Your role on the project, such as supplier (default) or contractor. |
notes | string | No | Notes saved on the project. |
invoice_number | string | No | Sent by the Zapier action. The API does not currently save or return it. |
The API ignores body fields not listed here. A missing state or invoice_date, a date in another format, or an invoice_amount_cents value that is negative or not a whole number returns 422. An unrecognized state name, a state code LienDeadline does not support (the error has code UNSUPPORTED_STATE), a negative invoice_amount, or a request without either amount field returns 400.
curl -X POST "https://secure-api-v1.liendeadline.com/api/zapier/webhook/invoice" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "X-Zapier-Event-Id: zapier-source-INV-1001" \
-d '{
"state": "TX",
"invoice_date": "2026-09-15",
"invoice_amount_cents": 499200,
"project_name": "Example Warehouse Retrofit",
"client_name": "Example Supply Co.",
"project_type": "Commercial",
"role": "supplier"
}'{
"success": true,
"version": "v1",
"id": "00000000-0000-4000-8000-000000000002",
"project_name": "Example Warehouse Retrofit",
"invoice_date": "2026-09-15",
"state": "TX",
"invoice_amount": "4992.00",
"invoice_amount_cents": 499200,
"preliminary_deadline": "2026-11-15",
"preliminary_deadline_days": 42,
"lien_deadline": "2027-01-15",
"lien_deadline_days": 103,
"message": "Project created successfully"
}Example values are synthetic. Dates show the format only and are not deadline guidance.
| Field | Type | Description |
|---|---|---|
success | boolean | true when the project was created. |
version | string | Always v1. |
id | string | ID of the new LienDeadline project. |
project_name | string | Project name, or an empty string. |
invoice_date | string | Invoice date, YYYY-MM-DD. |
state | string | Two-letter state code. |
invoice_amount | string | Amount in dollars with two decimal places. |
invoice_amount_cents | integer | Amount in cents. |
preliminary_deadline | string or null | Preliminary notice deadline, YYYY-MM-DD, or null when none was calculated. |
preliminary_deadline_days | integer or null | Days from today to the preliminary notice deadline. |
lien_deadline | string | Lien filing deadline, YYYY-MM-DD. |
lien_deadline_days | integer | Days from today to the lien filing deadline. |
message | string | Project created successfully |
Retries and duplicates
Send X-Zapier-Event-Id to make retries safe. LienDeadline records each value per user in the same transaction that saves the project. A later request from the same user with the same value creates nothing and returns 200 without the project ID or deadlines. If a request fails before the project is saved, for example at the plan limit, the value is not recorded and a retry can succeed.
The Zapier action sets this header from its Deduplication key input (dedupe_key) as zapier-source- followed by the key. Without a key, it uses an identifier from the Zapier run when one is available, or otherwise a hash of the request body. Map a value that identifies the source invoice, such as its record number in your accounting app.
{
"success": true,
"version": "v1",
"duplicate": true,
"message": "Event already processed"
}Plan limits
Each project the action creates counts as one protected item toward the account’s plan limit (see Pricing). When the limit is reached, the action creates nothing and returns 402. Repeated requests that return the duplicate response do not count.
{
"success": false,
"version": "v1",
"code": "LIMIT_REACHED",
"limit_type": "manual_calcs",
"used": 3,
"limit": 3,
"plan": "free"
}Errors & limits
These statuses apply to the connection test, trigger and action routes.
| Status | Meaning | Response body |
|---|---|---|
| 400 | Action only: unrecognized state name, unsupported state code (code UNSUPPORTED_STATE), negative invoice_amount, or no amount field. | {"success": false, "version": "v1", "error": "…"} |
| 401 | Missing, unknown, expired or revoked access token. The Zapier integration refreshes the token automatically. | {"detail": "Unauthorized"} |
| 402 | Action only: the plan’s protected-item limit is reached. | code is LIMIT_REACHED; see Plan limits. |
| 403 | Triggers and action: the account’s plan does not include Zapier access. | code is PLAN_NOT_ALLOWED, inside detail for the triggers. |
| 422 | Invalid query parameter or request body. | {"detail": [{"loc": […], "msg": "…", "type": "…"}]} |
| 429 | Rate limit exceeded; see Rate limits below. The response has no Retry-After header. Zapier treats 429 as throttling and retries later. | {"error": "Rate limit exceeded: 10 per 1 minute"} |
| 500 | The deadline could not be calculated for a supported state, or the project could not be saved. | {"detail": "…"} or {"success": false, "version": "v1", "error": "…"} |
Rate limits
| Route | Limit |
|---|---|
GET /api/zapier/v2/triggers/upcoming | 60 requests per minute |
GET /api/zapier/v2/triggers/reminders | 60 requests per minute |
POST /api/zapier/webhook/invoice | 10 requests per minute |
Support
For integration questions or access problems, email support with the request path, the response status and body, and the approximate time of the request. Never send access tokens, refresh tokens or client secrets.