Associate a Contract and Service to an Autotask Ticket
Tickets without the right contract and service can require billing cleanup or send time entries to the wrong place. If your Autotask process depends on those associations, Email2AT can find them before it creates the ticket.
This tutorial adds that optional lookup chain to an existing ticket rule.
Overview
Autotask uses three related entities for contract/service association:
| Entity | What it is |
|---|---|
| Contract | A billing agreement with a customer (for example, a Managed Services contract) |
| Service | A type of work (for example, "Help Desk" or "Hardware - Desktop") |
| ContractService | The join record that links a specific Service to a specific Contract. This is what the ticket actually references. |
When you manually create a ticket in the Autotask UI and select a contract, then select a service, Autotask resolves the ContractService join record behind the scenes. When creating tickets via the API, you must resolve it yourself.
The workflow to resolve the ContractService ID is:
- Find the Account
- Find the Contract on that Account
- Find the Service by name
- Find the ContractService record that links the Contract to the Service
- Create the ticket with the Account ID, Contract ID, and ContractService ID
Related pages:
When to Use This
Use this pattern when:
- Your Autotask instance requires a contract and service on tickets for billing
- You want time entries on tickets to automatically apply to the correct contract
- You have standardized contract structures across your customers (for example, every customer has a "Managed Service" contract with a "Help Desk" service)
If your Autotask instance does not use contract/service associations on tickets, you do not need this.
Step-by-Step Workflow
This tutorial assumes you already have a rule that creates tickets (for example, from the Create Your First Mailbox tutorial). The steps below are inserted before the ticket creation step.
Action 1: Query for the Account
If your workflow already has the Account ID (for example, from the Create Autotask Ticket workflow action), you can skip this step.
- Click Add New Action, select API: Query for One Object, click OK
- Name the step
Find Account - Set Entity Type to
Account - Add query conditions as appropriate (for example, by account name or by contact lookup). See Identify the Customer for account-name, UDF, and fallback choices.
- In Store results in variable, enter
account
Action 2: Query for the Contract
- Click Add New Action, select API: Query for One Object, click OK
- Name the step
Find Contract - Set Entity Type to
Contract - Set Only perform this action if:
custom.account.idis not empty - Add query conditions:
AccountIDequals{{custom.account.id}}StatusequalsActive(or1, depending on your Autotask)- Optionally filter by contract category (for example,
ContractCategoryequalsManaged Service)
- In Store results in variable, enter
contract
Type { in a query value field to open the variable picker and select a value such as {{custom.account.id}}.
Action 3: Query for the Service
- Click Add New Action, select API: Query for One Object, click OK
- Name the step
Find Service - Set Entity Type to
Service - Set Only perform this action if:
custom.contract.idis not empty - Add query conditions:
ServiceNameequals the name of the service you want (for example,Help Desk)
- In Store results in variable, enter
service
If you always use the same service, you can skip this query and hard-code the service ID directly in the next step. Query the service by name if it varies by customer or if you want the workflow to adapt automatically.
Action 4: Query for the ContractService
This is the join record that links the Contract to the Service.
- Click Add New Action, select API: Query for One Object, click OK
- Name the step
Find ContractService - Set Entity Type to
ContractService - Set Only perform this action if:
custom.service.idis not empty - Add query conditions:
ContractIDequals{{custom.contract.id}}ServiceIDequals{{custom.service.id}}
- In Store results in variable, enter
contractService
Action 5: Create the Ticket
- Click Add New Action, select API: Create an Object, click OK
- Name the step
Create Ticket with Contract - Set Entity Type to
Ticket - Set Only perform this action if:
custom.contractService.idis not empty - Configure the required ticket fields, plus:
| Field | Value |
|---|---|
| AccountID | {{custom.account.id}} (unlock the field) |
| ContractID | {{custom.contract.id}} (unlock the field) |
| ContractServiceID | {{custom.contractService.id}} (unlock the field) |
| Status | New |
| Priority | Set as appropriate |
| QueueID | Your support queue |
| Title | {{email.subject}} |
| Description | {{email.body}} |
The ID fields start as picklists for fixed Autotask records. Unlock them so you can enter variables and use the Account, Contract, and ContractService found by the earlier actions.
Autotask rejects ticket creation if the Contract ID does not belong to the Account on the ticket. The query chain above ensures this by filtering the Contract by Account ID.
What happens now
- The automation finds the customer Account.
- It finds an active Contract on that Account and the Service you selected.
- It finds the ContractService that connects them.
- It creates the ticket with all three IDs, so Autotask associates the correct contract and service from the start.
Handling Missing Data
First decide how your team wants to handle missing data:
| Missing data | Choice | Tradeoff |
|---|---|---|
| Account | Stop with an exception, or create on a dedicated default account or the zero Account | Stopping avoids a ticket on the wrong customer but requires someone to fix and replay the email. A fallback account keeps email moving but requires manual reassignment. |
| Contract, Service, or ContractService | Stop with an exception, or create the ticket without contract association | Stopping protects billing requirements but delays the ticket. Creating without the association avoids delay but may require billing cleanup. |
To use a fallback Account, leave the first lookup's no-results exception disabled. Add a second Account lookup that finds your dedicated default account or zero Account, stores it in account, and has Only perform this action if set to custom.account.id is empty.
To stop, enable Generate an exception if no results on each lookup that your process requires. To create the ticket without contract association, keep the lookup exceptions disabled and add this fallback action:
- Add another API: Create an Object (Ticket) step after the contract-associated version
- Set Only perform this action if:
custom.contractService.idis empty ANDcustom.account.idis not empty - Configure the same ticket fields but omit ContractID and ContractServiceID
This version creates a ticket whenever it finds the Account, even when it cannot complete the contract association.
Key Takeaways
- ContractService is the join record: the ticket references ContractService, not Service directly
- Four queries to resolve the chain: Account → Contract → Service → ContractService
- Guard every step: if any query returns empty, skip downstream steps and fall back to a ticket without contract
- Contract must match the account: Autotask rejects tickets where the contract does not belong to the ticket's account
- This is optional: only use this pattern if your Autotask instance requires or benefits from contract/service on tickets
Related Documentation
- API: Query for One Object: querying Autotask for a single result
- API: Create an Object: creating any Autotask entity
- Core Concepts: how rules, actions, and variables work together
- Create Your First Mailbox: the starting point for a basic ticket workflow