How Do You Set an Expiration Date From a Start Date in Zendesk?
Zendesk has no calculated fields, so an expiration date based on a custom start date needs either a webhook with Liquid date math or an action flow with a custom code step. Zendesk calls the webhook route unsupported, which is worth knowing before you build it.
Key takeaways
- Zendesk cannot calculate one date field from another natively, so an expiration date based on a custom start date needs a webhook with Liquid or an action flow with a custom code step.
- The Liquid formula converts the start date to a Unix timestamp, adds seconds with plus, then reformats it as YYYY-MM-DD, where 30 days equals 2,592,000 seconds.
- Zendesk's own help article says using a trigger and a webhook to update tickets is not recommended or supported, because business rules and API updates can collide on the same ticket.
- Zendesk action flows are available on Suite Growth and above and Support Team and above, allow up to 100 flows, and can run synchronous JavaScript of up to 10,000 characters.
- Custom date fields used in Zendesk business rules and views always reference GMT rather than the account time zone, which can shift deadlines near midnight.
Zendesk can't calculate one date field from another natively, so to set an expiration date 30 days after a custom start date you either run a trigger that calls a webhook with a Liquid formula (date: '%s' | plus: 2592000 | date: '%Y-%m-%d'), or build an action flow with a custom code step. If the date only needs to count from today, a plain trigger action can set it without either.
| Method | Counts from | Plans | Zendesk support status |
|---|---|---|---|
| Trigger date action | The day the trigger fires | All plans with triggers | Native, supported |
| Trigger + webhook + Liquid | Any custom date field | Any plan with webhooks and API token access | Works, but Zendesk says it isn't recommended or supported |
| Action flow with a custom code step | Any custom date field | Suite Growth and above, Support Team and above | Native, Zendesk's suggested alternative |
| Marketplace app or middleware (Zapier, custom service) | Any field | Varies | Supported by the vendor, extra cost |
Why can't Zendesk calculate an expiration date on its own?
You've got a start date in a custom field: when a trial began, when a warranty activated, when a contract was signed. You want an expiration date 30 days, 90 days or a year later, filled in automatically.
Zendesk has no calculated fields. You can't tell a date field to equal "another date field + 30 days" the way you would in a spreadsheet, and the standard trigger actions can't read one custom field to write another. Custom date fields do work as trigger and automation conditions, though, which is what makes the workarounds below possible.
Doing it by hand is slow and error-prone, and it gets worse as ticket volume grows. The common cases where teams need it:
- Warranties and service contracts: reach out before coverage ends and offer a renewal.
- Trials: trigger follow-ups and upgrade reminders on the day a trial ends.
- Response deadlines: set a due date from ticket creation and escalate before it passes.
- Subscription renewals: calculate the renewal date from the signup date.
- Compliance deadlines: track when documentation expires or a review is due.
Can a trigger set a date field on its own?
Yes, if the date counts from the moment the trigger fires rather than from another field.
When this works best
- You need a date relative to ticket creation, not to a custom date field
- The number of days is always the same
- You don't need business days (Zendesk says custom date field actions always use calendar days and ignore schedules)
How to set it up
- Create the date field
- Go to Admin Center > Objects and rules > Tickets > Fields
- Create a date field for the expiration date (for example "Warranty Expiration Date")
- Create the trigger
- Go to Admin Center > Objects and rules > Business rules > Triggers
- Add conditions such as "Ticket is Created" and "Warranty Start Date is present"
- In Actions, pick the expiration date field and set it a number of days from the current date (for example 30)
The limitation: the count starts from now, not from another field. If a customer enters a warranty start date of three months ago, this gives the wrong answer. For that you need one of the next two methods.
How do you calculate the date with a webhook and Liquid?
This is the method most admins use. A trigger fires a webhook that calls the Zendesk API on the same ticket, and Liquid markup in the JSON body does the arithmetic.
Know what you're taking on first. Zendesk's article Can I use a trigger and a webhook to update tickets? answers "No, this workflow isn't recommended or supported." The reason given is race conditions: "Errors are likely when a ticket gets updated by business rules and the API at the same time." Plenty of teams run it anyway, but Zendesk Support won't troubleshoot it, and you should test for tickets where another trigger or an agent update lands at the same moment.
The pieces
Webhooks let a trigger send an HTTP request. Pointed at your own Zendesk API, the webhook can update fields a trigger action can't.
Liquid is the templating language Zendesk uses for placeholders. It supports filters such as date and plus, plus if statements and loops, which is enough for date arithmetic.
Step 1: Create an API token
- Go to Admin Center > Apps and integrations > APIs > API tokens
- Make sure token access is enabled
- Add a token, give it a description such as "Expiration date webhook" and store it securely
Step 2: Create the two date fields
- Start date field, filled in by agents or customers (for example "Warranty Start Date")
- Expiration date field, filled in by the webhook (for example "Warranty Expiration Date")
Create both under Admin Center > Objects and rules > Tickets > Fields (Add field > Date) and note both field IDs. The ID is shown in the field's details and in the URL when you edit it.
Step 3: Create the webhook
- Go to Admin Center > Apps and integrations > Webhooks > Webhooks
- Click "Create webhook" and choose Trigger or automation as the connection type
- Configure it:
- Name: Update Expiration Date
- Endpoint URL:
https://yoursubdomain.zendesk.com/api/v2/tickets/{{ticket.id}}.json - Request method: PUT
- Request format: JSON
- Authentication: Basic authentication
- Username:
[email protected]/token(the/tokensuffix matters) - Password: the API token from Step 1
- Click "Create webhook"
Step 4: Create the trigger with the Liquid calculation
- Go to Admin Center > Objects and rules > Business rules > Triggers
- Click "Create trigger" and name it, for example "Calculate Warranty Expiration Date"
Conditions:
- Ticket: Is Created (or Is Updated, depending on when the start date gets filled in)
- Warranty Start Date: Is present
- Tags: Does not contain
expiration_calculated(stops it firing again)
Actions:
- Add tags:
expiration_calculated - Notify by > Active webhook: select "Update Expiration Date"
JSON body:
json
{
"ticket": {
"custom_fields": [
{
"id": YOUR_EXPIRATION_FIELD_ID,
"value": "{{ ticket.ticket_field_YOUR_START_DATE_FIELD_ID | date: '%s' | plus: 2592000 | date: '%Y-%m-%d' }}"
}
]
}
}
How the Liquid works:
{{ ticket.ticket_field_YOUR_START_DATE_FIELD_ID }}reads the start date field| date: '%s'turns it into a Unix timestamp (seconds since 1970)| plus: 2592000adds 30 days of seconds| date: '%Y-%m-%d'turns it back into the YYYY-MM-DD format Zendesk date fields expect
To change the offset, change the seconds:
- 1 day = 86,400 seconds
- 7 days = 604,800 seconds
- 30 days = 2,592,000 seconds
- 90 days = 7,776,000 seconds
- 1 year (365 days) = 31,536,000 seconds
Step 5: Replace the field IDs
In the JSON body, swap YOUR_EXPIRATION_FIELD_ID for the expiration field's ID and YOUR_START_DATE_FIELD_ID for the start field's ID.
Step 6: Test it
- Create a test ticket and fill in the start date
- Wait a few seconds, then reload the ticket
- Check the expiration date field
The agent interface doesn't always refresh when a webhook updates the ticket, so reload before you decide it failed.
Is there a supported way to do this without a webhook?
Zendesk's own answer to the webhook question points to action builder and ZIS flows instead. Action builder is the one most admins can use without a developer.
According to Zendesk's action builder overview, action flows are available on Suite Growth, Professional, Enterprise and Enterprise Plus, and on Support Team, Professional and Enterprise. An account can have up to 100 flows of up to 60 steps each, and flows can update all custom ticket fields.
The date arithmetic goes in a custom code step: JavaScript that takes an inputs object (the start date) and returns an outputs object (the expiration date), which the next step writes to the ticket. The code has to be synchronous, with no network requests or library imports, and can be up to 10,000 characters. Adding days to a date fits comfortably inside those limits, and Zendesk supports the result.
A marketplace app or external middleware such as Zapier can also do it, at extra cost, and some teams keep the dates in a spreadsheet synced over the API.
What goes wrong, and how do you fix it?
The expiration date field isn't updating
- Check the field IDs. A wrong ID is the most common mistake.
- Check authentication. The username must end in
/token. - Read the webhook activity log. Open the webhook and look at recent invocations for errors.
- Validate the JSON. Paste the body into a JSON validator.
- Check the trigger conditions. Make sure the ticket actually meets them.
The webhook fires more than once
Use the condition Tags: Does not contain expiration_calculated together with the action Add tags: expiration_calculated.
The date comes out in the wrong format
Zendesk date fields take YYYY-MM-DD. The last filter must be date: '%Y-%m-%d'.
The date is off by a day
Zendesk's custom field documentation says "Custom date fields used in business rules or views always reference GMT time and not the account timezone." Keep that in mind for accounts far from GMT and for deadlines that fall near midnight.
What else can you do with calculated dates?
Set several dates in one call
One webhook call can update several fields:
json
{
"ticket": {
"custom_fields": [
{
"id": FIRST_FOLLOWUP_DATE_ID,
"value": "{{ ticket.ticket_field_START_DATE_ID | date: '%s' | plus: 604800 | date: '%Y-%m-%d' }}"
},
{
"id": SECOND_FOLLOWUP_DATE_ID,
"value": "{{ ticket.ticket_field_START_DATE_ID | date: '%s' | plus: 1209600 | date: '%Y-%m-%d' }}"
},
{
"id": FINAL_EXPIRATION_DATE_ID,
"value": "{{ ticket.ticket_field_START_DATE_ID | date: '%s' | plus: 2592000 | date: '%Y-%m-%d' }}"
}
]
}
}
That sets follow-up dates 7, 14 and 30 days after the start date.
Use different periods for different ticket types
Liquid conditions let the period depend on another field:
json
{
"ticket": {
"custom_fields": [
{
"id": EXPIRATION_DATE_ID,
"value": "{% if ticket.ticket_field_WARRANTY_TYPE == 'standard' %}{{ ticket.ticket_field_START_DATE | date: '%s' | plus: 2592000 | date: '%Y-%m-%d' }}{% elsif ticket.ticket_field_WARRANTY_TYPE == 'premium' %}{{ ticket.ticket_field_START_DATE | date: '%s' | plus: 7776000 | date: '%Y-%m-%d' }}{% endif %}"
}
]
}
}
Standard warranties get 30 days and premium warranties 90.
Send reminders before the date
Once the expiration date exists, automations can act on it. Zendesk documents that "Is within the next" takes a whole number of days, each counted as 24 hours, so "Is within the next | 3" means the next 72 hours.
- 30-day reminder:
- Condition:
Warranty Expiration Date | Is within the next | 30 - Action: email the customer about the upcoming expiration
- Condition:
- 7-day reminder:
- Condition:
Warranty Expiration Date | Is within the next | 7 - Action: send an urgent email and assign to the renewal team
- Condition:
Add a tag in each automation's actions and a "does not contain" condition for it, or the reminder will send every hour the condition stays true.
What should you set up to keep it reliable?
- Name fields precisely. "Warranty Start Date" beats "Start Date"; "Warranty Expiration Date" beats "End Date".
- Make the start date required on the ticket forms where the calculation matters, so it always runs.
- Document the setup. Zendesk won't troubleshoot the webhook route, so write down which fields are calculated, the formula and the expected result.
- Test in a sandbox first, or with test tickets, including tickets another trigger updates at the same time.
- Build views such as "Warranties expiring this month" and "Trials ending this week".
- Check the webhook activity log regularly to catch failed calls early.
What are the limits of the webhook approach?
- Delay: the update can take a few seconds to appear.
- No business days: adding seconds ignores weekends and holidays.
- GMT: date fields in business rules use GMT, not your account time zone.
- API rate limits: each ticket costs an API call, which adds up at high volume.
- No vendor support: Zendesk calls the trigger-and-webhook pattern unsupported, so fixes are on you.
If you're setting this up for the first time, start with the webhook recipe to prove the dates are right, then move the logic into an action flow once you know what you want. If the calculation is critical, go straight to the action flow.
Add AI agents to your Zendesk
Macha reads the ticket, drafts the reply and takes the action, inside the Zendesk you already run.
Intercom
Shopify
Stripe
Slack
Notion
Google Workspace
Confluence

