- Brand
- easySales
- Category
- Sales & CRM
- Primary Subcategory
- B2B Sales CRM Platforms
Integration details
Description
Connect ChatGPT to easySales CRM to find customers and contacts, manage follow-up tasks, and work with quotations and invoices within your account permissions. Requires an existing easySales account connected through OAuth. The integration manages business and payment records; it does not charge cards or transfer money.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- B2B Sales CRM Platforms
- Secondary Subcategories
- None listed
- Brand
- easySales
- Access
- Account required
- First tracked
- 2026-10-28
- Tool count
- 211
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
Your score is coming
ChatGPT now suggests Plugins on its own when they match a user's request.Your Plugin Discovery Score measures how often yours appears, and it will show here as soon as it’s ready.
What discovery looks like

Get alerts for easySales
Get updates when easySales’s Discoverability Score or category rank changes.
Competing in ChatGPT B2B Sales CRM Platforms
View Category211 tools agents can invoke
One record’s timeline, newest first: the activity threads linked to it that this user can see and, unless includeDocumentEvents is false, what happened to the record and its documents (created, issued, paid, …). object { type, id } is the record — type is account, contact, lead, opportunity, quotation, invoice, creditNote, receipt, refund or contract — and must be one this user may open, or the answer is not found. kinds limits the threads to note, task, event and call (call = a communication); subTypeIds to those sub-types (activity.sub_types; none for threads without one). rollup true (default) on an account or contact includes its quotations’, invoices’ and opportunities’ activities. limit is at most 50; pass nextCursor back as cursor. Each row has entry activity (the thread’s fields as activity.feed gives them) or entry documentEvent (eventId, at in UTC, verb, variant, objectType, objectId, objectLabel and who did it). link on a record is its page in the web app; cite it when you name the record.
activity.timeline
Close an open quotation as accepted (won true) or rejected (won false); a draft is refused — finalise it first. This is final: a closed quotation cannot be reopened or edited again. One exception: an accepted quotation with no invoice and no billing plan may still be rejected (won false), for example a duplicate accepted by mistake. Returns { dryRun, record: { id, status } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
quotation.close
Add and remove members of a space this user owns, or of any space when they may manage others’ activities. id is the space; add and remove are user ids (at most 200 each; activity.pick_user finds them). Never this user (they join or leave themselves with space.join and space.leave) and never the owner (hand the space over first with space.update). A removed member of a members-only space no longer sees its threads unless named in them, and an added one sees all of them, their history included: dryRun true answers audienceGains and audienceLosses, the people who would gain or lose them (none for a company space, whose threads everyone sees). Added people are told in their Updates, and the addition is shown in the space. Returns { dryRun, record: { spaceId }, addedUserIds, removedUserIds }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
space.set_members
Allocate the unapplied money of an existing receipt to issued invoices of the same account and currency — no new receipt and no new number. This reduces what the customer owes on each invoice at once; removing one of the payments it writes (invoice.delete_payment) reverses it. A security deposit is refused here. receiptId is required (receipt.search: a receipt with unapplied above zero). allocations is a list of { invoiceId, amount }, each invoice named once, each amount an exact decimal string no more than the invoice still owes, together no more than the receipt’s unapplied money. date is the day the money is allocated, yyyy-MM-dd, blank for today; not before the receipt’s or an invoice’s own date, and not in the future. Allocating may be switched off for this company, and the answer then says so. Returns { dryRun, record: { id, number, date, allocated, unapplied, invoices: [{ invoiceId, paymentId, amount, status, paidAmount, outstandingAmount, creditedAmount }] } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
receipt.apply
Use a security deposit a receipt holds as payment for issued invoices of the same account and currency — the Allocate deposit action. Each invoice owes that much less at once and the deposit held falls by the same amount, dated today; it is undone by removing the payment it wrote from the invoice (invoice.delete_payment). receiptId is a receipt whose nature is deposit (receipt.get: unapplied is what is held). allocations is a list of { invoiceId, amount }, each invoice named once, each amount an exact decimal string no more than the invoice still owes, together no more than is held. Needs access to all invoices, not only the user’s own; may be switched off for this company, and the answer then says so. Returns { dryRun, record: { id, number, date, held, invoices: [{ invoiceId, paymentId, amount, outstandingAmount, status }] } }, the amounts in the receipt’s currency. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
receipt.apply_deposit
Apply an issued credit note’s remaining credit to invoices of the same account and currency. This reduces what the customer owes on each invoice at once; creditNote.unapply reverses one allocation. creditNoteId is required. allocations is a list of { invoiceId, amount }, each invoice named once; amount is an exact decimal string in the note’s currency, such as "100.00", above zero. Each amount may not exceed what its invoice still owes, and together they may not exceed the note’s remaining credit (creditNote.get’s credit). allocationDate is yyyy-MM-dd, blank for today, and cannot be in the future. Applying credit may be switched off for this company, and the answer then says so. Returns { dryRun, record: { creditNoteId, allocations: [{ invoiceId, allocationId, amount, status, paidAmount, outstandingAmount, creditedAmount }], credit: { face, allocated, refunded, remaining } } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
creditNote.apply
Archive (Done) this user’s own Updates by id (at most 200, from notification.list): they leave the inbox and stay in the archived view. Returns { dryRun, record: { updated } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
notification.archive
Attach the supplier’s document — a file of at most 5 MB — to a supplier invoice recorded on a purchase order; larger files are attached from the web. purchaseBillId is the supplier invoice (purchaseOrder.bills); fileName is its name; contentType its MIME type, such as application/pdf — a PDF, an image, a Word, Excel or PowerPoint file or a CSV; dataBase64 the file’s bytes in base64. A supplier invoice holds at most 10 files, its order must be issued or closed, and a voided invoice takes none. The dry run only checks that this user can see the supplier invoice: nothing is uploaded, and the type, the size, the limit and the right to change the order are checked when the file is attached. Returns { dryRun, record: { id, purchaseBillId, fileName, contentType, size } }; a file is removed with purchaseOrder.remove_bill_file. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
purchaseOrder.attach_bill_file
Attach a file of at most 5 MB to an activity this user may edit; larger files are attached from the web. activityId is the activity (a thread’s first activity or a reply); fileName is its name; contentType its MIME type, such as application/pdf; dataBase64 the file’s bytes in base64. inline true shows a PNG, JPEG, GIF or WebP image in the body (reference it as  in a later edit); no other type can be inline. An activity holds at most 20 files, and a thread in a closed space takes none. The dry run only checks that this user can see the activity: nothing is uploaded. Returns { dryRun, record: { id, activityId, fileName, contentType, size, inline } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
activity.attach_file
The events, tasks with a due day and communications (kind call) between from and to (yyyy-MM-dd, both included, in this user’s own time zone; at most 62 days), as the web’s calendar shows them. scope is mine (default: items this user is involved in), team (this user and their team) or all (everything this user can see); userIds (at most 50) narrows to those people’s items; kinds is a list of event, task and call (call = a communication); subTypeIds narrows to those sub-types (activity.sub_types; none for items without one; busy blocks are never narrowed); spaceId shows one space’s items (space.search finds it; a space this user may not see is not found). Each row has the item’s fields as activity.my_work gives them, without group. busy (default true; not with scope mine) adds busy blocks: for a team colleague’s event this user cannot see, only who (userId, name) and when (startAt and endAt in UTC, or allDay with startDate and endDate) — never what, where or which space, and never for an event in a members-only space. documentDates (default false; not with spaceId) adds documents: the dated days (due, expiry, start and the like) of opportunities, quotations, invoices, contracts and other records this user may list, each as type, id, label, field (the date column) and day; in scope mine only records this user owns, in team those this user or their team own. tooMany true means more than 2000 items matched: narrow the range or the filters. Only items in threads this user can see are listed. link on a record is its page in the web app; cite it when you name the record.
calendar.range
Cancel an issued credit note. This is final: the note stays on record as Cancelled, every allocation of its credit is released, and each invoice it credited owes that amount again. A draft is refused (delete it with creditNote.delete), and so is a note that has had money refunded out of it. id is required; reason is optional and is added to the note’s remark. Returns { dryRun, record: { id, status, released: [{ id, status, outstandingAmount, creditedAmount }] } }, the invoices whose credit was released, in the note’s currency. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
creditNote.cancel
Cancel an issued purchase order. This is final: the order stays on record as Cancelled with its number, counts as no cost, and cannot be reopened or changed again. A draft is refused (delete it with purchaseOrder.delete). It is also refused while a supplier invoice or a payment stands on the order: void them first with purchaseOrder.void_bill and purchaseOrder.void_payment, or close the order with purchaseOrder.close instead. id is the order; reason, up to 200 characters, is required and recorded. Returns { dryRun, record: { id, status } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
purchaseOrder.cancel
Cancel a quotation’s live billing plan. This is final for that plan: it stays on record as cancelled and cannot be brought back, though a new plan can be created afterwards; invoices already issued for its lines are untouched. Refused while a draft invoice bills one of its lines: issue or delete that draft first. planId is the plan’s id (quotation.billing_plan) and is required, except where invoicing is not part of the company’s plan and quotation.billing_plan shows no schedule: there leave it out and the quotation’s live plan is cancelled. reason is optional. Returns { dryRun, record: { id, status } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
quotation.cancel_billing_plan
Cancel an issued invoice — the Cancel invoice action. This is final: the invoice becomes Cancelled for good and a credit note for the whole invoice is issued at once, with the next credit note number. A draft is refused (delete it with invoice.delete). It is also refused while money or credit stands on the invoice — a payment, applied credit, a refund, a bad debt written off or another credit note in force — and the answer names what to reverse first; invoice.get’s voidBlockedReason says so in advance. id is required. dryRun true checks it without cancelling anything or taking a number. Returns { dryRun, record: { id, status, creditNote: { id, number, face } } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
invoice.void
Change a contact. id is required. Only the fields sent change; every field left out keeps its current value, and "" clears a field (Name cannot be cleared). AccountID, when sent, moves the contact to that account, which must be one this user may see and not a personal account. Salutation is one of Mr., Ms., Mrs., Dr. or Mdm., or blank. The owner is not changed here: that is contact.change_owner. A personal account’s own contact is changed with its account in easySales, and is refused here. Returns { dryRun, record: { id } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
contact.update
Hand a contact to another user. Only that contact moves — its account and documents keep their owners — and the previous owner may lose access to it; only another change of owner moves it back. With transferOpenActivities true (default false), the open tasks assigned to the previous owner and the future events they organise, on threads linked to the contact, move too (the author never changes). id is the contact ID; toUserId is the new owner’s user ID, and must be an active user whose role can view contacts. Only the contact’s owner, a manager above the owner, or a role allowed to transfer records may do this. A personal account’s own contact moves only with its account (account.change_owner). Returns { dryRun, record: { batchId, restricted, counts } }: counts is the number of each kind moved (account, contact, opportunity, quotation, invoice, creditNote, task, event), leaving out members-only items this user cannot see; restricted is how many open tasks and events stayed because the new owner is not in their members-only space - ask that space’s owner to add them, then change the owner again. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
contact.change_owner
Change a draft credit note; an issued or cancelled one is refused. id is required. Every header field left out is saved blank, so send the whole credit note as it should read afterwards — creditNote.get gives the current values. SalesID may be left out; a different one is refused. items, when sent, replaces every line, with the line rules of creditNote.create; leave items out to keep the lines. TaxRate is a fraction — 0.09 for 9%, at most 1 — and must be the invoice’s. Returns { dryRun, record: { id, name, status, invoiceId } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
creditNote.update
Change a payment recorded on a purchase order. id is the payment (purchaseOrder.bills lists the order’s payments). Every field is restated: PaymentDate (yyyy-MM-dd, not later than today) and Amount (an exact decimal string above zero in the order’s currency) are required, and Method, Reference, Remark and PurchaseBillID left out are saved blank — purchaseOrder.bills gives the current values. Method is one of the codes of purchaseOrder.payment_methods; PurchaseBillID, when it changes, must be a live supplier invoice of the same order. The order must be issued or closed, and a voided payment cannot be changed. The order’s paid state follows at once, and warnings reports a payment above the invoices or the order’s total. Returns { dryRun, record: { id, purchaseOrderId, replayed, payment }, warnings }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
purchaseOrder.update_payment
Change a personal account. Only the fields sent change — inside contact too — and "" clears one (Name cannot be cleared). A business account is refused (account.update), and the owner is not changed here (account.change_owner). Returns { dryRun, record: { id } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
account.update_personal
Change a product. Only the fields sent change; "" clears a text field or a price, and null clears CategoryID or ManufacturerID. A new name that another active product already has is refused. Returns { dryRun, record: { id, ItemType } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
product.update
Change a draft or issued purchase order; a cancelled one is refused, and on a closed one only OpportunityID may change (reopen it with purchaseOrder.reopen to edit). id is required. Every header field left out is saved blank or at its default — a TaxRate left out is saved as 0 — so send the whole order as it should read afterwards: purchaseOrder.get gives the current values. items, when sent, replaces every line, with the line rules of purchaseOrder.create; leave items out to keep the lines and totals as they are, and send [] only to remove every line. On an issued order the supplier account and contact cannot change (cancel it and raise a new one), and once a supplier invoice is recorded its lines, currency, tax rate and exchange rate are locked, and its currency once a payment is recorded — the answer says which. An order changed after it was marked as sent shows as amended after sent until it is marked again. TaxRate is a fraction — 0.09 for 9%, at most 1. exchangeRateOverride left out keeps the order’s rate, null returns it to the company’s own rate, and a string is a typed rate above zero. Amounts are exact decimal strings. The owner is not changed here: use purchaseOrder.change_owner. Returns { dryRun, record: { id, name } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
purchaseOrder.update
Hand a purchase order to another user — the Change Owner action on the purchase order page. Only that order moves; its supplier account, contact, opportunity, supplier invoices and payments stay where they are, and the previous owner may lose access to it; only another change of owner moves it back. id is the order; toUserId is the new owner’s user ID (purchaseOrder.get’s OwnerID and account.get’s OwnerID are user IDs in use), and must be an active user whose role can view purchase orders. Only the order’s owner, a manager above them, or a role allowed to transfer records may do this. Returns { dryRun, record: { batchId, restricted, counts: { account, contact, opportunity, quotation, invoice, creditNote, purchaseOrder, task, event } } }, the number of each moved. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
purchaseOrder.change_owner
Change a draft or open quotation; a closed one is refused. id is required. Every header field left out is saved blank, so send the whole quotation as it should read afterwards — quotation.get gives the current values. SalesID may be left out; sending a different one is refused, because changing the salesperson is not an edit. items, when sent, replaces every line, with the line rules of quotation.create; leave items out to keep the lines and totals as they are, and send [] only to remove every line. TaxRate is a fraction — 0.09 for 9%, at most 1. Amounts are exact decimal strings. Returns { dryRun, record: { id, name, refNo, createdProducts } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
quotation.update
Hand a quotation to another salesperson — the Change Owner action on the quotation page. Only that quotation moves; its account, contact and invoices keep their owners, and the previous salesperson may lose access to it; only another change of owner moves it back. With transferOpenActivities true (default false), the open tasks assigned to the previous salesperson and the future events they organise, on threads linked to the quotation, move too (the author never changes). id is the quotation ID; toUserId is the new salesperson’s user ID, and must be an active user whose role can view quotations. Only the quotation’s salesperson, a manager above them, or a role allowed to transfer records may do this. Returns { dryRun, record: { batchId, restricted, counts } }: counts is the number of each kind moved (account, contact, opportunity, quotation, invoice, creditNote, task, event), leaving out members-only items this user cannot see; restricted is how many open tasks and events stayed because the new owner is not in their members-only space - ask that space’s owner to add them, then change the owner again. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
quotation.change_owner
Change a recurring invoice that is active or paused. Only the fields sent change: contactId, paymentTerm, recipientUserId, autoDraft (switching it on raises drafts automatically from today, never for periods already past), endDate (yyyy-MM-dd, or null to remove it; only on a recurring invoice with no fixed number of periods, and refused if it would cut off a period that is already invoiced or has a draft), ownerUserId (only for a user who may edit every invoice) and template, which replaces the tax, text and lines whole — its TaxRate is a fraction — 0.09 for 9% — and its items are as in recurringInvoice.create. A new template applies to drafts raised afterwards; invoices and drafts already raised keep their figures. The currency and the schedule’s frequency, interval and start date cannot change: end it and create another. id and version are required; version is the token recurringInvoice.get returned, and a recurring invoice someone else changed since is refused so their change is not lost — read it again and retry. Returns { dryRun, record: { id, status, currencyCode, autoDraft, autoSince, periodAmount, version, periods: [{ id, seq, name, invoiceDate, status }] } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
recurringInvoice.update
Change a space this user owns, or any space when they may manage others’ activities: name, description (null clears it), status (open, or closed: a closed space takes no new threads), visibility (company or members; only a member may change it) and ownerUserId (hand it over to someone who is already a member; the old owner stays a member). Send only what changes. A visibility change moves who can see every thread in the space: dryRun true answers audienceGains (company: everyone who may see activities) and audienceLosses (the company audience a members-only space takes away); the other checks are made when the change is saved. Returns { dryRun, record: { id, changed } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
space.update
Change a supplier invoice recorded on a purchase order. id is the supplier invoice (purchaseOrder.bills). Every field is restated: SupplierInvoiceNo, SupplierInvoiceDate (yyyy-MM-dd), NetAmount and TaxAmount are required, and DueDate and Remark left out are saved blank — purchaseOrder.bills gives the current values. The amounts are exact decimal strings in the order’s currency, as the supplier printed them. exchangeRateOverride left out keeps the invoice’s rate, null takes the company’s current rate, and a string is a typed rate above zero. TaxTreatment left out keeps a treatment someone chose, with its reason; sending one that differs from the company’s tax rule needs TreatmentReason. The order must be issued or closed, and a voided invoice cannot be changed. The cost on the order and its opportunity follows at once, and warnings reports over-billing or a repeated invoice number. Returns { dryRun, record: { id, purchaseOrderId, replayed, bill }, warnings }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
purchaseOrder.update_bill
Change a business account. id is required. Only the fields sent change; every field left out keeps its current value, and "" clears a field (Name cannot be cleared). A change that makes it the same name, or the same registration number (RegNum), as another account in the same country (Billing_Country) is refused as a duplicate. The owner is not changed here: that is account.change_owner. A personal account is refused. Returns { dryRun, record: { id } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
account.update
Hand an account to another user. The account moves with every contact under it and, unless options say otherwise, the previous owner’s open opportunities, open quotations, draft invoices and credit notes, and the open tasks assigned to them and future events they organise on the threads about what moves (never who wrote them); the previous owner may lose access to all of them, and only another change of owner moves them back. id is the account ID; toUserId is the new owner’s user ID, and must be an active user whose role can view what moves. Only the account’s owner, a manager above the owner, or a role allowed to transfer records may do this. options, all optional: openOpportunities, openQuotes, openDocuments and openActivities (default true), closedDocuments (default false; true also moves accepted or rejected quotations and issued invoices and credit notes), keepAccountTeam (default true; false removes the account team). Returns { dryRun, record: { batchId, restricted, counts } }: counts is the number of each kind moved (account, contact, opportunity, quotation, invoice, creditNote, task, event), leaving out members-only items this user cannot see; restricted is how many open tasks and events stayed because the new owner is not in their members-only space - ask that space’s owner to add them, then change the owner again. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
account.change_owner
Change an invoice. id is required. Every header field left out is saved blank, so send the whole invoice as it should read afterwards — invoice.get gives the current values. SalesID may be left out; a different one is refused. Once an invoice is issued its lines, amounts, contact, dates, currency and tax are locked and a change to any of them is refused; its reference, terms and remark stay editable. items, when sent, replaces every line: each line names ProductID (product.search), or ProductID 0 with newProduct to create one, Qty with at most two decimals and UnitPrice as an exact decimal string; leave items out to keep the lines as they are. TaxRate is a fraction — 0.09 for 9%, at most 1. exchangeRateOverride, when sent, is a rate above zero, and null returns the invoice to the automatic rate; leave it out to keep the current one. taxCurrencyRateOverride, on a draft, is the SGD rate for an SG tax invoice’s SGD figures when the base currency is not SGD (frozen at issue); null returns it to the table rate; leave it out to keep it. Returns { dryRun, record: { id, name, refNo, status, paidAmount, outstandingAmount, creditedAmount, exchangeRate, exchangeRateSource, autoExchangeRate, exchangeRateAsOf, createdProducts } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
invoice.update
Hand an invoice to another salesperson — the Change Owner action on the invoice page. Only that invoice moves; its account, contact, quotation, payments and credit notes keep their owners, and the previous salesperson may lose access to it; only another change of owner moves it back. With transferOpenActivities true (default false), the open tasks assigned to the previous salesperson and the future events they organise, on threads linked to the invoice, move too (the author never changes). id is the invoice ID; toUserId is the new salesperson’s user ID, and must be an active user whose role can view invoices. Only the invoice’s salesperson, a manager above them, or a role allowed to transfer records may do this. Returns { dryRun, record: { batchId, restricted, counts } }: counts is the number of each kind moved (account, contact, opportunity, quotation, invoice, creditNote, task, event), leaving out members-only items this user cannot see; restricted is how many open tasks and events stayed because the new owner is not in their members-only space - ask that space’s owner to add them, then change the owner again. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
invoice.change_owner
Change an opportunity’s details. Only the fields sent change; "" clears SalesValue, TotalCost, CurrencyCode or Remark. Moving it to another account clears the primary contact unless PrimaryContactID is sent with it; null clears PrimaryContactID or OpportunityType. The stage is changed with opportunity.set_stage and the owner with opportunity.change_owner. Returns { dryRun, record: { id } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
opportunity.update
Hand an opportunity to another user. Only that opportunity moves — its account, quotations and invoices keep their owners — and the previous owner may lose access to it. toUserId must be an active user whose role can view opportunities. With transferOpenActivities true, the previous owner’s open tasks and future events on threads linked to the opportunity move too. Returns { dryRun, record: { batchId, restricted, counts } }: counts is how many records of each kind moved, restricted how many tasks and events stayed because the new owner is not in their members-only space. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
opportunity.change_owner
Change the nature of a receipt’s unapplied money: overpayment, prepayment or deposit (a refundable security deposit held for the customer). Changing it into a deposit cannot be changed back: a deposit leaves only by refund, by being used as payment, or by voiding the receipt. Refused once any of that money was allocated on a later day or refunded, where the receipt pays invoices and a deposit is asked for, and where the tax profile does not admit the nature on the receipt’s date (receipt.nature_options tells in advance). id is the receipt ID. Needs access to all invoices. Returns { dryRun, record: { id, number, nature, previous } }; nature equal to previous means nothing changed. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
receipt.set_nature
Records that already match the account or contact about to be created — call it before account.create, account.create_personal or contact.create. module is account or contact; name, regNum, email and phone are compared exactly, and excludeId leaves out the record being edited. Each match has the record ID, its name, its owner and team, and which value matched (reason); a match may be a record this user cannot open.
duplicate.check
Which natures (prepayment, deposit) the company’s tax profile admits for money received on receiptDate (yyyy-MM-dd, blank for today), before receipt.create or receipt.set_nature. refusals gives, per nature, the reason it is refused or null; invoiceOnReceipt says where recording it issues a deposit tax invoice, so receipt.create needs depositInvoice; taxOptions lists the taxes that invoice may be charged at (key, taxRateId, rate as a fraction, label, standard) and defaultTax the default’s key. Returns { found, record: { asOf, refusals, invoiceOnReceipt, taxOptions, defaultTax, taxName } }.
receipt.nature_options
Remove the gross margin typed by hand on an opportunity (deal), so that it shows its computed margin again — the Clear override action of the opportunity page. The typed figure and its reason no longer show on the opportunity or in the list; they stay in the opportunity’s change history, and the override can be set again with opportunity.set_margin_override. id is the opportunity (opportunity.profit shows its override, if any). Refused when the user may not edit the opportunity. Returns { dryRun, record: { id, cleared } }; cleared is false when there was no override to remove, and then nothing was changed. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
opportunity.clear_margin_override
Close an issued purchase order: no further supplier invoices are expected, so what is still unbilled stops counting as committed cost. The supplier invoices and payments already recorded stay, and payments can still be recorded on a closed order. Only an issued order can be closed. Reopening is purchaseOrder.reopen. id is the order. Returns { dryRun, record: { id, status } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
purchaseOrder.close
Mark a task or event done and create the follow-up in one step. id is the task or event; next is the new one: kind task or event, title (required), and the scheduling fields of activity.create (assigneeUserId, dueDate or dueAt, priority, startAt, endAt, allDay, startDate, endDate, location, subTypeId of next’s kind) and an optional md1 body. The new activity keeps the same links. Returns { dryRun, record: { id (the new one), rootId, rev, completedId } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
activity.complete_and_next
Copy a quotation into a new, independent draft — the Copy action of the quotation page. This is not a revision: nothing links the two, the quotation copied does not change, and it may be in any status (draft, open, accepted, rejected, superseded or expired); to make the next version of the same quotation use quotation.revise instead. The copy is a draft with its own draft number such as QD-10000002, owned by the user making it (not the original’s salesperson). Copied: the customer contact, the opportunity, the currency, payment term, heading, terms, remark and custom fields, and every line with its product, description, quantity, unit price, unit cost, unit, remark and tax code. Not copied: the status, sent marks, billing plan, invoices, activities, attachments and history. It is priced as a new offer today: taxes follow today’s rates (a rate no longer in force moves to the current rate of its kind, or to none), the exchange rate is today’s, the totals are recomputed from the lines, and the expiry restarts from today for the same number of days. What could not be carried over is left out and reported in warnings rather than refused; each warning has a code: lineDropped (line, productId, description — the product no longer exists, so that line was left out), taxFollowed (line, from, to — a tax rate, as a fraction such as 0.08, moved to today’s rate), taxRemoved (line, from — a tax that cannot be charged today was set to none), opportunityDropped (the opportunity is gone or not one this user may use), totalChanged (currency, from, to — the copy’s grand total differs from the original’s, as exact amounts). line is the line’s position in the original, counted from 1, and is null for the quotation’s own tax. Tell the user about every warning. Refused, with nothing saved, when the quotation does not exist or this user may not see it, when the user may not create quotations, when its contact is gone or not one this user may use, when there is no exchange rate for its currency, and when the company’s quotation limit is reached. id is the quotation to copy (quotation.get shows it). refNo, up to 100 characters, is an optional customer reference for the copy; left out, the copy keeps the original’s reference, or uses its own new number where the original’s reference was its number. A repeat answers the copy already made, with replayed true and no warnings, and never makes a second. dryRun true checks it without saving anything and without naming the new draft; its warnings are the ones the real copy would give. Returns { dryRun, record: { id (the new draft), name (its draft number), refNo, copiedFromId, replayed, warnings } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
quotation.copy
This user’s own message-centre counts: todo (To do items), unread (unread Updates this user can still see, at most 100), complete (false means the count stopped early and there may be more unread) and badge (todo plus unread, at most 100).
notification.count
Create a contact — a person at an account. Search first with contact.search (accountId narrows it to one account’s contacts) or lookup.resolve (entity contact) and use the contact that already exists rather than creating a second one for the same person: easySales does not refuse a duplicate contact. AccountID, the account the contact belongs to (account.search or lookup.resolve), is required and must be an account this user may see; a personal account takes no further contacts. Name is required. OwnerID, the user ID of the contact’s owner, is required: account.get’s OwnerID is a user ID in use. Salutation is one of Mr., Ms., Mrs., Dr. or Mdm., or blank. Every other field may be left out and is then blank. A company may require its own additional fields, which only a person in easySales can fill in; such a create is refused and the answer names the field. Returns { dryRun, record: { id } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
contact.create
Create a draft credit note against an issued invoice. A draft changes no balance and has no number until it is issued. InvoiceID, ContactID and CurrencyCode are required, and the currency and tax rate must be the invoice’s. SalesID, the salesperson’s user ID, is required. ReasonCode is one of creditNote.reasons’ codes (needed before it can be issued). CreditNoteDate is yyyy-MM-dd or blank. items is the line set: each line names ProductID (product.search), Qty with at most two decimals and UnitPrice as an exact decimal string, and the total is a positive amount. TaxRate is a fraction — 0.09 for 9%, at most 1. Returns { dryRun, record: { id, name, status, invoiceId } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
creditNote.create
Create a personal account — a private individual, saved as an account and its one contact together. Call duplicate.check first: a person with the same name and the same e-mail address or mobile number is refused as a duplicate. OwnerID is required (session.whoami gives this user’s own). contact holds the person’s Salutation, Email and MobileNumber; Name, PhoneNumber, the address and Remark are written to both. Returns { dryRun, record: { id } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
account.create_personal
Create a product or service in the catalogue. Search first with product.search: a name an active product already has is refused. ItemType is goods (default) or service. ListPrice and Cost are decimal strings in CurrencyCode. CategoryID and ManufacturerID come from product.taxonomies. Returns { dryRun, record: { id, ItemType } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
product.create
Create a purchase order as a draft: it has no number and commits nothing until it is issued with purchaseOrder.issue, and a draft can be changed freely or deleted. AccountID is the supplier — an account (account.search or lookup.resolve); any account may be a supplier, and issuing marks it as one. ContactID, optional, is a contact of that account. OpportunityID, optional, is the opportunity this cost is charged to (opportunity.search). OwnerID is the user who owns the order; left out it is this user, and only a user who may create orders for everyone can name someone else. SupplierReference is the supplier’s own quotation or reference number. ExpectedDate is the required-by date as yyyy-MM-dd, or blank. CurrencyCode is three capital letters. TaxRate is the document’s tax as a fraction — 0.09 for 9%, never a percentage, at most 1; TaxDesc is its name. items is the line set: each line names a product by ProductID (product.search) with ProductDescription, Qty and UnitPrice — the price is the cost, as exact decimal strings such as "120.50" — and optionally Unit, Remark, SerialNo, LeadTime, and TaxRate or TaxRateID for a line taxed differently (a line’s rate is a fraction too). exchangeRateOverride, when sent, is a rate above zero to the tenant’s base currency; left out, the company’s own rate is used. PaymentTerm, DeliveryAddress (ship to), Remark, TNC and Heading (the printed heading; blank prints Purchase Order) are optional. Amounts and quantities are strings, never JSON numbers. Returns { dryRun, record: { id, name } }, name being the order number, null on a draft. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
purchaseOrder.create
Create a quotation. It is saved as a draft (status Draft) with a draft number such as QD-10000001; it gets its quotation number and status Open when it is finalised with quotation.finalise, and only then can it be marked as sent, accepted, rejected or invoiced. ContactID is the customer contact (contact.search or lookup.resolve). SalesID, the salesperson’s user ID, is required: account.get’s OwnerID and quotation.get’s SalesID are user IDs in use. CurrencyCode is three letters. TaxRate is the document’s tax as a fraction — 0.09 for 9%, never a percentage, at most 1. ExpirationDate is yyyy-MM-dd or blank. items is the whole line set: each line names a product by ProductID (product.search), or sets ProductID 0 with newProduct { Name, ItemType goods or service } to create one — never both; Qty has at most two decimals; UnitPrice is an exact decimal string such as "120.50"; a line’s own TaxRate, if any, is a fraction too. Amounts and quantities are strings, never JSON numbers. dryRun true checks it without saving and without naming the number. Returns { dryRun, record: { id, name (the draft number), refNo, createdProducts } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
quotation.create
Create a recurring invoice: a schedule that raises a draft invoice for one customer every period from a template of lines. It issues nothing and sends nothing — each period’s invoice is a draft a person reviews and issues. Give one of three: contactId, currencyCode and template; or sourceInvoiceId (an existing invoice: its contact, currency, tax, text and lines are copied, the recurring invoice is independent of it afterwards, and that invoice is not its first period — leave the other three out); or sourcePlanId (copy a recurring invoice this user may see: its contact, currency, payment term, tax, text and lines are taken, and any of contactId, currencyCode, template or paymentTerm given here replaces the copied one — the way to get a different currency or schedule, which cannot change on an existing one; the one copied is left as it is). Never sourceInvoiceId and sourcePlanId together. template has the tax (TaxRate is a fraction — 0.09 for 9% — and TaxDesc its name), optional Header, TNC, Remark and CustomerPONumber, and items: each a ProductID (a product that exists; product.search finds it), ProductDescription, Qty and UnitPrice as exact decimal strings, and optionally Unit and TaxRate or TaxRateID for a line taxed differently. A description may carry [Month], [Year], [PeriodStart], [PeriodEnd] and [Period n/N], filled in on each draft. The lines must add up to more than zero before tax. schedule has frequency (week, month, quarter or year), intervalCount (every how many, default 1), startDate (yyyy-MM-dd; a plan that starts on the 29th to 31st bills the last day of a shorter month; with sourceInvoiceId it may be left out and is then one period after that invoice’s date, otherwise it is required) and, to end it, endDate or periodCount — not both; dueRule is periodStart (the default: invoiced on each period’s first day), periodEnd or dayOfMonth with dueDayOfMonth. autoDraft (default true) raises each draft automatically on the day its period falls due, from today on: periods already past are left for recurringInvoice.generate. ownerUserId is the salesperson the invoices are raised for (default this user; a user limited to their own invoices can only name themselves); paymentTerm such as NET 30 sets each draft’s due date. Refused while this company does not keep new invoices as drafts. Returns { dryRun, record: { id, status, currencyCode, autoDraft, autoSince, periodAmount, version, periods: [{ id, seq, name, invoiceDate, status }] } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
recurringInvoice.create
Create a space, a shared area for activities. name (at most 120 characters) and visibility — company (everyone who may see activities sees its threads) or members (only its members, and the people named in a thread) — are required; description is at most 1000 characters; memberUserIds (at most 200, activity.pick_user finds them) adds colleagues, who are told so in their Updates. This user becomes the owner and its first member. Returns { dryRun, record: { id } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
space.create
Create a business account — a company. Search first with account.search or lookup.resolve (entity account) and use the account that already exists rather than creating a second one for the same company: an account with the same name, or the same registration number (RegNum), in the same country (Billing_Country) is refused as a duplicate, and the answer says so. Name is required. OwnerID, the user ID of the account’s owner, is required: account.get’s OwnerID and quotation.get’s SalesID are user IDs in use. Billing_Country is the country’s name, such as Singapore. TaxRegNum is the customer’s own tax registration number (in Singapore its GST registration number, which can differ from the UEN in RegNum); invoices issued afterwards print it, and an SG customer-accounting invoice needs it. Every other field may be left out and is then blank. A personal account (a private individual) cannot be created with this tool. A company may require its own additional fields, which only a person in easySales can fill in; such a create is refused and the answer names the field. Returns { dryRun, record: { id } }. Required safety workflow: first call with dryRun true, show the full preview to the user and wait for their later explicit confirmation; only then repeat with dryRun false, the same arguments and requestId, and the returned confirmationToken. The original request is not that confirmation.
account.create
easySales ChatGPT Plugin FAQ
How the directory, categories and Discoverability Score work.
Read the methodologyHow do I improve easySales's ChatGPT Plugin discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are easySales alternatives on ChatGPT?
As of 2026-10-28, easySales competes with HubSpot, Attio, Close, Zoho CRM, 33CRM, Agiled, Alaz, Asbie and 59 more in ChatGPT B2B Sales CRM Platforms, ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.