Browse the documentation

MCP tools

Quotations and sales people

MCP tools for creating, editing, approving, generating and downloading quotations, and for the sales-person roster.

A quotation is the priced offer your organization presents to a buyer: a header (the addressee, validity, delivery period, payment terms and a contact person) and lines with quantity, unit price and VAT. It stays a draft until it is approved. The organization stamp and the sales person's signature print on the PDF only while the quotation is approved, and any content change returns it to draft. The sales-people roster is the list a quotation's printed contact person is picked from. The app's own pages are described in Quotations and Sales people.

Note:Quotations carry prices, so these tools are closed to the technical and viewer (no pricing) roles. Each quotation keeps its own copy of your company details and its contact person, so editing the organization profile or a sales person later never changes a quotation that already exists.
ToolWhat it does
quotations_listList quotations
quotations_getGet a quotation
quotations_createCreate a quotation
quotations_updateUpdate a quotation
quotations_deleteDelete a quotation
quotations_bulk_updateUpdate many quotation headers
quotations_set_approvalApprove or un-approve quotations
quotations_defaults_getGet the quotation defaults
tender_quotations_listList a tender's quotations
tender_quotations_generateGenerate a tender's quotations
tender_quotation_pdf_bundleDownload a tender's quotation PDFs
quotation_pdfDownload a quotation PDF
quotation_packageDownload a quotation package
quotation_packages_bundleDownload many quotation packages
quotation_product_document_prefillGet the product document prefill
quotation_product_documentGenerate the product document
sales_persons_listList sales people
sales_persons_getGet a sales person
sales_persons_createAdd a sales person
sales_persons_updateUpdate a sales person
sales_persons_deleteDelete a sales person

Quotations

Creating, reading, editing and deleting quotations, approving them, and reading the defaults new quotations start from.

quotations_list

Lists your organization's quotations, newest first, optionally only those on one tender. summary adds the grand totals per currency.

Read-only · scope quotations.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans

ParameterTypeRequiredDescription
tender_idintegerNoOnly the quotations on this tender.
summarybooleanNotrue adds a summary to the reply: the quotation count and the grand total per currency in totals_by_currency, over every matching quotation rather than only the page.
pageintegerNoPage number, starting at 1.
page_sizeintegerNoResults per page: 20 by default, 100 at most.

Returns: A page of quotations in data with total, page, page_size and total_pages, plus summary when asked. Each quotation carries id, quote_number, customer_name, approval_status, currency, the totals total_subtotal, total_vat and total_grand, and its tender in tenders.

  • The list does not carry the lines; use quotations_get for them.

quotations_get

Reads one quotation in full: the header, the lines, the company details frozen at creation, the printed contact person and the linked tender. Use it before an edit to see exactly what the quotation holds.

Read-only · scope quotations.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe quotation's ID, from quotations_list.

Returns: quotation (the header, approval_status, approved_at, salesperson_snapshot and company_snapshot, whose logo_url and stamp_url are freshly signed links), items with each line's ID, tender (agency_name and tender_name, or null), and itemImages with the cover photo link of each line whose product has photos.

  • A line's ID here is what quotation_product_document takes as item_id and as the keys of fields.
  • A quotation that is not your organization's answers 404.

quotations_create

Creates one quotation: either standalone, with an addressee you name, or linked to a tender whose agency becomes the addressee. It gets a number from your organization's counter, starts as a draft, and your company details are frozen into it at that moment.

Changes data · scope quotations.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
tender_idintegerNoThe ID of the tender to link; its agency becomes the addressee unless you name another. It must be a tender your organization can see. Leave it out or send null for a quotation with no tender.
customer_idintegerNoThe ID of a customer profile from customers_list. Its name prints as the addressee when you give no customer_name. A customer that is not your organization's answers 404.
customer_namestringNoThe printed addressee, up to 200 characters. It wins over the linked tender's agency name. On a quotation with no tender, give this or customer_id so the quotation has an addressee.
rfq_nostringNoThe buyer's own RFQ number, up to 100 characters.
quote_validity_daysintegerNoHow many days the offer stays valid, 1 to 3650. When left out, your organization's default applies (see quotations_defaults_get).
delivery_period_daysintegerNoThe delivery period in days, 1 to 3650. When left out, your organization's default applies.
payment_termsstringNoThe payment terms printed on the quotation, up to 500 characters: one of the presets advance_100, advance_50_balance_on_delivery, on_delivery, net_30, net_60 or net_90 (printed in Arabic and English), or free text printed as typed. When left out, your organization's default terms apply; null prints none.
currencystringNoThe currency code, 1 to 8 characters. Defaults to SAR.
notesstringNoNotes printed on the quotation, up to 2,000 characters. When left out, the standard closing line "Looking forward for your business" prints.
sales_person_idintegerNoThe ID of a person on your sales roster, from sales_persons_list. Their details fill any salesperson_* field you leave out, and the quotations list can filter by them. An ID that is not on your roster answers sales_person_not_found.
salesperson_namestringNoThe name printed as the contact person, up to 200 characters. When left out, the picked sales person's name is used, else the name of the member who connected. null prints none.
salesperson_phonestringNoThe phone printed for the contact person, up to 50 characters. When left out, the picked sales person's phone is used, else the connected member's. null prints none.
salesperson_emailstringNoThe email printed for the contact person, a valid address up to 320 characters. When left out, the picked sales person's email is used, else the connected member's. null prints none.
itemsobject[]YesThe quotation lines, from 1 to 500.
items[].tender_item_idintegerNoThe ID of the tender item this line covers, from the tender's items in tenders_get. Used only on a quotation linked to a tender.
items[].product_idintegerNoThe ID of the catalog product behind this line, from products_list. A linked product supplies the catalog number when you leave it blank and the VAT rate when you leave it out, and later feeds the product document with its catalog and certificates.
items[].manufacturer_idintegerNoThe ID of the manufacturer this line is quoted under, from manufacturers_list; it must be one of your organization's. When left out, the product's default manufacturer is used, and null keeps it automatic, so the manufacturer is chosen when documents are generated. It decides the manufacturer name, the authorization letter and the agency type in the product document.
items[].descriptionstringYesThe line's description as printed, 1 to 4,000 characters.
items[].stock_nostringNoThe stock or NUPCO material number, up to 100 characters.
items[].catalog_nostringNoThe catalog number, up to 100 characters.
items[].unitstringNoThe unit of measure, up to 50 characters.
items[].quantitynumberYesThe quantity, zero or more.
items[].unit_pricenumberYesThe unit price in the quotation's currency, zero or more.
items[].vat_ratenumberNoThe VAT percentage, 0 to 100. When left out it is 0 for a line whose linked product is medical and 15 for everything else, including a line with no product.
{
  "tender_id": 48213,
  "rfq_no": "RFQ-2026-0417",
  "quote_validity_days": 90,
  "delivery_period_days": 30,
  "payment_terms": "net_30",
  "sales_person_id": 6,
  "items": [
    {
      "tender_item_id": 902114,
      "product_id": 3381,
      "description": "Disposable syringe 5 ml, Luer lock, sterile",
      "stock_no": "4111610529900",
      "unit": "Box",
      "quantity": 200,
      "unit_price": 24.5
    }
  ]
}
Example arguments

Returns: The new quotation_id, the quote_number it was given, and logo_url and stamp_url links for the logo and the stamp.

  • Creating a quotation counts against your plan's monthly quota: 50 on Starter, unlimited on Pro. At the limit the tool answers plan_limit_reached with limit and current.
  • Blank fields are filled from your own data: a line tied to a tender item and carrying no product takes the product you selected for that item, a blank catalog number comes from the product, and a blank stock number comes from the tender item's material code. What you typed is never replaced.
  • A tender your organization cannot see answers 404, and a manufacturer that is not your organization's answers manufacturer_not_found.

quotations_update

Edits a quotation's header or lines. Every field is optional and whatever you leave out stays as it is, so a header-only edit needs no lines. Any change returns the quotation to draft.

Changes data · scope quotations.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe quotation's ID, from quotations_list.
quote_numberstringNoThe number printed on the quotation, 1 to 100 characters. Unique within your organization.
tender_idintegerNoLinks the quotation to this tender, one your organization can see. Send null to unlink it.
customer_idintegerNoLinks the quotation to a customer profile, or null to unlink. This sets the link only; to change the printed addressee, send customer_name.
customer_namestringNoThe printed addressee, up to 200 characters. Send null to fall back to the linked tender's agency.
rfq_nostringNoThe buyer's own RFQ number, up to 100 characters. Send null to clear it.
quote_validity_daysintegerNoHow many days the offer stays valid, 1 to 3650. Send null to clear it.
delivery_period_daysintegerNoThe delivery period in days, 1 to 3650. Send null to clear it.
payment_termsstringNoThe payment terms printed on the quotation, up to 500 characters: one of the presets advance_100, advance_50_balance_on_delivery, on_delivery, net_30, net_60 or net_90 (printed in Arabic and English), or free text printed as typed. Send null to print no payment terms.
currencystringNoThe new currency code, 1 to 8 characters.
notesstringNoNotes printed on the quotation, up to 2,000 characters. Send null to clear them.
sales_person_idintegerNoThe ID of a person on your sales roster, from sales_persons_list. Their details fill any salesperson_* field you do not send in the same call, and the quotations list can filter by them. Send null to remove the link; the printed contact stays as it is.
salesperson_namestringNoThe name printed as the contact person, up to 200 characters. It is merged into the stored contact, so what you do not send stays. Send null to print no name.
salesperson_phonestringNoThe phone printed for the contact person, up to 50 characters. Send null to print no phone.
salesperson_emailstringNoThe email printed for the contact person, a valid address up to 320 characters. Send null to print no email.
itemsobject[]NoThe complete new set of lines, 1 to 500. When sent, it replaces every existing line and the totals are recomputed; when left out, the lines and totals stay as they are.
items[].tender_item_idintegerNoThe ID of the tender item this line covers, from the tender's items in tenders_get. Used only on a quotation linked to a tender.
items[].product_idintegerNoThe ID of the catalog product behind this line, from products_list. A linked product supplies the catalog number when you leave it blank and the VAT rate when you leave it out, and later feeds the product document with its catalog and certificates.
items[].manufacturer_idintegerNoThe ID of the manufacturer this line is quoted under, from manufacturers_list; it must be one of your organization's. When left out, the product's default manufacturer is used, and null keeps it automatic, so the manufacturer is chosen when documents are generated. It decides the manufacturer name, the authorization letter and the agency type in the product document.
items[].descriptionstringYesThe line's description as printed, 1 to 4,000 characters.
items[].stock_nostringNoThe stock or NUPCO material number, up to 100 characters.
items[].catalog_nostringNoThe catalog number, up to 100 characters.
items[].unitstringNoThe unit of measure, up to 50 characters.
items[].quantitynumberYesThe quantity, zero or more.
items[].unit_pricenumberYesThe unit price in the quotation's currency, zero or more.
items[].vat_ratenumberNoThe VAT percentage, 0 to 100. When left out it is 0 for a line whose linked product is medical and 15 for everything else, including a line with no product.
{
  "id": 311,
  "customer_name": "Acme Medical Supplies",
  "quote_validity_days": 60,
  "payment_terms": null
}
Example arguments

Returns: The quotation_id of the edited quotation.

  • Any change to the header or the lines returns the quotation to draft, so the organization stamp and the signature stop printing until you approve it again with quotations_set_approval.
  • Sending items replaces every line, so a partial array truncates the document. Unlike creation, an edit does not fill a blank catalog number or stock number from your data, so send both in full with each line. An omitted VAT rate and an omitted manufacturer are resolved as on creation.
  • A number already taken answers 409 quote_number_taken. A quotation that is not your organization's, or a tender it cannot see, answers 404.
  • The frozen company details are never changed by an edit.

quotations_delete

Deletes a quotation and its lines for good. This cannot be undone.

Deletes or overwrites data · scope quotations.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe quotation's ID, from quotations_list.

Returns: A confirmation, ok: true.

  • A quotation that is not your organization's answers 404.

quotations_bulk_update

Edits the headers of up to 200 quotations in one call: number, addressee, validity, delivery, currency, notes, tender link, sales person and contact details. It takes no lines, so it can never truncate a document; to change lines, use quotations_update per quotation.

Changes data · scope quotations.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
updatesobject[]YesOne element per quotation, from 1 to 200. Each carries the id and only the keys to change: what is left out stays, and an explicit null clears the field.
updates[].idintegerYesThe quotation's ID, from quotations_list.
updates[].quote_numberstringNoThe new number, 1 to 100 characters. A number already taken fails that row alone.
updates[].tender_idintegerNoLinks the quotation to this tender. Send null to unlink.
updates[].customer_namestringNoThe printed addressee, up to 200 characters. Send null to fall back to the tender's agency.
updates[].rfq_nostringNoThe buyer's own RFQ number, up to 100 characters. Send null to clear it.
updates[].quote_validity_daysintegerNoHow many days the offer stays valid, 1 to 3650. Send null to clear it.
updates[].delivery_period_daysintegerNoThe delivery period in days, 1 to 3650. Send null to clear it.
updates[].payment_termsstringNoThe payment terms printed on the quotation, up to 500 characters: one of the presets advance_100, advance_50_balance_on_delivery, on_delivery, net_30, net_60 or net_90 (printed in Arabic and English), or free text printed as typed. Send null to print no payment terms.
updates[].currencystringNoThe new currency code, 1 to 8 characters.
updates[].notesstringNoNotes printed on the quotation, up to 2,000 characters. Send null to clear them.
updates[].sales_person_idintegerNoThe ID of a person on your sales roster, from sales_persons_list. Their details fill any salesperson_* field you do not send in the same call, and the quotations list can filter by them. Send null to remove the link; the printed contact stays as it is.
updates[].salesperson_namestringNoThe name printed as the contact person, up to 200 characters. It is merged into the stored contact, so what you do not send stays. Send null to print no name.
updates[].salesperson_phonestringNoThe phone printed for the contact person, up to 50 characters. Send null to print no phone.
updates[].salesperson_emailstringNoThe email printed for the contact person, a valid address up to 320 characters. Send null to print no email.
{
  "updates": [
    {
      "id": 311,
      "sales_person_id": 6,
      "payment_terms": "net_30"
    },
    {
      "id": 312,
      "sales_person_id": 6,
      "payment_terms": "net_30"
    }
  ]
}
Example arguments

Returns: updated, the IDs of the quotations that changed, and failed, a list of id and error for the rows that did not.

  • Rows are applied independently and the call succeeds even when some fail: what succeeded stays saved, and each failed row is named with its reason, such as quote_number_taken or sales_person_not_found. Always read failed.
  • Every quotation that changed returns to draft, so approve it again with quotations_set_approval.
  • To present several quotations under one person, repeat the same sales_person_id on every row: their name, phone and email fill each printed contact block, and their signature prints once the quotations are approved again.

quotations_set_approval

Approves one or more quotations, or returns them to draft. Only an approved quotation prints with the organization stamp and the linked sales person's signature, when that person has one saved; approval does not depend on a signature existing.

Changes data · scope quotations.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
idsinteger[]YesThe quotation IDs, from 1 to 200.
approvedbooleanYestrue approves the quotations and false returns them to draft.
{
  "ids": [
    311,
    312,
    313
  ],
  "approved": true
}
Example arguments

Returns: updated, the IDs that changed, and failed, the IDs not found in your organization, each with the error not_found.

  • Any content edit, whether through quotations_update or a regeneration from the tender, returns the quotation to draft, so approve it again afterwards.
  • In the app, the approve button is limited to owners and admins. This tool is open to every role that may edit quotations, as the roles line above shows.

quotations_defaults_get

Reads the values a new quotation starts from in your organization, and the contact details it would take if you name no person. Use it before quotations_create to know what prints when you leave fields out.

Read-only · scope quotations.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans

No parameters.

Returns: validityDays and deliveryDays (90 when your organization has set none), paymentTerms (or null), salesperson with the full_name, phone and email of the member who connected, and company: the letterhead a new quotation prints, with the legal names, registration and VAT numbers, address and contact details, and short-lived links to the logo and stamp.

Quotations on a tender

Tools that work on the quotations of one tender: listing them, generating them from its items and downloading their files.

tender_quotations_list

Lists all of your organization's quotations on one tender, newest first, with each one's number and totals.

Read-only · scope quotations.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans

ParameterTypeRequiredDescription
tender_idintegerYesThe tender's ID.

Returns: A quotations list, each with id, quote_number, rfq_no, currency, total_subtotal, total_vat, total_grand and created_at.

  • This list does not show the approval state; use quotations_list with tender_id for it.

tender_quotations_generate

Generates quotations on a tender from the lines you send: per_item gives every line its own quotation and combined puts all the lines in one. Sending again is safe: lines an existing quotation already covers are refreshed in place instead of duplicated.

Changes data · scope quotations.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
tender_idintegerYesThe tender's ID, a tender your organization can see.
modestringNoper_item for one quotation per line, the default, or combined for one quotation carrying all the lines.
rfq_nostringNoThe buyer's own RFQ number, up to 100 characters.
quote_validity_daysintegerNoHow many days the offer stays valid, 1 to 3650. When left out, your organization's default applies (see quotations_defaults_get).
delivery_period_daysintegerNoThe delivery period in days, 1 to 3650. When left out, your organization's default applies.
payment_termsstringNoThe payment terms printed on the quotation, up to 500 characters: one of the presets advance_100, advance_50_balance_on_delivery, on_delivery, net_30, net_60 or net_90 (printed in Arabic and English), or free text printed as typed. When left out, your organization's default terms apply; null prints none.
currencystringNoThe currency code, 1 to 8 characters. Defaults to SAR.
notesstringNoNotes printed on the quotation, up to 2,000 characters. When left out, the standard closing line "Looking forward for your business" prints.
sales_person_idintegerNoThe ID of a person on your sales roster, from sales_persons_list. Their details fill any salesperson_* field you leave out, and the quotations list can filter by them. An ID that is not on your roster answers sales_person_not_found.
salesperson_namestringNoThe name printed as the contact person, up to 200 characters. When left out, the picked sales person's name is used, else the name of the member who connected. null prints none.
salesperson_phonestringNoThe phone printed for the contact person, up to 50 characters. When left out, the picked sales person's phone is used, else the connected member's. null prints none.
salesperson_emailstringNoThe email printed for the contact person, a valid address up to 320 characters. When left out, the picked sales person's email is used, else the connected member's. null prints none.
itemsobject[]YesThe lines to quote, from 1 to 500.
items[].tender_item_idintegerNoThe ID of the tender item this line covers, from the tender's items in tenders_get. Used only on a quotation linked to a tender.
items[].product_idintegerNoThe ID of the catalog product behind this line, from products_list. A linked product supplies the catalog number when you leave it blank and the VAT rate when you leave it out, and later feeds the product document with its catalog and certificates.
items[].manufacturer_idintegerNoThe ID of the manufacturer this line is quoted under, from manufacturers_list; it must be one of your organization's. When left out, the product's default manufacturer is used, and null keeps it automatic, so the manufacturer is chosen when documents are generated. It decides the manufacturer name, the authorization letter and the agency type in the product document.
items[].descriptionstringYesThe line's description as printed, 1 to 4,000 characters.
items[].stock_nostringNoThe stock or NUPCO material number, up to 100 characters.
items[].catalog_nostringNoThe catalog number, up to 100 characters.
items[].unitstringNoThe unit of measure, up to 50 characters.
items[].quantitynumberYesThe quantity, zero or more.
items[].unit_pricenumberYesThe unit price in the quotation's currency, zero or more.
items[].vat_ratenumberNoThe VAT percentage, 0 to 100. When left out it is 0 for a line whose linked product is medical and 15 for everything else, including a line with no product.
{
  "tender_id": 48213,
  "mode": "per_item",
  "payment_terms": "net_30",
  "sales_person_id": 6,
  "items": [
    {
      "tender_item_id": 902114,
      "product_id": 3381,
      "description": "Disposable syringe 5 ml, Luer lock, sterile",
      "unit": "Box",
      "quantity": 200,
      "unit_price": 24.5
    },
    {
      "tender_item_id": 902115,
      "product_id": 3390,
      "description": "Surgical gloves, nitrile, size M",
      "unit": "Box",
      "quantity": 500,
      "unit_price": 31
    }
  ]
}
Example arguments

Returns: A quotations list, each with quotation_id, quote_number and updated: true for a quotation refreshed in place and false for a new one.

  • In per_item mode the existing quotation for the same tender item is refreshed under the same number; in combined mode the one covering exactly the same set of tender items is. A quotation is refreshed only when your lines account for every line it carries; otherwise your lines become new quotations and the existing one is left alone. Anything with no existing quotation is created.
  • Give every line its tender_item_id: a line without one cannot be matched to an earlier quotation, so every run creates a new one for it.
  • The header fields apply to new quotations only; a refreshed quotation keeps its header. Every refreshed quotation returns to draft and needs approving again.
  • Only new quotations count against the monthly quota (50 on Starter, unlimited on Pro). The limit is checked before generation starts, so a refusal with plan_limit_reached creates nothing. A failure part-way through stops the run, and the quotations made before it stay.

tender_quotation_pdf_bundle

Renders a PDF for every quotation on a tender and returns them in one ZIP archive. It runs in a single request, so for a tender with many quotations use quotation_packages_bundle with pdf_only, which builds the file in the background.

Read-only · scope quotations.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans

ParameterTypeRequiredDescription
tender_idintegerYesThe tender's ID.

Returns: A ZIP file with one PDF per quotation: filename, content_type, size_bytes and base64.

  • A tender with none of your organization's quotations answers 404 with No quotations to download.
  • Each PDF prints the stamp and the signature if its quotation is approved, and prints without them if it is a draft.

Quotation files

The main file is the printed quotation. The product document is extra files per line that go with it: a cover letter with the catalog, the catalog alone, the SFDA certificate or a generated compliance letter, the manufacturer's authorization letter, and a plain-text file of the fields a buyer portal asks for. A file with no source in your data is left out of the archive without an error. It is explained in Quotations.

quotation_pdf

Renders one quotation as a PDF and returns it. It is the printed document itself: it carries the organization stamp and the sales person's signature when the quotation is approved, and a draft prints without a stamp and says it is not valid.

Read-only · scope quotations.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe quotation's ID, from quotations_list.

Returns: A PDF file: filename, content_type, size_bytes and base64.

  • The file is named after the quote number, except a single-line quotation on a NUPCO tender, which is named by the tender reference, the quote number and the item serial.
  • A quotation that is not your organization's answers 404.

quotation_package

Returns everything the platform produces for one quotation in a single ZIP archive: the quotation's PDF and, for each line, the product document's files. The document's fields are the automatically filled values, with no edits; to change a field, use quotation_product_document.

Read-only · scope quotations.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe quotation's ID, from quotations_list.

Returns: A ZIP file: filename, content_type, size_bytes and base64.

  • Each line gets up to five files: the cover letter with the catalog, the catalog alone, the SFDA certificate or the generated compliance letter, the authorization letter, and the text file. Files with no source are left out: a line with no stored catalog gets a cover letter without catalog pages, and a line whose manufacturer has no stored authorization letter gets none.
  • Files are named with the quote number and the line's position in the quotation, so they stay distinguishable outside the archive.

quotation_packages_bundle

Merges the packages of several quotations into flat ZIP archives, each quotation's PDF and product-document files side by side. It is the "download all files" of the quotations list. It is built in the background: the tool starts it and waits up to wait_seconds, then returns the file if it is done, or the job if it is not. It changes none of your data, and the finished file is kept for 24 hours.

Read-only · scope quotations.read · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
idsinteger[]YesThe IDs of the quotations to download, from 1 to 100.
pdf_onlybooleanNotrue includes only each quotation's PDF, without the product-document files. It is the list's "Download quotation PDFs".
reportbooleanNotrue returns the job (its status, report and parts) instead of the file itself.
wait_secondsintegerNoHow many seconds the tool waits for the bundle before answering with the job, 0 to 120. Defaults to 40, which usually covers a few quotations.
{
  "ids": [
    311,
    312,
    313
  ],
  "pdf_only": true,
  "wait_seconds": 60
}
Example arguments

Returns: When the archive is finished as a single part within the wait, the file: filename, content_type, size_bytes and base64, with report. Otherwise the job: job_id, status (queued, running, succeeded, failed or cancelled), progress, parts, report on success, and next_step saying what to do next.

  • A large bundle comes in several ZIP parts, each quotation whole in one part, so extract every part into one folder. Fetch the parts with generation_jobs_part and follow the job with generation_jobs_get.
  • One bundle builds per member at a time. If you already have one building, the tool answers with that job and already_running (it may be for another selection); to start over, cancel it with generation_jobs_cancel.
  • A finished job's report lists every quotation in included with its part, and every one that produced nothing in failed by quote number with a reason: not_found, render_failed or too_large (its own files exceed one archive). No quotation is dropped silently.
  • If none of the IDs is a quotation of your organization, the tool answers 404. For a NUPCO upload set, prefer tenders_nupco_attachments_fill, whose packet is self-contained.
  • This tool is not available to the viewer role.

quotation_product_document_prefill

Shows, for each line of a quotation, the values the product document will be filled with automatically and whether a catalog is stored for it. Use it to see what will print, or to build fields before calling quotation_product_document.

Read-only · scope quotations.read · roles: owner, admin, sales, purchasing, viewer · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe quotation's ID, from quotations_list.

Returns: quote_number and lines, each with item_id, label, fields (the values by key), has_catalog and catalog_name.

  • A quotation that is not your organization's answers 404.

quotation_product_document

Generates a quotation's product document as a ZIP of separate files: for each line the cover letter with the catalog, the catalog alone, the SFDA certificate or the generated compliance letter, the manufacturer's authorization letter, and a plain-text file of the buyer-portal registration fields. It covers every line or just one, and takes edits to the values per line.

Read-only · scope quotations.read · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe quotation's ID, from quotations_list.
modestringYescombined covers every line of the quotation; single covers one line, named by item_id.
item_idintegerNoThe ID of a line of this quotation, from quotations_get. Required with single, ignored with combined.
fieldsobjectNoEdits to the filled values. Each key is a line's ID in the quotation (a numeric string such as "4807") and its value is an object of field names to text of up to 2,000 characters. What you do not send stays as filled, and an empty value clears that row. A misspelled field key is ignored without an error, so take the keys from quotation_product_document_prefill.
{
  "id": 311,
  "mode": "single",
  "item_id": 4807,
  "fields": {
    "4807": {
      "product_title": "Disposable syringe 5 ml",
      "min_order_qty": "1000"
    }
  }
}
Example arguments

Returns: A ZIP file: filename, content_type, size_bytes and base64. File names start with the quote number and the line number, then cover, catalog, sfda, authorization or info.

  • The cover page fields are serial, nupco, company_name, manufacturer_name, product_title, description, catalogue, mdma and listing. The text file fields are mdma_number, mdma_expiry, min_order_qty, shelf_life_years, authorization_validity, volume, volume_unit, package_type, package_size, packing_uom, weight, weight_unit, unit_price, foc_percent, vat, net_price, additional_info and agency_type.
  • A catalog cannot be uploaded through this tool: the stored catalogs of the lines' products are included automatically. A line with no stored catalog gets its cover letter alone, and a missing authorization letter or certificate is left out of the archive without an error.
  • A product recorded as under registration gets the generated compliance letter instead of any stored certificate. A line that is not in the quotation, in single mode, answers 404, and single without item_id answers 400. This tool is not available to the viewer role.

Sales people

The roster belongs to the whole organization: what a colleague adds, you see. An entry is not a login, only a name, an email and a phone that picking the person fills into a quotation's printed contact block.

sales_persons_list

Lists the people on your organization's sales roster, newest first. Deactivated people are hidden unless you ask for them, and the tool can also list team members not yet on the roster.

Read-only · scope sales_persons.read · all roles · Pro and Enterprise plans

ParameterTypeRequiredDescription
include_inactivebooleanNotrue also lists deactivated people.
include_teambooleanNotrue adds team_members: organization members not yet on the roster, ready to add with sales_persons_create and the member's user_id.
pageintegerNoPage number, starting at 1.
page_sizeintegerNoResults per page: 20 by default, 100 at most.

Returns: A page of people in data with total, page, page_size and total_pages. Each carries id, name, email, phone, user_id (for one linked to a team member) and is_active. With include_team, team_members is added, each member with user_id, name, email and phone.

  • team_members comes back only for the roles that may edit quotations (owner, admin, sales and purchasing); for other roles the request is ignored without an error, because the list exposes members' contact details.

sales_persons_get

Reads one person from your organization's roster: their name, email, phone and state, and whether they are linked to a team member. Use it to check what picking them will fill into a quotation.

Read-only · scope sales_persons.read · all roles · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe person's ID, from sales_persons_list.

Returns: The sales_person, whose ID is what quotations carry in sales_person_id.

  • An ID that is not on your organization's roster answers 404.

sales_persons_create

Adds a person to your organization's sales roster: either by name, email and phone, or by a team member's ID, in which case their details come from their profile and the entry stays linked to them. No login is created either way.

Changes data · scope sales_persons.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
namestringNoThe full name as it prints, 1 to 200 characters. Required unless you send user_id.
emailstringNoThe email printed on quotations, a valid address up to 320 characters.
phonestringNoThe phone printed on quotations, up to 50 characters.
user_idstringNoA team member's ID (a UUID) from team_members in sales_persons_list. Their profile fills whichever of name, email and phone you do not send, and the entry updates by itself whenever the member edits their profile.
{
  "name": "Omar Al-Qahtani",
  "email": "omar@acme-medical.example",
  "phone": "+966501234567"
}
Example arguments

Returns: The new sales_person.

  • Each member has one roster entry: adding one again answers 409 already_on_roster. A user_id that is not a member of your organization answers 400 not_a_team_member, and sending neither name nor user_id answers 400.
  • A member's saved signature prints on an approved quotation only when the picked sales person is linked to that member.

sales_persons_update

Changes a person's name, email or phone, or deactivates and reactivates them. Only what you send changes. It never rewrites the quotations that already picked the person, since each quotation keeps its own copy of the contact details.

Changes data · scope sales_persons.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe person's ID, from sales_persons_list.
namestringNoThe full name, 1 to 200 characters.
emailstringNoThe email, a valid address up to 320 characters. Send null to clear it.
phonestringNoThe phone, up to 50 characters. Send null to clear it.
is_activebooleanNofalse hides the person from pickers and from the roster's default list, and true brings them back.
{
  "id": 6,
  "phone": "+966551234567",
  "is_active": true
}
Example arguments

Returns: The sales_person after the change.

  • A person linked to a team member is refreshed from the member's profile whenever it changes, so a later profile edit may replace what you set here.
  • Send at least one field, and an ID that is not on your roster answers 404.

sales_persons_delete

Deletes a person from the roster, or deactivates them instead when any quotation references them; the reply says which happened. The printed contact details in quotations stay either way.

Deletes or overwrites data · scope sales_persons.write · roles: owner, admin, sales, purchasing · Pro and Enterprise plans

ParameterTypeRequiredDescription
idintegerYesThe person's ID, from sales_persons_list.

Returns: ok: true and deactivated: true when the person was deactivated instead of deleted, false when deleted.

  • A real deletion cannot be undone, while a deactivation is reversed with sales_persons_update and is_active set to true. An ID that is not on your roster answers 404.