List resourcing allocations — date-ranged assignments of a position on a project to an employee (or to nobody yet, an open role). No filters; page with cursor. Each item carries employeeId/employeeName and projectId/projectName already resolved (null employeeId means an open role); positionId is bare — resolve its name via positions_list. source distinguishes sheet-imported rows from ones created directly in Flowtly. Use this to reconcile a resourcing sheet import: read back what landed and compare against what was submitted.
cursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
clientContacts_create
write
Create a contact person for a client (client, type, name, email required). Write.
client stringtype* stringposition integeremail* stringname* stringtitle string | nullphone string | null
Create a new client record (name, country, currency, status, tinType required). Write.
country* stringcurrency* stringdefaultCost string | nullstatus* stringattributeSet string | nullname* stringdueDays integertinType* stringtinCountry string | nulltin string | nullexternalPaymentCustomerId string | nullinvoiceComment string | nulldefaultTaxRate string | nulldocumentsLanguage stringaddressPhoneNumber string | nulladdressCity string | nulladdressPostCode string | nulladdressStreetLine string | nulladdressBuildingNumber string | nulladdressLocaleNumber string | nulladdressCountry string | nullclientContacts arrayallowDuplicate boolean | null- Not persisted (no ORM\Column): an escape hatch for POST /clients only,
mirroring CounterpartyCreateByTypeInput::allowDuplicate. When true,
ClientCreateProcessor::refuseIfDuplicate() skips the duplicate-party
guard, matching the human-facing PATCH-and-attach pattern in
CounterpartyCreateByTypeProcessor.
vatNumber string | null
Get one client by id — name, country, currency, tax id and status.
id* string | integer
List clients (the org's customers). Filter by status, or by externalPaymentCustomerId to find the client behind a payment-provider id. Use it to resolve the client id that invoices_list, deals_list, projects_list and contracts_list all filter on.
properties array- Allows you to reduce the response to contain only the properties you need. If your desired property is nested, you can address it using nested arrays. Example: properties[]={propertyName}&properties[]={anotherPropertyName}&properties[{nestedPropertyParent}][]={nestedProperty}
externalPaymentCustomerId anystatus anyorder.name stringorder.status stringorder.tin stringorder.tinCountry stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Update a client record by id. Write.
country stringcurrency stringdefaultCost string | nullstatus stringattributeSet string | nullname stringdueDays integertinType stringtinCountry string | nulltin string | nullexternalPaymentCustomerId string | nullinvoiceComment string | nulldefaultTaxRate string | nulldocumentsLanguage stringaddressPhoneNumber string | nulladdressCity string | nulladdressPostCode string | nulladdressStreetLine string | nulladdressBuildingNumber string | nulladdressLocaleNumber string | nulladdressCountry string | nullclientContacts arrayvatNumber string | nullid* string | integer
List every organization config key the backend recognises, with its type and allowed values. This is the catalog of what is configurable — read it before configs_get or configs_update rather than guessing a key name. Permission is enforced per key by the backend, so a key appearing here does not guarantee the connected user may write it.
cursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Read one organization config value by id, where the id is a key from configKeys_catalog (e.g. organization-logo-url, organization-icon-url).
id* string | integer
Update an organization config value by id (type + name required; permission is enforced per config key by the backend). Write.
type stringname stringvalue stringid* string | integer
counterpartyBankAccounts_create
write
Attach a bank account to a counterparty (counterparty + accountNumber). Write.
counterparty stringaccountNumber string
Add a note to a lead or a deal (body + exactly one of lead/deal). Author is the connected user. Write.
body* stringlead string | nulldeal string | null
Delete a CRM note by id. Write.
id* string | integer
Get one CRM note by id.
id* string | integer
List notes written on leads and deals. Filter by lead or deal to read the running commentary on one record.
lead anydeal anycursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Update a CRM note’s body by id. Write.
body stringid* string | integer
Get one deal lost-reason by id.
id* string | integer
dealLostReasons_list
read
List the reasons a deal can be marked lost, in order. deals_lose requires a lostReasonId from here.
order.position stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Create a deal/opportunity (title, client, stage required; amountMinor, currency, expectedCloseDate, owner, contact optional). Write.
title* stringclient string | nullcontact string | nullstage* stringamountMinor string | nullcurrency string | nullexpectedCloseDate string | nullowner string | nulllead string | null
Delete a deal by id (soft delete). Write.
id* string | integer
Get one deal by id — title, client, stage, amount, owner, contact, expected and actual close dates.
id* string | integer
List deals/opportunities — the sales pipeline. Filter by status (open / won / lost), stage, owner, client, lead, or by expectedCloseDate / closedAt ranges. Amounts are minor units with an explicit currency; do not assume the org's default.
status anystage anyowner anyclient anylead anytitle stringclosedAt.before stringclosedAt.strictly_before stringclosedAt.after stringclosedAt.strictly_after stringexpectedCloseDate.before stringexpectedCloseDate.strictly_before stringexpectedCloseDate.after stringexpectedCloseDate.strictly_after stringcreatedAt.before stringcreatedAt.strictly_before stringcreatedAt.after stringcreatedAt.strictly_after stringorder.createdAt stringorder.expectedCloseDate stringorder.amountMinor stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Mark a deal lost — requires lostReasonId (from dealLostReasons_list); optional lostReasonNote. Write.
title* stringclient string | nullcontact string | nullstage* stringamountMinor string | nullcurrency string | nullexpectedCloseDate string | nullowner string | nulllead string | nullid* string | integer
Reopen a won/lost deal back to open. Write.
title* stringclient string | nullcontact string | nullstage* stringamountMinor string | nullcurrency string | nullexpectedCloseDate string | nullowner string | nulllead string | nullid* string | integer
Update a deal by id (title, stage, amount, close date, owner, contact). Moving the stage is logged automatically. Write.
title stringclient string | nullcontact string | nullstage stringamountMinor string | nullcurrency string | nullexpectedCloseDate string | nullowner string | nulllead string | nullid* string | integer
Mark a deal won — moves it to a won stage and stamps it closed; optional contractId links an existing contract. Write.
title* stringclient string | nullcontact string | nullstage* stringamountMinor string | nullcurrency string | nullexpectedCloseDate string | nullowner string | nulllead string | nullid* string | integer
dealStageHistories_get
read
Get one deal stage-change record by id.
id* string | integer
dealStageHistories_list
read
List a deal's stage transitions, newest first. Filter by deal. Every deals_update that moves the stage is logged here automatically, so this is how you reconstruct how long a deal sat in each stage — the deal itself only carries its current one.
deal anyorder.changedAt stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
incomingInvoices_acceptAllSuggestions
read
Accept every pending suggestion on an incoming invoice in one call — what a human does with the app's "accept all" button. The server applies, rebuilds, and applies again until nothing new appears: the transaction match does NOT exist until the supplier and amount are applied, so a single pass would leave the document unattached. Returns a report (what was applied, what was refused and why, and the transaction it ended up filed against). Pass dryRun to preview without writing. Never accepts supplier_create or a duplicate warning. Write.
dryRun boolean | null- Preview only: report what WOULD be applied, write nothing.
id* string | integer
incomingInvoices_applySuggestion
read
Accept one of Flowtly's own suggestions on an incoming invoice — the same proposals a human sees in the app (supplier match, cost group, matching bank transaction, duplicate warning). Read them first with incomingInvoices_suggestions, then apply one by its id. Prefer this over guessing: Flowtly's matcher, not the agent, decides what is plausible. Write.
suggestionId string | nullaction string | nulloverrides array | nullid* string | integer
incomingInvoices_checkEInvoices
read
Pull any new KSeF e-invoices into the org — what the app's "Sprawdź e-faktury" button does. Call this before concluding that a supplier's invoice is missing: without it you cannot tell "the supplier never sent it" from "our sync has not run yet". Returns once the fetch is queued; re-read incomingInvoices_list afterwards to see what arrived. Write.
No parameters.
incomingInvoices_create
write
File an incoming (supplier) invoice or supporting document into accountancy — pass the bytes as base64 with a fileName and receivedAt. Flowtly OCRs it and suggests a supplier and a matching bank transaction. The file is fingerprinted as externalId 'upload_sha256:<sha256 of the bytes>': to avoid a duplicate, hash the bytes and check incomingInvoices_list for that externalId BEFORE uploading. Write.
fileBase64* string- The document's bytes, base64-encoded (a PDF, image, or XML invoice).
fileName* string- Filename for the upload, e.g. Invoice-2026-07-0007.pdf.
receivedAt* string- When the document reached the org (ISO-8601) — e.g. the date of the email that carried it.
mimeType string- MIME type of the bytes, e.g. application/pdf.
type string- invoice = the cost document itself. supporting_document = a payment receipt or annex filed alongside one.
contractor string | integer- Supplier this invoice is from — an id or IRI from suppliers_list. Optional: omit it and Flowtly's OCR suggests a supplier for a human to confirm.
transaction string | integer- Bank transaction this document settles — an id or IRI from transactions_list. Optional: omit it and Flowtly suggests a match.
currency string- Currency IRI, e.g. /currencies/1. Optional.
relatedMonth string- Accounting month this cost belongs to (ISO-8601 date). Optional.
dueDate string- Payment due date (ISO-8601). Optional.
note string- Free-text note. Optional.
incomingInvoices_get
read
Get one incoming (supplier) invoice or supporting document by id, with its OCR'd fields and current match state.
id* string | integer
incomingInvoices_list
read
List incoming (supplier) invoices and supporting documents — the accountancy inbox. An incoming invoice IS a document attached to a bank transaction, so exists.transaction=false is how you find documents that are not yet matched to a payment. Filter also by status, relatedMonth, counterparty, project, tags, or hasDetectedProblems. Each document is fingerprinted as externalId 'upload_sha256:<sha256 of the bytes>' — hash a file and look for that externalId here BEFORE incomingInvoices_create, or you will file a duplicate.
exists.transaction booleanhasDetectedProblems booleanproperties array- Allows you to reduce the response to contain only the properties you need. If your desired property is nested, you can address it using nested arrays. Example: properties[]={propertyName}&properties[]={anotherPropertyName}&properties[{nestedPropertyParent}][]={nestedProperty}
status string- Filter transaction attachment by status based on custom logic
relatedMonth stringtags stringorder.receivedAt stringorder.name stringorder.amount stringname stringcounterparty anyproject stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
incomingInvoices_matchCandidates
read
List the bank transactions that could be the payment for this incoming invoice, ranked by the backend's own matcher. Reach for it when a document has no transaction attached and you need to choose one; prefer these candidates over guessing from amounts yourself.
exists.transaction booleanhasDetectedProblems booleanproperties array- Allows you to reduce the response to contain only the properties you need. If your desired property is nested, you can address it using nested arrays. Example: properties[]={propertyName}&properties[]={anotherPropertyName}&properties[{nestedPropertyParent}][]={nestedProperty}
status string- Filter transaction attachment by status based on custom logic
relatedMonth stringtags stringorder.receivedAt stringorder.name stringorder.amount stringname stringcounterparty anyproject stringid* string | integercursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
incomingInvoices_suggestions
read
Read Flowtly's own proposals for an incoming invoice — supplier match, cost group, matching bank transaction, duplicate warning. These are exactly the proposals a human sees in the app. Read them first, then apply one by id with incomingInvoices_applySuggestion, or take them all with acceptAllSuggestions. Pass refresh to recompute rather than serve the cached set.
exists.transaction booleanhasDetectedProblems booleanproperties array- Allows you to reduce the response to contain only the properties you need. If your desired property is nested, you can address it using nested arrays. Example: properties[]={propertyName}&properties[]={anotherPropertyName}&properties[{nestedPropertyParent}][]={nestedProperty}
status string- Filter transaction attachment by status based on custom logic
relatedMonth stringtags stringorder.receivedAt stringorder.name stringorder.amount stringname stringcounterparty anyproject stringrefresh boolean- Force a rebuild instead of returning the cached suggestions. Suggestions are cached; this is the only way to regenerate ones that are stale or wrong. The transaction-match rebuild runs synchronously; the OCR/LLM rebuild is dispatched async.
id* string | integercursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
incomingInvoices_suggestionsDebug
read
Explain WHY an incoming invoice's suggestions came out as they did — the matcher's scoring, for diagnosing a missing or wrong suggestion. Diagnostic only; use incomingInvoices_suggestions for normal work.
id* string | integer
leadActivities_create
write
Log ONE outreach touch on a lead — an invite sent, an invite accepted, a message, a reply, a call, a follow-up (lead + type + occurredAt required; channel, contact, body optional). THIS is where a prospect's outreach history belongs: a crmNote is freeform commentary, an activity is the structured, filterable touch-log the prospecting queue timeline renders. Do NOT narrate touches into a note. type: invite_sent | invite_accepted | message_sent | reply_received | call | meeting | follow_up | …; channel: linkedin | email | phone | …. Write.
lead* stringcontact string | nulltype* stringchannel string | nulloccurredAt* stringbody string | nullexternalId string | nullthreadId string | nullfromMailbox string | null
leadActivities_delete
write
Delete a logged outreach activity by id. Write.
id* string | integer
Get one lead activity (outreach touch) by id.
id* string | integer
List a lead's outreach touches — its activity timeline (invite sent, replies, calls, follow-ups). Filter by lead to read one prospect's history. This is the structured counterpart to crmNotes_list: activities are the typed, dated touch-log; notes are freeform commentary.
lead anycontact anytype anychannel anyexternalId anythreadId anyoccurredAt.before stringoccurredAt.strictly_before stringoccurredAt.after stringoccurredAt.strictly_after stringorder.occurredAt stringorder.type stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
leadActivities_update
write
Update a logged outreach activity by id (type, channel, occurredAt, body). Write.
contact string | nulltype stringchannel string | nulloccurredAt stringbody string | nullexternalId string | nullthreadId string | nullfromMailbox string | nullid* string | integer
leadContacts_create
write
Add a contact person to a lead (lead + name required; email, phone, role, linkedinUrl, isPrimary optional). A contact's LinkedIn URL belongs in linkedinUrl, NOT in a crmNote. Write.
lead stringname* stringemail string | nullphone string | nulllinkedinUrl string | nullrole string | nullisPrimary boolean
leadContacts_delete
write
Delete a lead contact by id. Write.
id* string | integer
Get one lead contact by id.
id* string | integer
List the contact people attached to leads. Filter by lead to read one prospect's contacts, or by email to find which lead a message came from.
lead anyemail anylinkedinUrl anycursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
leadContacts_update
write
Update a lead contact by id — e.g. set linkedinUrl / email / phone once you find them. Write.
lead stringname stringemail string | nullphone string | nulllinkedinUrl string | nullrole string | nullisPrimary booleanid* string | integer
leadListMemberships_create
write
Add a lead to an outbound list (list + lead required; status optional). Write.
list* stringlead* stringstatus stringlastContactedAt string | null
leadListMemberships_delete
write
Remove a lead from an outbound list. Write.
id* string | integer
leadListMemberships_get
read
Get one lead-to-list membership by id.
id* string | integer
leadListMemberships_list
read
List which leads sit on which outbound prospecting lists, with each one's outreach status (contacted / replied / bounced). Filter by list, lead or status — this is how you read the state of a campaign.
list anylead anystatus anycursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
leadListMemberships_update
write
Update a lead’s membership in a list — e.g. set outreach status (contacted/replied/bounced). Write.
list stringlead stringstatus stringlastContactedAt string | nullid* string | integer
Create an outbound prospecting list (name required). Write.
name* stringdescription string | nullowner string | nullchannel string | nullstatus stringsegment string | null
Delete an outbound list by id. Write.
id* string | integer
Get one outbound prospecting list by id.
id* string | integer
List outbound prospecting lists. Use it to resolve the list id that leadListMemberships_create takes.
status anychannel anycursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Update an outbound list by id. Write.
name stringdescription string | nullowner string | nullchannel string | nullstatus stringsegment string | nullid* string | integer
Get one lead lost-reason by id.
id* string | integer
leadLostReasons_list
read
List the reasons a lead can be marked lost, in order.
order.position stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Import many leads in ONE call, each with its contacts, list membership and outreach activities nested — the server creates the lead then threads its id into the children, so you never juggle intermediate IRIs. Idempotent by natural keys (companyName / email / (list,lead) / (type,occurredAt,contact)): safe to re-run and to chunk (≤100 leads/call). This is the bulk path a campaign import should use instead of N leads_create calls. Write.
list objectleads* array
Convert a qualified lead into a Client + one contact per lead-contact + an open Deal. Requires an existing client (the lead’s client or a clientId in the body). Write.
companyName string | nullwebsite string | nullsource string | nullowner string | nullclient string | nullindustry string | nulllinkedinUrl string | nulldoNotContact boolean- getDoNotContact(), NOT isDoNotContact() — see the property's comment. An
is*() accessor is invisible to API Platform's readability check and the flag
would be silently dropped from every payload.
companySize string | nullstage string | nullid* string | integer
Create a lead (outbound/inbound prospect target; companyName, source, status, owner, linked client optional). Write.
companyName string | nullwebsite string | nullsource string | nullowner string | nullclient string | nullindustry string | nulllinkedinUrl string | nulldoNotContact boolean- getDoNotContact(), NOT isDoNotContact() — see the property's comment. An
is*() accessor is invisible to API Platform's readability check and the flag
would be silently dropped from every payload.
companySize string | nullstage string | null
Check whether a prospect is already in the CRM, using the same filters as leads_list (companyName, source, owner, …). Call this BEFORE leads_create: a duplicate lead splits the outreach history across two records, and nothing downstream will merge them for you.
status anysource anyowner anyclient anycompanyName stringlinkedinUrl anydoNotContact booleancreatedAt.before stringcreatedAt.strictly_before stringcreatedAt.after stringcreatedAt.strictly_after stringclosedAt.before stringclosedAt.strictly_before stringclosedAt.after stringclosedAt.strictly_after stringorder.createdAt stringorder.companyName stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Delete a lead by id (soft delete). Write.
id* string | integer
Get one lead by id — company, website, source, status, owner and the client it converted to, if any.
id* string | integer
List leads — prospect targets, before qualification. Filter by status, source, owner, client, companyName, or createdAt/closedAt ranges. A qualified lead becomes a Client plus an open Deal via leads_convert; until then it lives only here, not in clients_list.
status anysource anyowner anyclient anycompanyName stringlinkedinUrl anydoNotContact booleancreatedAt.before stringcreatedAt.strictly_before stringcreatedAt.after stringcreatedAt.strictly_after stringclosedAt.before stringclosedAt.strictly_before stringclosedAt.after stringclosedAt.strictly_after stringorder.createdAt stringorder.companyName stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Update a lead by id (company, website, source, status, owner, linked client). Write.
companyName string | nullwebsite string | nullsource string | nullowner string | nullclient string | nullindustry string | nulllinkedinUrl string | nulldoNotContact boolean- getDoNotContact(), NOT isDoNotContact() — see the property's comment. An
is*() accessor is invisible to API Platform's readability check and the flag
would be silently dropped from every payload.
companySize string | nullstage string | nullid* string | integer
Get one lead stage by id.
id* string | integer
List the stages a lead moves through, in order. Leads have their own stage set — deals use stages_list, which is a different thing.
order.position stringorder.label stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Return the organization this MCP connection is bound to — { orgId, name, slug, userId }. Call it to confirm WHICH tenant you are about to write into before any create/update: the connection is pinned to exactly one org by the token, and writing prospects/records into the wrong org is a real incident. Read-only.
No parameters.
organizationIcon_upload
read
Upload/replace the organization's icon/favicon (base64 image + contentType + filename). Read the current one via configs_get organization-icon-url. Write.
bytesBase64* string- The image file bytes, base64-encoded.
contentType* string- The image MIME type, e.g. image/png, image/jpeg, image/svg+xml.
filename* string- A filename for the upload, e.g. logo.png.
organizationLogo_upload
read
Upload/replace the organization's logo (base64 image + contentType + filename). Read the current one via configs_get organization-logo-url. Write.
bytesBase64* string- The image file bytes, base64-encoded.
contentType* string- The image MIME type, e.g. image/png, image/jpeg, image/svg+xml.
filename* string- A filename for the upload, e.g. logo.png.
Get an organization by id. WARNING — this does NOT tell you which organization you are connected to. An OAuth connection is pinned to exactly one org (token-bound), but this endpoint returns any org the connected USER is a member of, so a successful read here reads like confirmation you are working in that org when you may not be. To verify the tenant you are actually operating on, read tenant-scoped data instead — people_list or clients_list — and never start a bulk write on the strength of this call alone.
id* string | integer
Create a person/employee record (firstname + lastname required; optional companyEmail, contactEmail, contactPhone). Write.
companyEmail string | nullcontactEmail string | nullcontactPhone string | nullbirthday string | nullfirstname* string | nulllastname* string | nullphoneTextAllowed booleantracksTime boolean- Whether this employee is expected to log working time. When false, the
time-tracking dashboard widgets (project timer + monthly working-hours)
are hidden for them. Defaults to true so existing employees keep their
current behaviour.
department string | nullreportsTo anydefaultProject string | null- Project this employee's working time is assigned to by default when not
logged against a specific project. Stored only for now — no automatic
assignment is wired up yet.
Delete an employee/person record by id (e.g. to remove a placeholder/dummy employee). Requires ROLE_EMPLOYEES_MANAGER; the backend runs a delete processor that also detaches related records. High-impact, irreversible. Write.
id* string | integer
Get one person/employee record by id — names, emails, phone, manager, and whether they are active.
id* string | integer
List people/employees. Filter by isActive, reportsTo (a manager's id), projectMembers.project, or search; page with cursor. People and employees share the same id, so this is how you resolve the employee id that work time, responsibilities, project membership and permission tools all expect.
isActive booleanid anyfirstname stringlastname stringreportsTo anyprojectMembers.project anyexists.userId booleanexists.reportsTo booleanexists.companyEmail booleansearch string- Free-text search over employee name and company email.
properties array- Allows you to reduce the response to contain only the properties you need. If your desired property is nested, you can address it using nested arrays. Example: properties[]={propertyName}&properties[]={anotherPropertyName}&properties[{nestedPropertyParent}][]={nestedProperty}
cursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
people_setPermissionGroups
read
Set (replace) a person's permission groups by numeric group ids (see permissionGroups_list — e.g. the "Business Owner" group grants ROLE_ADMIN). Grants access; does NOT create a login or email the person. Write.
id* string | integer- Person/employee id (or IRI). people and employees share the same id.
groupIds* array- Numeric permission-group ids the person should have (see permissionGroups_list). REPLACES their current set — pass every group they should keep. Empty array removes all groups.
Update a person/employee record by id (name, companyEmail, contactEmail, contactPhone, etc.). Write.
companyEmail string | nullcontactEmail string | nullcontactPhone string | nullbirthday string | nullfirstname string | nulllastname string | nullphoneTextAllowed booleantracksTime boolean- Whether this employee is expected to log working time. When false, the
time-tracking dashboard widgets (project timer + monthly working-hours)
are hidden for them. Defaults to true so existing employees keep their
current behaviour.
department string | nullreportsTo anydefaultProject string | null- Project this employee's working time is assigned to by default when not
logged against a specific project. Stored only for now — no automatic
assignment is wired up yet.
id* string | integer
permissionGroups_create
write
Create a permission group (name required; roles = list of ROLE_* strings it grants). Write.
code string | null- Stable code for default seed groups; null for org-created custom groups.
name* stringdescription string | nullroles array- ROLE_* string values
permissionGroups_get
read
Get one permission group by id, including the ROLE_* strings it grants.
id* string | integer
permissionGroups_list
read
List the org's permission groups and the roles each one grants — e.g. the "Business Owner" group grants ROLE_ADMIN. Read this before people_setPermissionGroups: the roles in the response are the authority on what a group actually permits, so you never have to guess from its name.
cursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
permissionGroups_update
write
Update a permission group's name, description, or granted roles by id. Write.
name stringdescription string | nullroles array- ROLE_* string values
id* string | integer
Get one sales pipeline by id.
id* string | integer
List sales pipelines. A pipeline owns an ordered set of stages — read them with stages_list filtered by pipeline.
cursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
List positions — the named roles (e.g. "Backend Engineer") that a project allocation fills. No filters; Position has pagination disabled, so this always returns the org's full role catalog in one call. Each item is {id, name, roles}. Use it to resolve the position name behind an allocations_list row's positionId, and to find the position id a resourcing import must match against.
order.name stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
resourcing_importTimeline
read
Import a resourcing allocation timeline sheet (fetch it via the Drive MCP, pass its CSV verbatim). This is a FULL-REPLACE mirror of the org's Allocation rows for `year`: rows in the sheet are created/updated, and any existing row for that year absent from the sheet is DELETED — not a merge. DRY-RUN BY DEFAULT: an omitted dryRun previews and writes nothing; pass dryRun:false to apply. The report gives `created` / `replaced` plus `unmatchedPeople` / `unmatchedProjects`. TWO THINGS ARE EASY TO MISS: a sheet row whose project does not resolve is SKIPPED while the call still reports success, so a green result can hide a partial import; and a role code the position catalogue does not already hold is CREATED as a new position rather than rejected — see `createdPositions`. Both are called out in `warnings` when they happen; surface that to the user rather than reporting only `created`. A sheet that parses to zero rows is refused (it looks exactly like a bad read about to wipe the whole timeline) unless you pass force:true. Read allocations_list afterwards to see what landed. High-impact. Write.
csv* string- The allocation-timeline sheet as CSV (fetch it via the Drive MCP). A role code the position catalogue does not already hold is CREATED as a new position rather than rejected — check `createdPositions` and `warnings` in the report.
dryRun boolean- Preview only; report what WOULD change and write nothing. Default true.
force boolean- Allow an apply whose parse produced zero rows (would otherwise refuse to wipe).
year number- Planning year the day columns fall in.
responsibilities_create
write
Create a responsibility inside a group (responsibilityGroup = group id or IRI, + name, required; optional description; optional parent = another responsibility IRI for nesting). Assign people to it via responsibilityEmployees_create. Write.
parent anyresponsibilityGroup* stringname* stringdescription stringchildren array
responsibilities_get
read
Get one responsibility by id.
id* string | integer
responsibilities_list
read
List responsibilities inside a RACI group. Filter by responsibilityGroup. Responsibilities can nest via parent; people are assigned to them through responsibilityEmployees, not directly.
responsibilityGroup anycursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
responsibilities_update
write
Update a responsibility by id (name, description, parent, responsibilityGroup = group id or IRI). Write.
parent anyresponsibilityGroup stringname stringdescription stringchildren arrayid* string | integer
responsibilityEmployees_create
write
Assign an employee to a responsibility (responsibility = responsibility id or IRI, employee = employee id or IRI, percentage 0-100, all required; optional targets and description). Write.
responsibility* string | nullemployee* string | nullpercentage* integertargets stringdescription string
responsibilityEmployees_delete
write
Remove an employee's assignment from a responsibility by id. Write.
id* string | integer
responsibilityEmployees_get
read
Get one responsibility assignment by id.
id* string | integer
responsibilityEmployees_list
read
List who is assigned to which responsibility, and at what percentage. Filter by employee to read one person's entire RACI load across every group.
employee anycursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
responsibilityEmployees_update
write
Update a responsibility assignment by id (percentage, targets, description). Write.
responsibility string | nullemployee string | nullpercentage integertargets stringdescription stringid* string | integer
responsibilityGroups_create
write
Create a responsibility group / RACI area (name required; optional description and responsibleEmployee = the accountable person, given as a plain employee id like 6 (from people_list) or the /people/6 IRI). This is the top-level 'Odpowiedzialności' item. Add individual responsibilities under it via responsibilities_create. Write.
responsibleEmployee* string | nullname* stringdescription stringresponsibilities array
responsibilityGroups_get
read
Get one responsibility group by id.
id* string | integer
responsibilityGroups_list
read
List responsibility groups / RACI areas — the top-level "Odpowiedzialności" items, each with an accountable person. Individual responsibilities hang underneath them.
cursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
responsibilityGroups_update
write
Update a responsibility group by id (name, description, responsibleEmployee = employee id or IRI). Write.
responsibleEmployee string | nullname stringdescription stringresponsibilities arrayid* string | integer
Get one deal stage by id.
id* string | integer
List deal stages, in order. Filter by pipeline. deals_create requires a stage id from here, and moving a deal between stages is what dealStageHistories records.
pipeline anyorder.position stringcursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
tagDefinitions_create
write
Create a tag definition (name, level, tagGroup required) within a tag group. Write.
name* stringlevel* integerlabel stringtagGroup* string
List tag definitions — the tags that can be attached to records, each inside a tag group. tags_create takes a tagDefinition id from here plus the record to attach it to.
cursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Create a tag group (name required) to organize related tag definitions. Write.
name* stringallowedRelations array | null
List tag groups — the containers that organize tag definitions.
cursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Attach a tag definition to a record (tagDefinition + relationName + relationId; e.g. relationName "counterparty" to tag a supplier/vendor). Write.
tagDefinition* stringrelationName stringrelationId* stringweight string
Create a tax rule. Write.
taxGroup* stringcountry* stringtaxAmount* string
List tax rules — the rates and the periods they apply to. Filter by taxGroup.
taxGroup anycursor string- Opaque pagination token from a previous response's nextCursor. Omit for the first page. When present, other filters are ignored — the cursor already encodes them.
itemsPerPage integer- Page size (max 100). Ignored when cursor is set.
Update a tax rule by id. Write.
taxGroup stringcountry stringtaxAmount stringid* string | integer