Freshdesk contacts and companies: contact fields and the required contact-channel rule, contact CRUD plus merge and make_agent, company fields and domain-based auto-association, search and autocomplete lookups, and the MSP workflow of resolving a ticket requester to a contact and then to its parent company through the Freshdesk REST API v2.
Scanned 9/5/2026
Install to Claude Code
npx -y skills add WYRE-AI/msp-claude-plugins --skill contacts-companies --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Contacts Companies?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/wyre-ai-contacts-companies)More formats (shields.io, HTML) on the badges page.
---
name: "Freshdesk Contacts & Companies"
description: >
Freshdesk contacts and companies: contact fields and the required
contact-channel rule, contact CRUD plus merge and make_agent, company fields
and domain-based auto-association, search and autocomplete lookups, and the
MSP workflow of resolving a ticket requester to a contact and then to its
parent company through the Freshdesk REST API v2.
when_to_use: >-
When working with Freshdesk contacts and companies — looking up, creating, updating, merging, or
converting them, and resolving a ticket requester to a contact and company. Use when: freshdesk
contact, freshdesk company, freshdesk requester, merge contact freshdesk, make agent freshdesk,
search contacts freshdesk, resolve requester freshdesk, or freshdesk customer.
---
# Freshdesk Contacts & Companies
## Overview
In Freshdesk, **contacts** are the people who raise tickets (requesters) and
**companies** group those contacts into the organizations an MSP serves.
Resolving a ticket's requester to a contact, and that contact to its company,
is the foundation for account-level context, SLA association, and reporting.
This skill covers contact and company operations through tools named
`freshdesk_contacts_<action>` and `freshdesk_companies_<action>`.
## Anti-triggers
In Freshdesk a **contact** is a customer who raises tickets; an **agent**
is your own helpdesk staff. `freshdesk_contacts_make_agent` crosses that
line permanently — it consumes a licensed seat and grants access to every
ticket in the account, so it is not a labelling change.
- **Technician rosters and team capacity** — this skill only converts a
contact *into* an agent. For looking up who your technicians are and
which teams they sit in, the PSA carries the richer model; use
`halopsa-agents`.
- **The same customer in another system** — a HaloPSA client, a
ConnectWise company, or an Autotask company is a different record with
different required fields; use `halopsa-clients`,
`connectwise-psa-companies`, or `autotask-crm`. Do not
assume IDs or domains map across.
- **Assets, sites, or contracts belonging to the customer** — Freshdesk
companies carry no CMDB or billing model; use `halopsa-assets` and
`halopsa-contracts`.
- **Anything about the customer's tickets** — listing, replying, or
triaging is `freshdesk-ticketing`; this skill resolves who the
requester is.
## Contacts
### Key Contact Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | Integer | System | Auto-generated unique identifier |
| `name` | String | Yes | Full name |
| `email` | String | One of email/phone/mobile | Primary email |
| `phone` | String | One of email/phone/mobile | Landline |
| `mobile` | String | One of email/phone/mobile | Mobile number |
| `company_id` | Integer | No | Associated company |
| `job_title` | String | No | Role at the company |
| `tags` | Array | No | Free-form labels |
A contact must have at least one of `email`, `phone`, `mobile`, `twitter_id`,
or `unique_external_id`.
### Contact Operations
| Action | Endpoint | Notes |
|--------|----------|-------|
| List | `GET /api/v2/contacts` | Filter with `email`, `mobile`, `phone`, `company_id`, `updated_since` |
| Get | `GET /api/v2/contacts/{id}` | Single contact |
| Search | `GET /api/v2/search/contacts?query="..."` | Query language; 300-result cap |
| Create | `POST /api/v2/contacts` | `name` + one contact channel required |
| Update | `PUT /api/v2/contacts/{id}` | Partial update |
| Merge | `POST /api/v2/contacts/merge` | Combine duplicates into a primary |
| Make agent | `PUT /api/v2/contacts/{id}/make_agent` | Convert a contact into an agent |
### Create a Contact
```json
{
"name": "John Smith",
"email": "john.smith@acme.com",
"company_id": 5001,
"job_title": "Office Manager"
}
```
### Search Contacts
```http
GET /api/v2/search/contacts?query="email:'john.smith@acme.com'"
```
The query language wraps the expression in double quotes and quotes string
values. Search returns up to 30 results per page and a maximum of 10 pages
(300 records).
### Merge Duplicate Contacts
```http
POST /api/v2/contacts/merge
```
```json
{
"primary_contact_id": 1001,
"secondary_contact_ids": [1002, 1003]
}
```
Tickets and history from the secondary contacts are re-pointed at the primary.
Confirm which record should be primary before merging — merges are not easily
reversible.
### Make a Contact an Agent
```http
PUT /api/v2/contacts/{id}/make_agent
```
Converts a customer contact into a Freshdesk agent. This is a privileged,
billing-affecting change — flag it explicitly before invoking.
## Companies
### Key Company Fields
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `id` | Integer | System | Auto-generated unique identifier |
| `name` | String | Yes | Company name (unique) |
| `domains` | Array | No | Email domains used to auto-associate contacts |
| `description` | String | No | Notes about the company |
| `note` | String | No | Internal note |
| `health_score` | String | No | Account health indicator |
| `account_tier` | String | No | Service tier |
### Company Operations
| Action | Endpoint | Notes |
|--------|----------|-------|
| List | `GET /api/v2/companies` | Paginated with `page` / `per_page` |
| Get | `GET /api/v2/companies/{id}` | Single company |
| Search | `GET /api/v2/search/companies?query="..."` | Query language; 300-result cap |
| Create | `POST /api/v2/companies` | `name` required and unique |
| Update | `PUT /api/v2/companies/{id}` | Partial update |
### Search Companies
```http
GET /api/v2/search/companies?query="name:'Acme'"
```
You can also locate a company by an autocomplete-style name lookup:
```http
GET /api/v2/companies/autocomplete?name=Acme
```
## Resolving Requester -> Contact -> Company
A core MSP workflow is enriching a ticket with full account context:
1. **Start from the ticket** — a ticket carries `requester_id` and, when set,
`company_id`. Read the ticket first.
2. **Resolve the contact** — `GET /api/v2/contacts/{requester_id}` (or search
by `email` if you only have an address). This yields the contact's
`company_id`, `job_title`, and contact channels.
3. **Resolve the company** — `GET /api/v2/companies/{company_id}` for the
organization's `domains`, `account_tier`, and `health_score`.
4. **Use domains to disambiguate** — if a contact has no `company_id`, match
the email domain against company `domains` to infer the right account.
5. **Cache reference data** — companies and frequent contacts change rarely;
cache lookups within a session to stay under the per-minute rate limit.
```text
Ticket #4821
requester_id: 1001 -> Contact "John Smith" (john.smith@acme.com)
company_id: 5001
-> Company "Acme Corporation"
domains: ["acme.com"], tier: "Gold"
```
## Error Handling
| Error | Cause | Resolution |
|-------|-------|------------|
| 400 Validation failed | Missing name or contact channel; duplicate company name | Supply required fields; pick a unique company name |
| 404 Not found | Unknown contact/company ID | Re-list or re-search to confirm |
| 409 Conflict | Email/company already exists | Search for and reuse the existing record |
| 403 Forbidden | API key lacks scope | Check agent permissions (especially for make_agent) |
## Best Practices
- **Search before creating** — avoid duplicate contacts by checking `email`
first; let ticket creation auto-create only when intentional.
- **Maintain company domains** — accurate `domains` let Freshdesk
auto-associate new contacts to the right company.
## Related Skills
- [Freshdesk Ticketing](../ticketing/SKILL.md) - Tickets reference requesters and companies
- [Freshdesk API Patterns](../api-patterns/SKILL.md) - Search query language and pagination
- [Freshdesk SLA & Business Hours](../sla-business-hours/SKILL.md) - Company/tier-driven SLA association
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!