node-autotask 0.43.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/MCP_TOOL_CATALOG.json +156 -1253
  3. package/MCP_TOOL_MANIFEST.md +154 -220
  4. package/MCP_TOOL_OVERRIDES.json +8 -62
  5. package/N8N_MCP_MANIFEST.json +128 -705
  6. package/N8N_MCP_MANIFEST.md +43 -63
  7. package/README.md +10 -28
  8. package/capabilities.json +15315 -22219
  9. package/dist/{base-CVx2VMSj.d.cts → base-BVoYDlVA.d.cts} +2 -1
  10. package/dist/{base-CVx2VMSj.d.ts → base-BVoYDlVA.d.ts} +2 -1
  11. package/dist/capabilities.cjs +2 -2
  12. package/dist/capabilities.d.cts +2 -1
  13. package/dist/capabilities.d.ts +2 -1
  14. package/dist/capabilities.js +1 -1
  15. package/dist/{chunk-5VHSLJMR.js → chunk-A6LHCJQP.js} +30 -9
  16. package/dist/{chunk-JY2BWYXY.js → chunk-ASMCTZO2.js} +15314 -22218
  17. package/dist/{chunk-TH7B5H4P.cjs → chunk-DC3PY4EF.cjs} +1839 -1407
  18. package/dist/{chunk-4EFXIE53.js → chunk-DXKXQHCX.js} +5 -5
  19. package/dist/{chunk-SK3GYRNA.cjs → chunk-JO6WI763.cjs} +143 -143
  20. package/dist/{chunk-Q23JULNN.js → chunk-NSW7JPVS.js} +11529 -13319
  21. package/dist/{chunk-KTEDPS4X.js → chunk-O4PIPUS4.js} +1583 -1151
  22. package/dist/{chunk-MJTKK3QG.cjs → chunk-SN4BMQ2N.cjs} +31 -10
  23. package/dist/{chunk-5BDUMDAQ.cjs → chunk-VXVYFJH3.cjs} +15314 -22218
  24. package/dist/{chunk-VFLAMMIJ.cjs → chunk-YMBVKVK4.cjs} +10604 -12394
  25. package/dist/{index-C7rMJ4IV.d.ts → index-C5g1H_hF.d.ts} +1080 -1288
  26. package/dist/{index-Cm_Xpt7X.d.cts → index-Db0SNnQn.d.cts} +1080 -1288
  27. package/dist/{index-C3KFMnRT.d.cts → index-c549LvOb.d.cts} +332 -331
  28. package/dist/{index-C3KFMnRT.d.ts → index-c549LvOb.d.ts} +332 -331
  29. package/dist/index.cjs +23 -23
  30. package/dist/index.d.cts +15 -41
  31. package/dist/index.d.ts +15 -41
  32. package/dist/index.js +8 -8
  33. package/dist/operations/index.cjs +5 -2234
  34. package/dist/operations/index.d.cts +51 -323
  35. package/dist/operations/index.d.ts +51 -323
  36. package/dist/operations/index.js +30 -2259
  37. package/dist/pool.cjs +9 -9
  38. package/dist/pool.d.cts +4 -3
  39. package/dist/pool.d.ts +4 -3
  40. package/dist/pool.js +5 -5
  41. package/dist/resources/index.cjs +5 -5
  42. package/dist/resources/index.d.cts +2 -2
  43. package/dist/resources/index.d.ts +2 -2
  44. package/dist/resources/index.js +8 -8
  45. package/dist/types/index.d.cts +1 -1
  46. package/dist/types/index.d.ts +1 -1
  47. package/dist/untrusted.cjs +2 -2
  48. package/dist/untrusted.d.cts +14 -5
  49. package/dist/untrusted.d.ts +14 -5
  50. package/dist/untrusted.js +1 -1
  51. package/docs/API.md +321 -334
  52. package/docs/LIVE-TESTING.md +4 -6
  53. package/docs/N8N-ADAPTER.md +26 -26
  54. package/examples/mcp/schemas.ts +2 -0
  55. package/examples/mcp/tools-read.ts +3 -2
  56. package/n8n-mcp.curation.json +3 -3
  57. package/package.json +10 -9
@@ -1,6 +1,6 @@
1
1
  # N8N MCP Manifest — node-autotask (consumer projection)
2
2
 
3
- <!-- GENERATED by scripts/project-n8n-mcp.mjs at 2026-10-31T20:17:42.452Z — do not hand-edit. -->
3
+ <!-- GENERATED by scripts/project-n8n-mcp.mjs at 2026-11-01T10:43:53.479Z — do not hand-edit. -->
4
4
 
5
5
  The n8n CONSUMER projection of the capability registry: the canonical source for what the
6
6
  n8n-side MCP tools must expose. The SDK is canonical — this is a projection of it, never a
@@ -24,23 +24,23 @@ user's n8n instances; PROD is read-only for any verification).
24
24
  | tool | mode | entity | readOnlyHint | destructiveHint | idempotentHint | openWorldHint | operations |
25
25
  |------|------|--------|--------------|-----------------|----------------|---------------|------------|
26
26
  | `autotask_ticket` | read | ticket | true | false | true | true | 17 |
27
- | `autotask_ticket_write` | write | ticket | false | false | false | true | 4 |
28
- | `autotask_contact` | read | contact | true | false | true | true | 10 |
29
- | `autotask_contact_write` | write | contact | false | false | false | true | 4 |
27
+ | `autotask_ticket_write` | write | ticket | false | false | false | true | 3 |
28
+ | `autotask_contact` | read | contact | true | false | true | true | 11 |
29
+ | `autotask_contact_write` | write | contact | false | false | false | true | 3 |
30
30
  | `autotask_company` | read | company | true | false | true | true | 14 |
31
- | `autotask_company_write` | write | company | false | false | false | true | 3 |
31
+ | `autotask_company_write` | write | company | false | false | false | true | 2 |
32
32
  | `autotask_companyLocation` | read | companyLocation | true | false | true | true | 8 |
33
33
  | `autotask_companyLocation_write` | write | companyLocation | false | false | false | true | 2 |
34
34
  | `autotask_ticketNote` | read | ticketNote | true | false | true | true | 7 |
35
35
  | `autotask_ticketNote_write` | write | ticketNote | false | false | false | true | 2 |
36
- | `autotask_resource` | read | resource | true | false | true | true | 9 |
37
- | `autotask_resource_write` | write | resource | false | false | false | true | 2 |
38
- | `autotask_timeEntry` | read | timeEntry | true | false | true | true | 23 |
39
- | `autotask_timeEntry_write` | write | timeEntry | false | false | false | true | 5 |
36
+ | `autotask_resource` | read | resource | true | false | true | true | 10 |
37
+ | `autotask_resource_write` | write | resource | false | false | true | true | 1 |
38
+ | `autotask_timeEntry` | read | timeEntry | true | false | true | true | 8 |
39
+ | `autotask_timeEntry_write` | write | timeEntry | false | false | false | true | 2 |
40
40
 
41
41
  ### `autotask_ticket` (read — ticket)
42
42
 
43
- > Read ticket records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for tickets: count: Count ticket records matching a JSON filter. | findByTicketNumber: Find a ticket by its ticketNumber. | forResource: List the tickets a resource is assigned to — as primary owner, as a secondary resource, or both — de-duplicated, with the four reconciling counts and an optional open-only filter that uses the tenant's own closed-status set. | fullContext: Get the full context of one ticket in a single call: the ticket, its company, contact, assigned resource and project, plus its notes, time entries, attachment metadata and (opt-in) histories — every part separately reported. | get: Get one Ticket by id. | getContext: Get a ticket with its primary context records in one call. | getEntityInfo: Get the Ticket capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the Ticket field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the Ticket user-defined-field catalog. | lineOfBusiness: Get the full Line of Business chain for one ticket in a single call: the association, the OrganizationalLevel2 (the customizable 'Line of Business' label) and the OrganizationalLevel1 (the division). | query: Query Ticket records with a JSON filter. | resolve: Resolve a Ticket from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (title — exact match only). Returns the Ticket record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). | search: Search ticket records by text (a vendor contains filter on title only — the vendor exposes no free-text search and no matched-field reporting). | slaHealthCheck: Run the SLA health check for a ticket (numeric ticket id). | statusSemantics: Report the ticket status picklist and the ids this SDK treats as CLOSED for the caller's tenant, with the provenance of that set (read from the tenant's picklist, or the documented assumed fallback). | summary: Get a one-call summary of a ticket (numeric ticket id). | timeline: Get the event timeline of a ticket (numeric ticket id).. Bounds: Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. Bounded: limit default 25, max 500. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
43
+ > Read ticket records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for tickets: count: Count ticket records matching a JSON filter. | findByTicketNumber: Find a ticket by its ticketNumber. | forResource: List the tickets a resource is assigned to — as primary owner, as a secondary resource, or both — de-duplicated, with the four reconciling counts and an optional open-only filter that uses the tenant's own closed-status set. | fullContext: Get the full context of one ticket in a single call: the ticket, its company, contact, assigned resource and project, plus its notes, time entries, attachment metadata and (opt-in) histories — every part separately reported. | get: Get one Ticket by id. | getContext: Get a ticket with its primary context records in one call. | getEntityInfo: Get the Ticket capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the Ticket field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the Ticket user-defined-field catalog. | lineOfBusiness: Get the full Line of Business chain for one ticket in a single call: the association, the OrganizationalLevel2 (the customizable 'Line of Business' label) and the OrganizationalLevel1 (the division). | query: Query Ticket records with a JSON filter. | resolve: Resolve a Ticket from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (title — exact match only). Returns the Ticket record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). | search: Search ticket records by text (a vendor contains filter on title only — the vendor exposes no free-text search and no matched-field reporting). | slaHealthCheck: Run the SLA health check for a ticket (numeric ticket id). | statusSemantics: Report the ticket status picklist and the ids this SDK treats as CLOSED for the caller's tenant, with the provenance of that set (read from the tenant's picklist, or the documented assumed fallback). | summary: Get a one-call summary of a ticket (numeric ticket id). | timeline: Get the event timeline of a ticket (numeric ticket id).. Bounds: Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. Bounded: limit default 25, max 500. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
44
44
 
45
45
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
46
46
  |------------------|------|--------|-------|--------------|---------|
@@ -54,7 +54,7 @@ user's n8n instances; PROD is read-only for any verification).
54
54
  | `tickets.getFieldInfo` | getFieldInfo | read | — | none | Get the Ticket field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). |
55
55
  | `tickets.getUdfInfo` | getUdfInfo | read | — | none | Get the Ticket user-defined-field catalog. |
56
56
  | `tickets.lineOfBusiness` | lineOfBusiness | read | — | ticketId | Get the full Line of Business chain for one ticket in a single call: the association, the OrganizationalLevel2 (the customizable 'Line of Business' label) and the OrganizationalLevel1 (the division). |
57
- | `tickets.query` | query | read | — | none | Query Ticket records with a JSON filter. Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. |
57
+ | `tickets.query` | query | read | — | none | Query Ticket records with a JSON filter. Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. |
58
58
  | `tickets.resolve` | resolve | read | — | identifier | Resolve a Ticket from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (title — exact match only). Returns the Ticket record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). |
59
59
  | `tickets.search` | search | read | — | query | Search ticket records by text (a vendor contains filter on title only — the vendor exposes no free-text search and no matched-field reporting). Bounded: limit default 25, max 500. |
60
60
  | `tickets.slaHealthCheck` | slaHealthCheck | read | — | id | Run the SLA health check for a ticket (numeric ticket id). |
@@ -64,50 +64,49 @@ user's n8n instances; PROD is read-only for any verification).
64
64
 
65
65
  ### `autotask_ticket_write` (write — ticket)
66
66
 
67
- > Write ticket records (mode: write — the registry operations with effect=write for tickets: changeStatus, create, openWithNoteAndAssign, update). Writes are dry-run first: dry_run defaults to true — the request is validated against the registry inputSchema and a DryRunResult envelope is returned; the mutating request is never issued unless the caller passes confirm (the n8n-side handler must force dry-run unless confirm is present, mirroring the SDK governor). Destructive operations are refused without the confirm flag — confirm must equal the operation key exactly (the deliberate act is the call). The n8n consumer surface excludes destructive operations by curation default (excludeDestructive); they remain available on the canonical SDK server (autotask_delete / per-op tools). By curation default (excludeDestructive) no destructive operation is included; destructive capability remains on the canonical SDK server surface. Per-operation required arguments: changeStatus [id, targetStatus]; create [data]; openWithNoteAndAssign [params]; update [id, data]. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
67
+ > Write ticket records (mode: write — the registry operations with effect=write for tickets: changeStatus, create, update). Writes are dry-run first: dry_run defaults to true — the request is validated against the registry inputSchema and a DryRunResult envelope is returned; the mutating request is never issued unless the caller passes confirm (the n8n-side handler must force dry-run unless confirm is present, mirroring the SDK governor). Destructive operations are refused without the confirm flag — confirm must equal the operation key exactly (the deliberate act is the call). The n8n consumer surface excludes destructive operations by curation default (excludeDestructive); they remain available on the canonical SDK server (autotask_delete / per-op tools). By curation default (excludeDestructive) no destructive operation is included; destructive capability remains on the canonical SDK server surface. Per-operation required arguments: changeStatus [id, targetStatus]; create [data]; update [id, data]. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
68
68
 
69
- Tool input: {"operation":{"type":"string","enum":["changeStatus","create","openWithNoteAndAssign","update"]},"id":{"type":"number | string (the ticket id — a safe integer, or a canonical integer string for ids above 2^53)"},"targetStatus":{"type":"number (validated pre-request against the tenant's LIVE status picklist from the entity metadata when it is resolvable — a value the live picklist lacks → typed STATUS_UNKNOWN; when the metadata is unavailable the vendor's own validation decides)"},"fields":{"type":"object (optional) — extra ticket fields merged into the same PUT (the caller value wins over the node map defaults; the merge keeps every other current field)"},"data":{"type":"object","ref":"tickets body (see types)"},"params":{"type":"object — { companyID: number | string (the parent company id), title: string, priority?: number (default 3 Low), status?: number (default 1 New), queueID?: number (the node NEVER guesses a queue: omitted + vendor-500 → the typed QUEUE_REQUIRED error with the vendor message + discovery suggestedAction) }"},"note":{"type":"object (optional) — { description: string, title?: string, noteType?: number (default 1), publish?: number (default 1; integer picklist 1/2/4 — a JSON boolean 500s) }"},"assign":{"type":"object (optional) — { resourceID: number | string, roleID: number (required with resourceID) } (prechecked via resources.get BEFORE the create — RESOURCE_INVALID on missing/inactive; the resources table is blind to the API user, get is the authority)"},"dry_run":{"type":"boolean","default":true,"note":"true (the default) = the pinned DryRunResult envelope; the mutating request is never issued. The handler must force dry-run unless confirm is present."},"confirm":{"type":"string","note":"The operation key (e.g. \"tickets.create\") — its presence lifts the dry run. For destructive/approval-gated operations confirm must equal the operation key exactly; the call is refused pre-request without it."}} (required: operation)
69
+ Tool input: {"operation":{"type":"string","enum":["changeStatus","create","update"]},"id":{"type":"number | string (the ticket id — a safe integer, or a canonical integer string for ids above 2^53)"},"targetStatus":{"type":"number (validated pre-request against the tenant's LIVE status picklist from the entity metadata when it is resolvable — a value the live picklist lacks → typed STATUS_UNKNOWN; when the metadata is unavailable the vendor's own validation decides)"},"fields":{"type":"object (optional) — extra ticket fields merged into the same PUT (the caller value wins over the node map defaults; the merge keeps every other current field)"},"data":{"type":"object","ref":"tickets body (see types)"},"dry_run":{"type":"boolean","default":true,"note":"true (the default) = the pinned DryRunResult envelope; the mutating request is never issued. The handler must force dry-run unless confirm is present."},"confirm":{"type":"string","note":"The operation key (e.g. \"tickets.create\") — its presence lifts the dry run. For destructive/approval-gated operations confirm must equal the operation key exactly; the call is refused pre-request without it."}} (required: operation)
70
70
 
71
71
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
72
72
  |------------------|------|--------|-------|--------------|---------|
73
73
  | `tickets.changeStatus` | changeStatus | write | — | id, targetStatus | Move a ticket to a target status in ONE op — the node validates targetStatus against the tenant's LIVE status picklist (entity metadata; vendor rejection is the fallback when the metadata is unavailable) + the live-discovered per-status required-field map and fills the proven-safe defaults itself (the vendor 500s when a target status has unsatisfied field requirements; the MCP LLM has no way to know the map). Dry-run first (dry_run). |
74
74
  | `tickets.create` | create | write | — | data | Create a ticket. Dry-run first (dry_run). |
75
- | `tickets.openWithNoteAndAssign` | openWithNoteAndAssign | write | — | params | Open a ticket with an optional first scoped note and an optional assignment in ONE op — the node absorbs the ww29-proven create contract and the note/assignment wire choreography (6 calls today → 1). Dry-run first (dry_run). |
76
75
  | `tickets.update` | update | write | idempotent | id, data | Update a ticket. Dry-run first (dry_run). Idempotent. |
77
76
 
78
77
  ### `autotask_contact` (read — contact)
79
78
 
80
- > Read contact records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for contacts: count: Count contact records matching a JSON filter. (under a company) | findByEmail: Find a contact by email address. | get: Get one Contact by id. | getContext: Get a contact with its primary context records in one call. (under a company) | getEntityInfo: Get the Contact capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the Contact field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the Contact user-defined-field catalog. | query: Query Contact records with a JSON filter. | resolve: Resolve a Contact from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (firstName + lastName — exact match only). Returns the Contact record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). | search: Search contact records by text (contains on the searchable fields). (under a company). Bounds: Sensitive. Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. Sensitive. Bounded: limit default 25, max 500. Sensitive. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
79
+ > Read contact records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for contacts: count: Count contact records matching a JSON filter. (under a company) | findByEmail: Find a contact by email address. | fullProfile: Get a contact with its company and its open tickets in a single call: the contact (the parent-scoped root read, or the stage-1 row when the contact has no company FK), its company, and its open tickets — every part separately reported. | get: Get one Contact by id. | getContext: Get a contact with its primary context records in one call. (under a company) | getEntityInfo: Get the Contact capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the Contact field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the Contact user-defined-field catalog. | query: Query Contact records with a JSON filter. | resolve: Resolve a Contact from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (firstName + lastName — exact match only). Returns the Contact record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). | search: Search contact records by text (contains on the searchable fields). (under a company). Bounds: Sensitive. Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. Sensitive. Bounded: limit default 25, max 500. Sensitive. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
81
80
 
82
81
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
83
82
  |------------------|------|--------|-------|--------------|---------|
84
83
  | `contacts.count` | count | read | sensitive | none | Count contact records matching a JSON filter. (under a company) Sensitive. |
85
84
  | `contacts.findByEmail` | findByEmail | read | sensitive | value | Find a contact by email address. Sensitive. |
85
+ | `contacts.fullProfile` | fullProfile | read | — | id | Get a contact with its company and its open tickets in a single call: the contact (the parent-scoped root read, or the stage-1 row when the contact has no company FK), its company, and its open tickets — every part separately reported. |
86
86
  | `contacts.get` | get | read | sensitive | parentId, id | Get one Contact by id. Sensitive. |
87
87
  | `contacts.getContext` | getContext | read | sensitive | id | Get a contact with its primary context records in one call. (under a company) Sensitive. |
88
88
  | `contacts.getEntityInfo` | getEntityInfo | read | sensitive | none | Get the Contact capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). Sensitive. |
89
89
  | `contacts.getFieldInfo` | getFieldInfo | read | sensitive | none | Get the Contact field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). Sensitive. |
90
90
  | `contacts.getUdfInfo` | getUdfInfo | read | sensitive | none | Get the Contact user-defined-field catalog. Sensitive. |
91
- | `contacts.query` | query | read | sensitive | none | Query Contact records with a JSON filter. Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. Sensitive. |
91
+ | `contacts.query` | query | read | sensitive | none | Query Contact records with a JSON filter. Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. Sensitive. |
92
92
  | `contacts.resolve` | resolve | read | sensitive | identifier | Resolve a Contact from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (firstName + lastName — exact match only). Returns the Contact record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). Sensitive. |
93
93
  | `contacts.search` | search | read | sensitive | query | Search contact records by text (contains on the searchable fields). (under a company) Bounded: limit default 25, max 500. Sensitive. |
94
94
 
95
95
  ### `autotask_contact_write` (write — contact)
96
96
 
97
- > Write contact records (mode: write — the registry operations with effect=write for contacts: create, moveToCompany, update, upsertByEmail). Writes are dry-run first: dry_run defaults to true — the request is validated against the registry inputSchema and a DryRunResult envelope is returned; the mutating request is never issued unless the caller passes confirm (the n8n-side handler must force dry-run unless confirm is present, mirroring the SDK governor). Destructive operations are refused without the confirm flag — confirm must equal the operation key exactly (the deliberate act is the call). The n8n consumer surface excludes destructive operations by curation default (excludeDestructive); they remain available on the canonical SDK server (autotask_delete / per-op tools). By curation default (excludeDestructive) no destructive operation is included; destructive capability remains on the canonical SDK server surface. Approval-gated operations (contacts.moveToCompany) additionally require confirm equal to the operation key. Per-operation required arguments: create [parentId, data]; moveToCompany [sourceContactId, destinationCompanyId]; update [parentId, id, data]; upsertByEmail [companyID, email]. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
97
+ > Write contact records (mode: write — the registry operations with effect=write for contacts: create, moveToCompany, update). Writes are dry-run first: dry_run defaults to true — the request is validated against the registry inputSchema and a DryRunResult envelope is returned; the mutating request is never issued unless the caller passes confirm (the n8n-side handler must force dry-run unless confirm is present, mirroring the SDK governor). Destructive operations are refused without the confirm flag — confirm must equal the operation key exactly (the deliberate act is the call). The n8n consumer surface excludes destructive operations by curation default (excludeDestructive); they remain available on the canonical SDK server (autotask_delete / per-op tools). By curation default (excludeDestructive) no destructive operation is included; destructive capability remains on the canonical SDK server surface. Approval-gated operations (contacts.moveToCompany) additionally require confirm equal to the operation key. Per-operation required arguments: create [parentId, data]; moveToCompany [sourceContactId, destinationCompanyId]; update [parentId, id, data]. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
98
98
 
99
- Tool input: {"operation":{"type":"string","enum":["create","moveToCompany","update","upsertByEmail"]},"parentId":{"type":"number | string"},"data":{"type":"object","ref":"contacts body (see types)"},"sourceContactId":{"type":"number | string"},"destinationCompanyId":{"type":"number | string"},"id":{"type":"number | string"},"companyID":{"type":"number | string (the parent — the create MUST be scoped: the global /V1.0/Contacts collection has no POST)"},"email":{"type":"string (the natural dedup key — the vendor field emailAddress, exact match under the parent)"},"extra":{"type":"object (optional) — { firstName?: string (default: the email local-part), lastName?: string (default: empty string), isActive?: boolean | number (BOOLEAN ACCEPTED — mapped to the zone-correct number 1/0; a raw 0/1 number passes through) }"},"dry_run":{"type":"boolean","default":true,"note":"true (the default) = the pinned DryRunResult envelope; the mutating request is never issued. The handler must force dry-run unless confirm is present."},"confirm":{"type":"string","note":"The operation key (e.g. \"tickets.create\") — its presence lifts the dry run. For destructive/approval-gated operations confirm must equal the operation key exactly; the call is refused pre-request without it."}} (required: operation)
99
+ Tool input: {"operation":{"type":"string","enum":["create","moveToCompany","update"]},"parentId":{"type":"number | string"},"data":{"type":"object","ref":"contacts body (see types)"},"sourceContactId":{"type":"number | string"},"destinationCompanyId":{"type":"number | string"},"id":{"type":"number | string"},"dry_run":{"type":"boolean","default":true,"note":"true (the default) = the pinned DryRunResult envelope; the mutating request is never issued. The handler must force dry-run unless confirm is present."},"confirm":{"type":"string","note":"The operation key (e.g. \"tickets.create\") — its presence lifts the dry run. For destructive/approval-gated operations confirm must equal the operation key exactly; the call is refused pre-request without it."}} (required: operation)
100
100
 
101
101
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
102
102
  |------------------|------|--------|-------|--------------|---------|
103
103
  | `contacts.create` | create | write | — | parentId, data | Create a contact. (under a company) Dry-run first (dry_run). |
104
104
  | `contacts.moveToCompany` | moveToCompany | write | requiresApproval+sensitive | sourceContactId, destinationCompanyId | Move a contact to a different company. Dry-run first (dry_run). Requires confirmation (confirm: contacts.moveToCompany). Sensitive. |
105
105
  | `contacts.update` | update | write | idempotent | parentId, id, data | Update a contact. (under a company) Dry-run first (dry_run). Idempotent. |
106
- | `contacts.upsertByEmail` | upsertByEmail | write | — | companyID, email | Make sure a contact with the given email exists under the given company — find-or-create under the RIGHT parent, with the typed EXISTS/CREATED result (+ the record). Dry-run first (dry_run). |
107
106
 
108
107
  ### `autotask_company` (read — company)
109
108
 
110
- > Read company records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for companies: count: Count company records matching a JSON filter. | fullProfile: Get everything the node knows about one company in a single call: the company record, its locations, contacts and notes, its open tickets, and its projects — every part separately reported with caps. | get: Get one Company by id. | getContext: Get a company with its primary context records in one call. | getEntityInfo: Get the Company capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the Company field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the Company user-defined-field catalog. | prepareCrmWrite: Plan a CRM write: from partial company/contact details, find the company, its locations and the location to link a contact to, duplicate contacts, the required fields still missing (with how to get each) and the next atomic write to preview. | query: Query Company records with a JSON filter. | resolve: Resolve a Company from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (companyName — exact match only). Returns the Company record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). | search: Search company records by text (contains on the searchable fields). | searchByDomain: Find companies whose web address matches a domain (when no web address matches, the op falls back to matching contact emails). | searchByIdentity: Find companies by any combination of companyName / email / website identity values. | unbilledWork: One call for a company's unbilled work: its posted billing items (per source), the time behind them (joined through the company's tickets and tasks — time entries carry no companyID), the per-ticket rollup, the unposted anti-join section, ex-tax totals + hours, and the billing-vs-time warnings. Bounds: Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. Bounded: limit default 25, max 500. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
109
+ > Read company records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for companies: count: Count company records matching a JSON filter. | fullProfile: Get everything the node knows about one company in a single call: the company record, its locations, contacts and notes, its open tickets, and its projects — every part separately reported with caps. | get: Get one Company by id. | getContext: Get a company with its primary context records in one call. | getEntityInfo: Get the Company capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the Company field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the Company user-defined-field catalog. | prepareCrmWrite: Plan a CRM write: from partial company/contact details, find the company, its locations and the location to link a contact to, duplicate contacts, the required fields still missing (with how to get each) and the next atomic write to preview. | query: Query Company records with a JSON filter. | resolve: Resolve a Company from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (companyName — exact match only). Returns the Company record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). | search: Search company records by text (contains on the searchable fields). | searchByDomain: Find companies whose web address matches a domain (when no web address matches, the op falls back to matching contact emails). | searchByIdentity: Find companies by any combination of companyName / email / website identity values. | unbilledWork: One call for a company's unbilled work: its posted billing items (per source), the time behind them (joined through the company's tickets and tasks — time entries carry no companyID), the per-ticket rollup, the unposted anti-join section, ex-tax totals + hours, and the billing-vs-time warnings. Bounds: Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. Bounded: limit default 25, max 500. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
111
110
 
112
111
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
113
112
  |------------------|------|--------|-------|--------------|---------|
@@ -119,7 +118,7 @@ Tool input: {"operation":{"type":"string","enum":["create","moveToCompany","upda
119
118
  | `companies.getFieldInfo` | getFieldInfo | read | — | none | Get the Company field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). |
120
119
  | `companies.getUdfInfo` | getUdfInfo | read | — | none | Get the Company user-defined-field catalog. |
121
120
  | `companies.prepareCrmWrite` | prepareCrmWrite | read | — | input | Plan a CRM write: from partial company/contact details, find the company, its locations and the location to link a contact to, duplicate contacts, the required fields still missing (with how to get each) and the next atomic write to preview. |
122
- | `companies.query` | query | read | — | none | Query Company records with a JSON filter. Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. |
121
+ | `companies.query` | query | read | — | none | Query Company records with a JSON filter. Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. |
123
122
  | `companies.resolve` | resolve | read | — | identifier | Resolve a Company from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (companyName — exact match only). Returns the Company record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). |
124
123
  | `companies.search` | search | read | — | query | Search company records by text (contains on the searchable fields). Bounded: limit default 25, max 500. |
125
124
  | `companies.searchByDomain` | searchByDomain | read | — | domain | Find companies whose web address matches a domain (when no web address matches, the op falls back to matching contact emails). |
@@ -128,19 +127,18 @@ Tool input: {"operation":{"type":"string","enum":["create","moveToCompany","upda
128
127
 
129
128
  ### `autotask_company_write` (write — company)
130
129
 
131
- > Write company records (mode: write — the registry operations with effect=write for companies: create, update, upsertByName). Writes are dry-run first: dry_run defaults to true — the request is validated against the registry inputSchema and a DryRunResult envelope is returned; the mutating request is never issued unless the caller passes confirm (the n8n-side handler must force dry-run unless confirm is present, mirroring the SDK governor). Destructive operations are refused without the confirm flag — confirm must equal the operation key exactly (the deliberate act is the call). The n8n consumer surface excludes destructive operations by curation default (excludeDestructive); they remain available on the canonical SDK server (autotask_delete / per-op tools). By curation default (excludeDestructive) no destructive operation is included; destructive capability remains on the canonical SDK server surface. Per-operation required arguments: create [data]; update [id, data]; upsertByName [companyName, params]. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
130
+ > Write company records (mode: write — the registry operations with effect=write for companies: create, update). Writes are dry-run first: dry_run defaults to true — the request is validated against the registry inputSchema and a DryRunResult envelope is returned; the mutating request is never issued unless the caller passes confirm (the n8n-side handler must force dry-run unless confirm is present, mirroring the SDK governor). Destructive operations are refused without the confirm flag — confirm must equal the operation key exactly (the deliberate act is the call). The n8n consumer surface excludes destructive operations by curation default (excludeDestructive); they remain available on the canonical SDK server (autotask_delete / per-op tools). By curation default (excludeDestructive) no destructive operation is included; destructive capability remains on the canonical SDK server surface. Per-operation required arguments: create [data]; update [id, data]. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
132
131
 
133
- Tool input: {"operation":{"type":"string","enum":["create","update","upsertByName"]},"data":{"type":"object","ref":"companies body (see types)"},"id":{"type":"number | string"},"companyName":{"type":"string (the natural dedup key — exact match on the vendor field companyName; the dedup covers only companies this API user can enumerate — the unowned surface is blind)"},"params":{"type":"object — { phone: string, ownerResourceID?: number (REQUIRED on the create path — an active non-API-only resource; the node cannot enumerate candidates: the resources table is blind to the API user; absent + a dedup miss → the typed OWNER_RESOURCE_REQUIRED, zero wire), companyType?: number (default 1 — the ww29-proven value) }"},"dry_run":{"type":"boolean","default":true,"note":"true (the default) = the pinned DryRunResult envelope; the mutating request is never issued. The handler must force dry-run unless confirm is present."},"confirm":{"type":"string","note":"The operation key (e.g. \"tickets.create\") — its presence lifts the dry run. For destructive/approval-gated operations confirm must equal the operation key exactly; the call is refused pre-request without it."}} (required: operation)
132
+ Tool input: {"operation":{"type":"string","enum":["create","update"]},"data":{"type":"object","ref":"companies body (see types)"},"id":{"type":"number | string"},"dry_run":{"type":"boolean","default":true,"note":"true (the default) = the pinned DryRunResult envelope; the mutating request is never issued. The handler must force dry-run unless confirm is present."},"confirm":{"type":"string","note":"The operation key (e.g. \"tickets.create\") — its presence lifts the dry run. For destructive/approval-gated operations confirm must equal the operation key exactly; the call is refused pre-request without it."}} (required: operation)
134
133
 
135
134
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
136
135
  |------------------|------|--------|-------|--------------|---------|
137
136
  | `companies.create` | create | write | — | data | Create a company. Dry-run first (dry_run). |
138
137
  | `companies.update` | update | write | idempotent | id, data | Update a company. Dry-run first (dry_run). Idempotent. |
139
- | `companies.upsertByName` | upsertByName | write | — | companyName, params | Make sure a company with the given name exists — find-or-create that carries the blind-surface boundary IN THE RESULT instead of pretending total visibility. Dry-run first (dry_run). |
140
138
 
141
139
  ### `autotask_companyLocation` (read — companyLocation)
142
140
 
143
- > Read companyLocation records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for company_locations: count: Count company location records matching a JSON filter. | get: Get one CompanyLocation by id. | getEntityInfo: Get the CompanyLocation capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the CompanyLocation field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the CompanyLocation user-defined-field catalog. | query: Query CompanyLocation records with a JSON filter. | resolve: Resolve a company location from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (name — exact match only). Returns the Company location record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). | search: Search company location records by text (contains on the searchable fields).. Bounds: Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. Bounded: limit default 25, max 500. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
141
+ > Read companyLocation records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for company_locations: count: Count company location records matching a JSON filter. | get: Get one CompanyLocation by id. | getEntityInfo: Get the CompanyLocation capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the CompanyLocation field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the CompanyLocation user-defined-field catalog. | query: Query CompanyLocation records with a JSON filter. | resolve: Resolve a company location from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (name — exact match only). Returns the Company location record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). | search: Search company location records by text (contains on the searchable fields).. Bounds: Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. Bounded: limit default 25, max 500. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
144
142
 
145
143
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
146
144
  |------------------|------|--------|-------|--------------|---------|
@@ -149,7 +147,7 @@ Tool input: {"operation":{"type":"string","enum":["create","update","upsertByNam
149
147
  | `company_locations.getEntityInfo` | getEntityInfo | read | — | none | Get the CompanyLocation capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). |
150
148
  | `company_locations.getFieldInfo` | getFieldInfo | read | — | none | Get the CompanyLocation field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). |
151
149
  | `company_locations.getUdfInfo` | getUdfInfo | read | — | none | Get the CompanyLocation user-defined-field catalog. |
152
- | `company_locations.query` | query | read | — | none | Query CompanyLocation records with a JSON filter. Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. |
150
+ | `company_locations.query` | query | read | — | none | Query CompanyLocation records with a JSON filter. Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. |
153
151
  | `company_locations.resolve` | resolve | read | — | identifier | Resolve a company location from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (name — exact match only). Returns the Company location record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). |
154
152
  | `company_locations.search` | search | read | — | query | Search company location records by text (contains on the searchable fields). Bounded: limit default 25, max 500. |
155
153
 
@@ -166,7 +164,7 @@ Tool input: {"operation":{"type":"string","enum":["create","update"]},"parentId"
166
164
 
167
165
  ### `autotask_ticketNote` (read — ticketNote)
168
166
 
169
- > Read ticketNote records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for ticket_notes: count: Count ticket note records matching a JSON filter. | get: Get one TicketNote by id. | getEntityInfo: Get the TicketNote capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the TicketNote field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the TicketNote user-defined-field catalog. | query: Query TicketNote records with a JSON filter. | resolve: Resolve a ticket note from a numeric id (the direct fetch) only — this resource has no searchable text field, so a non-numeric identifier throws a config error.. Bounds: Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
167
+ > Read ticketNote records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for ticket_notes: count: Count ticket note records matching a JSON filter. | get: Get one TicketNote by id. | getEntityInfo: Get the TicketNote capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the TicketNote field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the TicketNote user-defined-field catalog. | query: Query TicketNote records with a JSON filter. | resolve: Resolve a ticket note from a numeric id (the direct fetch) only — this resource has no searchable text field, so a non-numeric identifier throws a config error.. Bounds: Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
170
168
 
171
169
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
172
170
  |------------------|------|--------|-------|--------------|---------|
@@ -175,7 +173,7 @@ Tool input: {"operation":{"type":"string","enum":["create","update"]},"parentId"
175
173
  | `ticket_notes.getEntityInfo` | getEntityInfo | read | — | none | Get the TicketNote capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). |
176
174
  | `ticket_notes.getFieldInfo` | getFieldInfo | read | — | none | Get the TicketNote field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). |
177
175
  | `ticket_notes.getUdfInfo` | getUdfInfo | read | — | none | Get the TicketNote user-defined-field catalog. |
178
- | `ticket_notes.query` | query | read | — | none | Query TicketNote records with a JSON filter. Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. |
176
+ | `ticket_notes.query` | query | read | — | none | Query TicketNote records with a JSON filter. Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. |
179
177
  | `ticket_notes.resolve` | resolve | read | — | identifier | Resolve a ticket note from a numeric id (the direct fetch) only — this resource has no searchable text field, so a non-numeric identifier throws a config error. |
180
178
 
181
179
  ### `autotask_ticketNote_write` (write — ticketNote)
@@ -191,7 +189,7 @@ Tool input: {"operation":{"type":"string","enum":["create","update"]},"parentId"
191
189
 
192
190
  ### `autotask_resource` (read — resource)
193
191
 
194
- > Read resource records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for resources: count: Count resource records matching a JSON filter. | get: Get one Resource by id. | getEntityInfo: Get the Resource capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the Resource field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the Resource user-defined-field catalog. | query: Query Resource records with a JSON filter. | resolve: Resolve a resource from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (firstName + lastName — exact match only). Returns the Resource record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). | search: Search resource records by text (contains on the searchable fields). | whoAmI: Identify the resource the current credentials act as.. Bounds: Sensitive. Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. Sensitive. Bounded: limit default 25, max 500. Sensitive. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
192
+ > Read resource records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for resources: count: Count resource records matching a JSON filter. | get: Get one Resource by id. | getEntityInfo: Get the Resource capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the Resource field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the Resource user-defined-field catalog. | query: Query Resource records with a JSON filter. | resolve: Resolve a resource from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (firstName + lastName — exact match only). Returns the Resource record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). | search: Search resource records by text (contains on the searchable fields). | whoAmI: Identify the resource the current credentials act as. | workload: Get a resource's workload in a single call: its open tickets (rows + the exact open totals), its task assignments and the tasks behind them, its time-off balances and requests.. Bounds: Sensitive. Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. Sensitive. Bounded: limit default 25, max 500. Sensitive. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
195
193
 
196
194
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
197
195
  |------------------|------|--------|-------|--------------|---------|
@@ -200,64 +198,46 @@ Tool input: {"operation":{"type":"string","enum":["create","update"]},"parentId"
200
198
  | `resources.getEntityInfo` | getEntityInfo | read | sensitive | none | Get the Resource capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). Sensitive. |
201
199
  | `resources.getFieldInfo` | getFieldInfo | read | sensitive | none | Get the Resource field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). Sensitive. |
202
200
  | `resources.getUdfInfo` | getUdfInfo | read | sensitive | none | Get the Resource user-defined-field catalog. Sensitive. |
203
- | `resources.query` | query | read | sensitive | none | Query Resource records with a JSON filter. Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. Sensitive. |
201
+ | `resources.query` | query | read | sensitive | none | Query Resource records with a JSON filter. Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. Sensitive. |
204
202
  | `resources.resolve` | resolve | read | sensitive | identifier | Resolve a resource from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (firstName + lastName — exact match only). Returns the Resource record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog). Sensitive. |
205
203
  | `resources.search` | search | read | sensitive | query | Search resource records by text (contains on the searchable fields). Bounded: limit default 25, max 500. Sensitive. |
206
204
  | `resources.whoAmI` | whoAmI | read | sensitive | none | Identify the resource the current credentials act as. Sensitive. |
205
+ | `resources.workload` | workload | read | — | id | Get a resource's workload in a single call: its open tickets (rows + the exact open totals), its task assignments and the tasks behind them, its time-off balances and requests. |
207
206
 
208
207
  ### `autotask_resource_write` (write — resource)
209
208
 
210
- > Write resource records (mode: write — the registry operations with effect=write for resources: transferOwnership, update). Writes are dry-run first: dry_run defaults to true — the request is validated against the registry inputSchema and a DryRunResult envelope is returned; the mutating request is never issued unless the caller passes confirm (the n8n-side handler must force dry-run unless confirm is present, mirroring the SDK governor). Destructive operations are refused without the confirm flag — confirm must equal the operation key exactly (the deliberate act is the call). The n8n consumer surface excludes destructive operations by curation default (excludeDestructive); they remain available on the canonical SDK server (autotask_delete / per-op tools). By curation default (excludeDestructive) no destructive operation is included; destructive capability remains on the canonical SDK server surface. Approval-gated operations (resources.transferOwnership) additionally require confirm equal to the operation key. Per-operation required arguments: transferOwnership [sourceResourceIds, destinationResourceId]; update [id, data]. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
209
+ > Write resource records (mode: write — the registry operations with effect=write for resources: update). Writes are dry-run first: dry_run defaults to true — the request is validated against the registry inputSchema and a DryRunResult envelope is returned; the mutating request is never issued unless the caller passes confirm (the n8n-side handler must force dry-run unless confirm is present, mirroring the SDK governor). Destructive operations are refused without the confirm flag — confirm must equal the operation key exactly (the deliberate act is the call). The n8n consumer surface excludes destructive operations by curation default (excludeDestructive); they remain available on the canonical SDK server (autotask_delete / per-op tools). By curation default (excludeDestructive) no destructive operation is included; destructive capability remains on the canonical SDK server surface. Per-operation required arguments: update [id, data]. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
211
210
 
212
- Tool input: {"operation":{"type":"string","enum":["transferOwnership","update"]},"sourceResourceIds":{"type":"(number | string)[] (max 500)"},"destinationResourceId":{"type":"number | string"},"id":{"type":"number | string"},"data":{"type":"object","ref":"resources body (see types)"},"dry_run":{"type":"boolean","default":true,"note":"true (the default) = the pinned DryRunResult envelope; the mutating request is never issued. The handler must force dry-run unless confirm is present."},"confirm":{"type":"string","note":"The operation key (e.g. \"tickets.create\") — its presence lifts the dry run. For destructive/approval-gated operations confirm must equal the operation key exactly; the call is refused pre-request without it."}} (required: operation)
211
+ Tool input: {"operation":{"type":"string","enum":["update"]},"id":{"type":"number | string"},"data":{"type":"object","ref":"resources body (see types)"},"dry_run":{"type":"boolean","default":true,"note":"true (the default) = the pinned DryRunResult envelope; the mutating request is never issued. The handler must force dry-run unless confirm is present."},"confirm":{"type":"string","note":"The operation key (e.g. \"tickets.create\") — its presence lifts the dry run. For destructive/approval-gated operations confirm must equal the operation key exactly; the call is refused pre-request without it."}} (required: operation)
213
212
 
214
213
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
215
214
  |------------------|------|--------|-------|--------------|---------|
216
- | `resources.transferOwnership` | transferOwnership | write | requiresApproval+sensitive | sourceResourceIds, destinationResourceId | Transfer ownership of named resources to another resource. Dry-run first (dry_run). Requires confirmation (confirm: resources.transferOwnership). Sensitive. |
217
215
  | `resources.update` | update | write | idempotent+sensitive | id, data | Update a resource. Dry-run first (dry_run). Idempotent. Sensitive. |
218
216
 
219
217
  ### `autotask_timeEntry` (read — timeEntry)
220
218
 
221
- > Read timeEntry records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for time_entries: count: Count time entry records matching a JSON filter. | customRange: Get time entries for an explicit dateWorked range. | dateWorkedWindow: The unambiguous-named alias for time_entries.postedWithin (issue #66): the dateWorked window read with the posted/unposted split derived from the billing_items.timeEntryID join — same wire, same result (incl. truncated). The window is ON dateWorked (entries worked within [from, to]); "postedWithin" keeps its historical name (its "posted" is the posted/unposted split, never a posted-date window or a postedDate read). | get: Get one TimeEntry by id. | getEntityInfo: Get the TimeEntry capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the TimeEntry field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getPosted: Get posted time entries (an entry that a billing item references), optionally for one ticket and/or a dateWorked window — posted state derives from the billing_items.timeEntryID join, never a postedDate read or approval. | getUdfInfo: Get the TimeEntry user-defined-field catalog. | getUnposted: Get unposted time entries (entries no billing item references), optionally for one ticket and/or a dateWorked window — posted state derives from the billing_items.timeEntryID join, never a postedDate read or approval. | last14: Get time entries for the last 14 days (rolling, dateWorked). | last24h: Get time entries for the last 24 hours (rolling, dateWorked). | last30: Get time entries for the last 30 days (rolling, dateWorked). | last7: Get time entries for the last 7 days (rolling, dateWorked). | last90: Get time entries for the last 90 days (rolling, dateWorked). | lastFullFortnight: Get time entries for the last complete fortnight. | lastFullMonth: Get time entries for the last complete calendar month. | lastFullQuarter: Get time entries for the last complete calendar quarter. | lastFullWeek: Get time entries for the last complete calendar week. | postedWithin: Get time entries WORKED within an inclusive dateWorked window with the posted/unposted split. The window is ON the dateWorked field — the name's "posted" is the posted/unposted SPLIT derived from the billing_items.timeEntryID join (an entry a billing item references is posted, approval is not consulted), never a posted-date window or a postedDate read. The counts cover the returned rows only; truncated flags a capped read. time_entries.dateWorkedWindow is the unambiguous name. | query: Query TimeEntry records with a JSON filter. | resolve: Resolve a time entry from a numeric id (the direct fetch) only — this resource has no searchable text field, so a non-numeric identifier throws a config error. | today: Get time entries for today (dateWorked = now, server date). | yesterday: Get time entries for yesterday (dateWorked = yesterday, server date).. Bounds: Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
219
+ > Read timeEntry records (mode: read — effect=read operations only; zero mutating requests, ungated by design). Registry operations for time_entries: count: Count time entry records matching a JSON filter. | dateWorkedWindow: The ONE posted-state read (issue #290): a bounded read over the inclusive dateWorked window [from, to] (UTC 'YYYY-MM-DD' days) with the posted/unposted split derived from the billing_items.timeEntryID join — never a postedDate read (W-D3: this zone's TimeEntry entity has no postedDate; postedDate exist|notExist 500s, live ww29 2026-10-27). Approval is NOT consulted (ww29 never populates billingApprovalDateTime yet bills those entries). The no-window form is gone: read with no dateWorked filter goes through time_entries.query. | get: Get one TimeEntry by id. | getEntityInfo: Get the TimeEntry capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). | getFieldInfo: Get the TimeEntry field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). | getUdfInfo: Get the TimeEntry user-defined-field catalog. | query: Query TimeEntry records with a JSON filter. | resolve: Resolve a time entry from a numeric id (the direct fetch) only — this resource has no searchable text field, so a non-numeric identifier throws a config error.. Bounds: Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
222
220
 
223
221
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
224
222
  |------------------|------|--------|-------|--------------|---------|
225
223
  | `time_entries.count` | count | read | — | none | Count time entry records matching a JSON filter. |
226
- | `time_entries.customRange` | customRange | read | — | from, to | Get time entries for an explicit dateWorked range. |
227
- | `time_entries.dateWorkedWindow` | dateWorkedWindow | read | — | from, to | The unambiguous-named alias for time_entries.postedWithin (issue #66): the dateWorked window read with the posted/unposted split derived from the billing_items.timeEntryID join — same wire, same result (incl. truncated). The window is ON dateWorked (entries worked within [from, to]); "postedWithin" keeps its historical name (its "posted" is the posted/unposted split, never a posted-date window or a postedDate read). |
224
+ | `time_entries.dateWorkedWindow` | dateWorkedWindow | read | — | from, to | The ONE posted-state read (issue #290): a bounded read over the inclusive dateWorked window [from, to] (UTC 'YYYY-MM-DD' days) with the posted/unposted split derived from the billing_items.timeEntryID join — never a postedDate read (W-D3: this zone's TimeEntry entity has no postedDate; postedDate exist|notExist 500s, live ww29 2026-10-27). Approval is NOT consulted (ww29 never populates billingApprovalDateTime yet bills those entries). The no-window form is gone: read with no dateWorked filter goes through time_entries.query. |
228
225
  | `time_entries.get` | get | read | — | id | Get one TimeEntry by id. |
229
226
  | `time_entries.getEntityInfo` | getEntityInfo | read | — | none | Get the TimeEntry capability metadata (canCreate/canUpdate/hasUserDefinedFields/...). |
230
227
  | `time_entries.getFieldInfo` | getFieldInfo | read | — | none | Get the TimeEntry field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog). |
231
- | `time_entries.getPosted` | getPosted | read | — | none | Get posted time entries (an entry that a billing item references), optionally for one ticket and/or a dateWorked window — posted state derives from the billing_items.timeEntryID join, never a postedDate read or approval. |
232
228
  | `time_entries.getUdfInfo` | getUdfInfo | read | — | none | Get the TimeEntry user-defined-field catalog. |
233
- | `time_entries.getUnposted` | getUnposted | read | — | none | Get unposted time entries (entries no billing item references), optionally for one ticket and/or a dateWorked window — posted state derives from the billing_items.timeEntryID join, never a postedDate read or approval. |
234
- | `time_entries.last14` | last14 | read | — | none | Get time entries for the last 14 days (rolling, dateWorked). |
235
- | `time_entries.last24h` | last24h | read | — | none | Get time entries for the last 24 hours (rolling, dateWorked). |
236
- | `time_entries.last30` | last30 | read | — | none | Get time entries for the last 30 days (rolling, dateWorked). |
237
- | `time_entries.last7` | last7 | read | — | none | Get time entries for the last 7 days (rolling, dateWorked). |
238
- | `time_entries.last90` | last90 | read | — | none | Get time entries for the last 90 days (rolling, dateWorked). |
239
- | `time_entries.lastFullFortnight` | lastFullFortnight | read | — | none | Get time entries for the last complete fortnight. |
240
- | `time_entries.lastFullMonth` | lastFullMonth | read | — | none | Get time entries for the last complete calendar month. |
241
- | `time_entries.lastFullQuarter` | lastFullQuarter | read | — | none | Get time entries for the last complete calendar quarter. |
242
- | `time_entries.lastFullWeek` | lastFullWeek | read | — | none | Get time entries for the last complete calendar week. |
243
- | `time_entries.postedWithin` | postedWithin | read | — | from, to | Get time entries WORKED within an inclusive dateWorked window with the posted/unposted split. The window is ON the dateWorked field — the name's "posted" is the posted/unposted SPLIT derived from the billing_items.timeEntryID join (an entry a billing item references is posted, approval is not consulted), never a posted-date window or a postedDate read. The counts cover the returned rows only; truncated flags a capped read. time_entries.dateWorkedWindow is the unambiguous name. |
244
- | `time_entries.query` | query | read | — | none | Query TimeEntry records with a JSON filter. Bounded: server-side pagination — up to limit records (default 500, max 2500) in one call; 1000-page guard; hasMore flags a truncation. |
229
+ | `time_entries.query` | query | read | — | none | Query TimeEntry records with a JSON filter. Bounded: server-side pagination — ordinary limit default 500, max 2500; walk.maxRows independently sets the total cap, with pages at most min(500, limit); 1000-page guard; hasMore/truncated flag remaining rows. |
245
230
  | `time_entries.resolve` | resolve | read | — | identifier | Resolve a time entry from a numeric id (the direct fetch) only — this resource has no searchable text field, so a non-numeric identifier throws a config error. |
246
- | `time_entries.today` | today | read | — | none | Get time entries for today (dateWorked = now, server date). |
247
- | `time_entries.yesterday` | yesterday | read | — | none | Get time entries for yesterday (dateWorked = yesterday, server date). |
248
231
 
249
232
  ### `autotask_timeEntry_write` (write — timeEntry)
250
233
 
251
- > Write timeEntry records (mode: write — the registry operations with effect=write for time_entries: approve, create, createForResource, createIfNotExists, update). Writes are dry-run first: dry_run defaults to true — the request is validated against the registry inputSchema and a DryRunResult envelope is returned; the mutating request is never issued unless the caller passes confirm (the n8n-side handler must force dry-run unless confirm is present, mirroring the SDK governor). Destructive operations are refused without the confirm flag — confirm must equal the operation key exactly (the deliberate act is the call). The n8n consumer surface excludes destructive operations by curation default (excludeDestructive); they remain available on the canonical SDK server (autotask_delete / per-op tools). By curation default (excludeDestructive) no destructive operation is included; destructive capability remains on the canonical SDK server surface. Per-operation required arguments: approve [id]; create [data]; createForResource [resourceID, params]; createIfNotExists [data]; update [id, data]. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
234
+ > Write timeEntry records (mode: write — the registry operations with effect=write for time_entries: create, update). Writes are dry-run first: dry_run defaults to true — the request is validated against the registry inputSchema and a DryRunResult envelope is returned; the mutating request is never issued unless the caller passes confirm (the n8n-side handler must force dry-run unless confirm is present, mirroring the SDK governor). Destructive operations are refused without the confirm flag — confirm must equal the operation key exactly (the deliberate act is the call). The n8n consumer surface excludes destructive operations by curation default (excludeDestructive); they remain available on the canonical SDK server (autotask_delete / per-op tools). By curation default (excludeDestructive) no destructive operation is included; destructive capability remains on the canonical SDK server surface. Per-operation required arguments: create [data]; update [id, data]. Errors carry the SDK error contract: code, category, retryable, operation, httpStatus, suggestedAction (the nextAction directive — follow the directive), correlationId, vendorError (when the vendor returned a response body — the deep-redacted body, host-sourced text wrapped as untrusted content when untrusted-wrapping is on); credentials never appear in an error message.
252
235
 
253
- Tool input: {"operation":{"type":"string","enum":["approve","create","createForResource","createIfNotExists","update"]},"id":{"type":"number | string"},"data":{"type":"object","ref":"time_entries body (see types)"},"resourceID":{"type":"number | string"},"params":{"type":"object — the smart-create params: { internallAllocationCodeID?: number (pin the internal linkage code), ticketID?: number, taskID?: number, roleID?: number (pin the task/ticket roleID — vendor-validated as an allocation code), dateWorked?: UTC YYYY-MM-DD, startDateTime?: UTC ISO, endDateTime?: UTC ISO, hoursWorked?: number, + any other vendor TimeEntry field } (exactly one linkage pin; none → the default internal linkage with the node-resolved code)"},"dry_run":{"type":"boolean","default":true,"note":"true (the default) = the pinned DryRunResult envelope; the mutating request is never issued. The handler must force dry-run unless confirm is present."},"confirm":{"type":"string","note":"The operation key (e.g. \"tickets.create\") — its presence lifts the dry run. For destructive/approval-gated operations confirm must equal the operation key exactly; the call is refused pre-request without it."}} (required: operation)
236
+ Tool input: {"operation":{"type":"string","enum":["create","update"]},"data":{"type":"object","ref":"time_entries body (see types)"},"id":{"type":"number | string"},"dry_run":{"type":"boolean","default":true,"note":"true (the default) = the pinned DryRunResult envelope; the mutating request is never issued. The handler must force dry-run unless confirm is present."},"confirm":{"type":"string","note":"The operation key (e.g. \"tickets.create\") — its presence lifts the dry run. For destructive/approval-gated operations confirm must equal the operation key exactly; the call is refused pre-request without it."}} (required: operation)
254
237
 
255
238
  | backingOperation | verb | effect | flags | requiredArgs | purpose |
256
239
  |------------------|------|--------|-------|--------------|---------|
257
- | `time_entries.approve` | approve | write | — | id | Approve a time entry (the REST-only approval path): create the BillingItemApprovalLevels record, apply the vendor-documented follow-up update of BillingApprovalDateTime + BillingApprovalResourceID, then read the entry back and report whether the vendor accepted it. Dry-run first (dry_run). |
258
240
  | `time_entries.create` | create | write | — | data | Create a time entry. Dry-run first (dry_run). |
259
- | `time_entries.createForResource` | createForResource | write | — | resourceID, params | Create a time entry for a resource with the allocation-code dependency resolved by the node: it verifies the resource is active, honours the caller's linkage pin (else the default internal linkage), resolves an EXISTING active allocation code applicable to the resource (never creates one — the API user cannot), and posts the vendor-valid body. Dry-run first (dry_run). |
260
- | `time_entries.createIfNotExists` | createIfNotExists | write | — | data | Create a TimeEntry. Dry-run first (dry_run). |
261
241
  | `time_entries.update` | update | write | idempotent | id, data | Update a time entry. Dry-run first (dry_run). Idempotent. |
262
242
 
263
243
  ## Destructive operations — excluded by default, available via the SDK server (P2 honesty)
@@ -275,19 +255,19 @@ only via a recorded change to `n8n-mcp.curation.json`.
275
255
 
276
256
  ## Stats
277
257
 
278
- - registryRecords: 1281
258
+ - registryRecords: 1224
279
259
  - curatedEntities: 7
280
260
  - includedEntities: 7
281
261
  - readTools: 7
282
262
  - writeTools: 7
283
263
  - totalTools: 14
284
- - readOperations: 88
285
- - writeOperations: 22
286
- - approvalGatedWrites: 2
264
+ - readOperations: 75
265
+ - writeOperations: 15
266
+ - approvalGatedWrites: 1
287
267
  - destructiveExcluded: 4
288
268
 
289
269
  ## Meta
290
270
 
291
- - generatedAt: 2026-10-31T20:17:42.452Z
292
- - capabilitiesHash: 5c62553190a68829af1e554abc22fd9187edf78a0314a63fbf6706e98de0cbe4
293
- - curationHash: e19117ce73e38d9aded3be7e7f077a4e185d2e10294622b76c17d67f63cf9e3b
271
+ - generatedAt: 2026-11-01T10:43:53.479Z
272
+ - capabilitiesHash: 729ea0d47099fd45e1dde837510a92bd566a793368d0a4882e2613cbe05f7594
273
+ - curationHash: 623fbca25fa416f983dde22c8b736ce813a2db1bd8c188f7124abba710f52452
package/README.md CHANGED
@@ -47,6 +47,8 @@ const autotask = new AutotaskClient({
47
47
 
48
48
  // 2. Bounded query — the preferred read: ONE call returns up to `limit` TOTAL
49
49
  // records (server-side pagination inside the SDK; default 500, max 2500).
50
+ // For larger exports, `walk: { maxRows: 10_000 }` sets an independent total
51
+ // cap; `limit` then sizes pages (max 500). Check the returned `truncated` flag.
50
52
  // `maxRecords` is only the wire page size (default 10, max 500) — a raw
51
53
  // `query()`/`queryAll()` walk has NO total cap. `includeFields` slims the
52
54
  // payload (the context lever: only those fields + id come back).
@@ -242,7 +244,7 @@ The primary import re-exports everything; deep subpaths keep bundles small:
242
244
 
243
245
  ```ts
244
246
  // Cross-resource helpers (the agent execution layer)
245
- import { searchAcrossResources, resolveAny, invoke } from 'node-autotask/operations';
247
+ import { searchAcrossResources, resolveAny, resolveStaff, sanitiseResult, invoke } from 'node-autotask/operations';
246
248
 
247
249
  // The generated capability registry (zero-import plain literals)
248
250
  import { CAPABILITIES, CAPABILITY_GROUPS, CAPABILITY_PLAN_HASHES } from 'node-autotask/capabilities';
@@ -340,25 +342,9 @@ The SDK ships the mechanical substrate, not a server (no MCP imports, no zod):
340
342
  required); cross-mode calls are refused before any request (single
341
343
  governor place: `src/operations/invoke.ts`).
342
344
 
343
- **Harness approval policy (recommended).** Require approval on every tool
344
- whose MCP annotation is `readOnlyHint !== true` — today exactly **267
345
- tools**: the 265 dedicated write/delete tools (209 `effect=write` + 56
346
- `effect=destructive`, every one of them has a dedicated tool) +
347
- `autotask_write` + `autotask_delete`. The remaining **635 tools** (the 622 dedicated read tools + the 10 core read tools + `autotask_read` +
348
- `autotask_catalog` + `autotask_describe`) all carry `readOnlyHint: true`
349
- and are safe ungated: every op they can route is `effect=read` (zero
350
- mutating requests — pinned by the test inventory). Refined class for the
351
- highest-risk ops: the **57 tools with `destructiveHint: true`** (56
352
- dedicated delete tools + `autotask_delete`) additionally require
353
- `confirm === <operation key>` even inside `autotask_delete`, and the 3
354
- approval-gated writes (`configuration_items.moveConfigurationItem`,
355
- `contacts.moveToCompany`, `resources.transferOwnership`) require the same
356
- confirm inside `autotask_write`. Migration: `autotask_invoke` is REPLACED
357
- by `autotask_read`/`autotask_write`/`autotask_delete` — update harness
358
- config (approve the 267 above) and remove any `autotask_invoke` entry. The
359
- rule is derivable from the registry `effect` column (and the mode tools'
360
- fixed annotations) — it never needs a hand-maintained name list.
361
-
345
+ <!-- BEGIN GENERATED:approval-policy -->
346
+ **Harness approval policy (recommended).** Require approval on every tool whose MCP annotation is `readOnlyHint !== true` — today exactly **246 tools**: the 244 dedicated write/delete tools (188 `effect=write` + 56 `effect=destructive`, every one of them has a dedicated tool) + `autotask_write` + `autotask_delete`. The remaining **599 tools** (the 586 dedicated read tools + the 10 core read tools + `autotask_read` + `autotask_catalog` + `autotask_describe`) all carry `readOnlyHint: true` and are safe ungated: every op they can route is `effect=read` (zero mutating requests). Refined class for the highest-risk ops: the **57 tools with `destructiveHint: true`** (56 dedicated delete tools + `autotask_delete`) additionally require `confirm === <operation key>` even inside `autotask_delete`. The approval-gated writes (`configuration_items.moveConfigurationItem`, `contacts.moveToCompany`) require the same confirm inside `autotask_write`. Migration: `autotask_invoke` is REPLACED by `autotask_read`/`autotask_write`/`autotask_delete` — update harness config and remove any `autotask_invoke` entry. The rule is derivable from the registry `effect` column and the mode tools’ fixed annotations; it never needs a hand-maintained name list.
347
+ <!-- END GENERATED:approval-policy -->
362
348
  **Provider tool-search interop.** Hosts with provider-native tool search
363
349
  (OpenAI `type: "tool_search"` / `defer_loading`; Anthropic's tool search
364
350
  tool) defer-load tool arrays host-side. Two coexistences, both already
@@ -417,12 +403,8 @@ The SDK ships the mechanical substrate, not a server (no MCP imports, no zod):
417
403
  source.
418
404
 
419
405
  7. **Agent QoL surface (the stage-12 issue wave, live-verified on ww29)** —
420
- the zero-wire planning reads `operations.blindSurfaces` (the 124-surface
421
- blind/data inventory) and `operations.createGuidance` (per-child zone
422
- facts with verbatim vendor evidence), the bounded live
423
- `operations.probeReachability` sweep (confirm-gated, over-cap refuses),
424
- `operations.recovery` (find the records a marker-tagged write created;
425
- delete is dry-run-first under `confirm`), `time_entries.postedWithin`
406
+ the zero-wire planning read `operations.createGuidance` (per-child zone
407
+ facts with verbatim vendor evidence), `time_entries.postedWithin`
426
408
  (the inclusive UTC window read over `dateWorked` — posted/ticket/resource
427
409
  narrowing), the issue #13 create-path recovery (a drifted 2xx answers
428
410
  `idFrom: 'marker-recovery'` from ONE bounded marker read, or the typed
@@ -583,8 +565,8 @@ suites are the release gate, the live scripts are the ground-truth check.
583
565
  the 14-issue wave (agent profile + ClientPool/gateway mode, untrusted-content
584
566
  markers, the doctor preflight CLI, closed MCP input, wire-level surface probes
585
567
  + `npm run verify`, the Node-24 floor, the per-tenant 429 cooldown, delete
586
- boundaries + `operations.recovery`, the blind-surface inventory + bounded
587
- probe, the zone-fact create-guidance catalog, the posted/unposted rework
568
+ boundaries, the blind-surface inventory (the plan data the served artifacts
569
+ stamp from), the zone-fact create-guidance catalog, the posted/unposted rework
588
570
  (first the spec `postedDate` wire, replaced in 0.32.0 by the
589
571
  billing-item join because ww29 has no `postedDate`; W-D3 +
590
572
  `postedWithin`), the create-path marker recovery, the typed `emptyReason`,