From hudu
Manages Hudu companies (clients/organizations): create, search, update, archive; covers fields, PSA integrations, parent/child hierarchies, and related assets/passwords/articles.
How this skill is triggered — by the user, by Claude, or both
Slash command
/hudu:companiesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Companies are the foundational entity in Hudu, representing clients, vendors, or internal entities. All documentation, assets, passwords, articles, and websites are associated with a company. In Hudu, the "Company" label is customizable per instance -- some MSPs rename it to "Organization" or "Client" -- but the API endpoint is always `/api/v1/companies`.
Companies are the foundational entity in Hudu, representing clients, vendors, or internal entities. All documentation, assets, passwords, articles, and websites are associated with a company. In Hudu, the "Company" label is customizable per instance -- some MSPs rename it to "Organization" or "Client" -- but the API endpoint is always /api/v1/companies.
Unlike IT Glue, Hudu does not enforce built-in company types. Companies are typically organized using custom fields or naming conventions. Common patterns MSPs use:
| Pattern | Description | Example |
|---|---|---|
| Active Client | Currently serviced customer | Standard operational state |
| Prospect | Potential client | Pre-sales documentation |
| Vendor | Product/service supplier | Software vendors |
| Internal | Your own MSP | Internal documentation |
| Former Client | Previously serviced | Historical records |
Companies can have parent/child relationships for multi-location or multi-division clients:
Parent Company (Acme Holdings)
+-- Child: Acme East Division
+-- Child: Acme West Division
+-- Child: Acme International
Companies can be matched to PSA records using the id_in_integration and integration_slug fields, enabling cross-platform lookups between Hudu and tools like ConnectWise Manage, Autotask, or HaloPSA.
| Field | Type | Required | Description |
|---|---|---|---|
id | integer | System | Auto-generated unique identifier |
name | string | Yes | Company name |
nickname | string | No | Short name or abbreviation |
company_type | string | No | Type classification |
address_line_1 | string | No | Street address line 1 |
address_line_2 | string | No | Street address line 2 |
city | string | No | City |
state | string | No | State/province |
zip | string | No | Postal code |
country_name | string | No | Country |
phone_number | string | No | Phone number |
fax_number | string | No | Fax number |
website | string | No | Company website URL |
notes | string | No | Rich text notes |
| Field | Type | Description |
|---|---|---|
id_in_integration | integer | PSA system company ID |
integration_slug | string | PSA integration identifier |
| Field | Type | Description |
|---|---|---|
parent_company_id | integer | Parent company ID |
parent_company_name | string | Parent company name (read-only) |
| Field | Type | Description |
|---|---|---|
created_at | datetime | Creation timestamp |
updated_at | datetime | Last update timestamp |
slug | string | URL-friendly identifier |
object_type | string | Always "Company" |
GET /api/v1/companies
x-api-key: YOUR_API_KEY
Content-Type: application/json
With Filters:
GET /api/v1/companies?name=Acme
GET /api/v1/companies?city=Springfield
GET /api/v1/companies?state=IL
GET /api/v1/companies?id_in_integration=12345
GET /api/v1/companies?search=acme
With Pagination:
GET /api/v1/companies?page=1
GET /api/v1/companies?page=2
GET /api/v1/companies/123
x-api-key: YOUR_API_KEY
POST /api/v1/companies
Content-Type: application/json
x-api-key: YOUR_API_KEY
{
"company": {
"name": "New Client Corporation",
"nickname": "NCC",
"company_type": "Customer",
"address_line_1": "123 Main Street",
"city": "Portland",
"state": "OR",
"zip": "97201",
"phone_number": "555-123-4567",
"website": "https://newclient.com",
"notes": "Onboarded February 2026. Primary contact: John Smith."
}
}
PUT /api/v1/companies/123
Content-Type: application/json
x-api-key: YOUR_API_KEY
{
"company": {
"nickname": "NCC-UPDATED",
"notes": "Updated: New primary contact is Jane Doe (555-987-6543)."
}
}
DELETE /api/v1/companies/123
x-api-key: YOUR_API_KEY
Warning: Deleting a company removes all associated resources (assets, passwords, articles, etc.). Requires DELETE permission on the API key.
PUT /api/v1/companies/123/archive
x-api-key: YOUR_API_KEY
PUT /api/v1/companies/123/unarchive
x-api-key: YOUR_API_KEY
GET /api/v1/companies?id_in_integration=12345
async function onboardClient(clientData) {
// Step 1: Create company
const company = await createCompany({
name: clientData.companyName,
nickname: clientData.nickname,
company_type: 'Customer',
address_line_1: clientData.address,
city: clientData.city,
state: clientData.state,
zip: clientData.zip,
phone_number: clientData.phone,
website: clientData.website,
notes: `Onboarded: ${new Date().toLocaleDateString()}\nPrimary contact: ${clientData.primaryContact}`
});
// Step 2: Link to PSA
if (clientData.psaId) {
await updateCompany(company.id, {
id_in_integration: clientData.psaId
});
}
return company;
}
async function offboardClient(companyId, reason) {
// Add offboarding notes
await updateCompany(companyId, {
notes: `ARCHIVED: ${new Date().toLocaleDateString()} - ${reason}`
});
// Archive the company
await archiveCompany(companyId);
}
async function verifyPsaSync() {
const companies = await fetchAllCompanies();
const syncStatus = {
synced: [],
unsynced: [],
mismatched: []
};
for (const company of companies) {
if (!company.id_in_integration) {
syncStatus.unsynced.push(company);
} else {
const psaCompany = await lookupPsaCompany(company.id_in_integration);
if (psaCompany) {
syncStatus.synced.push(company);
} else {
syncStatus.mismatched.push(company);
}
}
}
return syncStatus;
}
async function generateCompanyReport() {
const companies = await fetchAllCompanies();
return companies.map(company => ({
name: company.name,
nickname: company.nickname,
city: company.city,
state: company.state,
psaSynced: !!company.id_in_integration,
hasWebsite: !!company.website,
createdAt: company.created_at,
updatedAt: company.updated_at
}));
}
| Code | Message | Resolution |
|---|---|---|
| 400 | Name can't be blank | Provide company name |
| 400 | Name has already been taken | Use unique name |
| 401 | Invalid API key | Check HUDU_API_KEY |
| 404 | Company not found | Verify company ID and HUDU_BASE_URL |
| 422 | Validation failed | Check required fields |
| Error | Cause | Fix |
|---|---|---|
| Name required | Missing name field | Add name to request body |
| Name not unique | Duplicate company name | Use a different name |
| Invalid parent ID | Non-existent parent company | Verify parent_company_id |
async function safeCreateCompany(data) {
try {
return await createCompany(data);
} catch (error) {
if (error.status === 422 && error.message?.includes('already been taken')) {
// Company exists - find and return it
const existing = await findCompanyByName(data.name);
return existing;
}
if (error.status === 401) {
throw new Error('API key invalid or expired. Check HUDU_API_KEY.');
}
throw error;
}
}
id_in_integration for cross-platform lookupsnpx claudepluginhub wyre-technology/msp-claude-plugins --plugin huduManages ConnectWise PSA company records via API: create, update, search; handle types, statuses, sites/locations, custom fields, relationships.
Guides management of Autotask CRM entities: companies, contacts, sites/locations, and opportunities. Useful for MSP account management, client onboarding, and REST API usage.
Manages IT Glue organizations: create, search, update, and handle client documentation including types, statuses, parent/child relationships, PSA sync, quick notes, and related configs, contacts, passwords.