Operate Obriym CRM from your AI assistant: leads, deals, orders, catalog, stock, marketplaces.
Maintain this server? Claim it
Call this server's tools from your browser. Nothing to install.
Requests go through mcptry because browsers can't call most MCP servers directly. Header values are sent to the server for that request only and are never stored or logged.
Tool list from our last check. Connect live to refresh it.
Add a line item to an existing order by its externalId. Recomputes the order total. Only allowed while the order is pending or confirmed; on any other status (processing and later, cancelled, refunded) it fails with 409 CONFLICT "Order lines can only be changed while the order is pending or confirmed". Use list_orders or create_order for the order externalId, and search_products to quote a real product. The CRM recalculates shipping eligibility from the saved priced lines; a separate whole-order discount may require source-confirmed amount correction. The result echoes the operating workspace.
Quantity ordered (integer, at least 1).
Price per unit in the order currency, as a decimal (e.g. 199.99). Snapshotted onto the line.
The order externalId returned by list_orders or create_order.
Line item name, snapshotted onto the order. Use search_products to quote a real catalog product's name. Required.
Product SKU snapshot (from search_products). Optional.
Percentage discount on this line (0-100). Default 0.
This tool isn't marked read-only, so it may change something on the server or in an account you connected.
Add a line item to an existing order by its externalId. Recomputes the order total. Only allowed while the order is pending or confirmed; on any other status (processing and later, cancelled, refunded) it fails with 409 CONFLICT "Order lines can only be changed while the order is pending or confirmed". Use list_orders or create_order for the order externalId, and search_products to quote a real product. The CRM recalculates shipping eligibility from the saved priced lines; a separate whole-order discount may require source-confirmed amount correction. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| sku | string | Product SKU snapshot (from search_products). Optional. |
| discount | number | Percentage discount on this line (0-100). Default 0. |
| quantity* | integer | Quantity ordered (integer, at least 1). |
| unitPrice* | any | Price per unit in the order currency, as a decimal (e.g. 199.99). Snapshotted onto the line. |
| externalId* | string | The order externalId returned by list_orders or create_order. |
| productName* | string | Line item name, snapshotted onto the order. Use search_products to quote a real catalog product's name. Required. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"productName",
"quantity",
"unitPrice",
"externalId"
],
"properties": {
"sku": {
"type": "string",
"maxLength": 120,
"description": "Product SKU snapshot (from search_products). Optional."
},
"discount": {
"type": "number",
"default": 0,
"maximum": 100,
"minimum": 0,
"description": "Percentage discount on this line (0-100). Default 0."
},
"quantity": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Quantity ordered (integer, at least 1).",
"exclusiveMinimum": 0
},
"unitPrice": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d+(\\.\\d{1,2})?$"
},
{
"type": "number",
"minimum": 0
}
],
"description": "Price per unit in the order currency, as a decimal (e.g. 199.99). Snapshotted onto the line."
},
"externalId": {
"type": "string",
"minLength": 1,
"description": "The order externalId returned by list_orders or create_order."
},
"productName": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "Line item name, snapshotted onto the order. Use search_products to quote a real catalog product's name. Required."
}
},
"additionalProperties": false
}Add photos to ONE product, after the photos it already has: public https image links (images, each with an optional caption), files the person attached in ChatGPT (files — ChatGPT fills it), or links returned by create_image_upload for files on the agent's own machine. Obriym downloads every image and stores its OWN COPY in the workspace's storage — the link may be temporary and nothing hotlinks to it. Limits: JPEG, PNG or WebP, at most 2 MB each (a bigger file is refused — there is no resize), at most 10 photos per product. All or nothing: if any link fails, or the total would exceed 10, nothing is stored and the reason is returned. Saves through the product form's own operation (version check, audit, channel updates). Not idempotent: repeating the call adds the photos again. Returns the product's full photo list { url, alt } — the first is the main photo. Use get_product first to see the current photos and update_product_images to reorder, caption or remove them. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| files | array | Image files the person attached in ChatGPT. ChatGPT fills this field itself; any other client leaves it out and passes image links instead (or uploads files with create_image_upload). |
| images | array | Photos to ADD after the product's current ones, in order. The product may hold at most 10 photos in total; a request that would exceed it is refused and nothing is stored. |
| productId* | string | The product id from search_products or get_product. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"productId"
],
"properties": {
"files": {
"type": "array",
"items": {
"type": "object",
"required": [
"download_url",
"file_id"
],
"properties": {
"file_id": {
"type": "string",
"description": "ChatGPT's id of the attached file."
},
"file_name": {
"type": "string",
"description": "The attached file's name."
},
"mime_type": {
"type": "string",
"description": "The attached file's type."
},
"download_url": {
"type": "string",
"format": "uri",
"description": "Temporary link ChatGPT gives to the attached file."
}
}
},
"maxItems": 10,
"description": "Image files the person attached in ChatGPT. ChatGPT fills this field itself; any other client leaves it out and passes image links instead (or uploads files with create_image_upload)."
},
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"url"
],
"properties": {
"alt": {
"type": "string",
"maxLength": 200,
"description": "Caption (alt text) of the photo, up to 200 characters. Empty or omitted: the storefront falls back to the product name. Do not invent a description of what you cannot see."
},
"url": {
"type": "string",
"format": "uri",
"description": "A public https image link (JPEG, PNG or WebP, at most 2 MB). Obriym downloads it and stores its own copy in the workspace, so the link may be temporary."
}
}
},
"maxItems": 10,
"minItems": 1,
"description": "Photos to ADD after the product's current ones, in order. The product may hold at most 10 photos in total; a request that would exceed it is refused and nothing is stored."
},
"productId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The product id from search_products or get_product."
}
}
}Move a product stock by a relative delta (negative to write off, positive to add) with a reason, and record it in the stock history. This is the correct tool for a correction, a write-off or damage — it never sets an absolute number, so an order committing at the same moment is not overwritten. The reason decides the direction: write_off, damage and return_to_supplier must carry a negative delta, opening_balance a positive one, while correction and other accept either; a delta that contradicts its reason is rejected. Any other word is your own vocabulary and is accepted in either direction. The product must already track inventory; a product that does not returns a conflict rather than having tracking switched on for it. A bundle also returns a conflict: its stock is derived from its components, so adjust each component instead. Pass a stable externalId to make a retry idempotent. The new stock is pushed to every connected sales channel. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| note | string | |
| delta* | integer | |
| reason* | string | |
| metadata | object | |
| productId* | string | |
| externalId | string |
Apply a bulk price change — step 2 of 2, after preview_bulk_price_change. Send the SAME rule, scope and target and the digest the preview returned, copied verbatim and never invented. The plan is recomputed from live prices and refused with CONFLICT if it no longer matches the digest (prices moved, or the rule would compound on a retry) — preview again and show the person the new numbers. Changes real prices: a selling price reaches connected channels where the owner armed price writes; a purchase cost is never published. Returns { affected, skipped }. Needs the owner's "AI may change prices in bulk" switch (Settings → Integrations → Connect AI); without it the call is refused and you should tell the person to ask the owner. Not idempotent for percent rules — never repeat a successful apply. Confirm with the person unless they asked for the change outright. Echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| rule* | any | HOW prices move. The target 'cost' accepts only op 'percent'. Pick the one that matches the request: a percent change, a fixed price, a markup over cost, a discount (and its end), or the old price. |
| scope* | any | WHICH products. Prefer a named container (category, brand, supplier, warehouse) when the person says 'all products of …' — it is read back by name in the preview. There is no free filter: a request like 'everything cheaper than 100' is not a scope; find the products first and send their ids. |
| digest* | string | The digest returned by preview_bulk_price_change for THIS rule, scope and target — copied verbatim, never invented. If prices moved since, the apply returns CONFLICT and you must preview again. |
Archive up to 100 products — this is how an AI client removes a product. It leaves sale and every sales channel's feed, and nothing is erased: update_product with status active or draft restores it. Hard deletion is not available over MCP. A product that a non-archived bundle is made of is NOT archived: it is listed in heldByBundle with the bundles that contain it — archive or change those bundles first. Archiving also asks Prom to take the product's listings down; notAttempted counts takedowns not reached in time. To end a live eBay listing use withdraw_ebay_listings. Returns { affected, skipped, notAttempted, heldByBundle } — skipped products were already archived. Idempotent. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| productIds* | array | The products to archive, at most 100 ids from search_products. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"productIds"
],
"properties": {
"productIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
},
"maxItems": 100,
"minItems": 1,
"description": "The products to archive, at most 100 ids from search_products."
}
}
}Assign a lead to a workspace member by user id, or pass assignedTo=null to unassign. Use search_leads to find the lead id and get_workspace_info to confirm the operating workspace. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The lead id returned by search_leads. |
| assignedTo* | any | User id of the workspace member to assign the lead to. Pass null to unassign. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"assignedTo",
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The lead id returned by search_leads."
},
"assignedTo": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "User id of the workspace member to assign the lead to. Pass null to unassign."
}
},
"additionalProperties": false
}Choose one eBay shipping (fulfillment) policy — or null for the connection default — for up to 25 products on one eBay site, with the same per-product rules as set_product_ebay_fulfillment_policy: no listing stores the choice; a draft or live listing has its offer updated in place and read back. The policy is checked against eBay once before any product is touched, and a product whose listing lives on another eBay site fails with marketplaceMismatch instead of being moved. Returns results per product (status updated, unchanged, saved, unverified or failed with the eBay error), counts and notAttempted (not reached in the time budget — call again with those ids). Refused until the workspace owner switches on AI publishing. Idempotent. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| productIds* | array | The products to change, at most 25 ids from search_products. |
| marketplaceId | string | The eBay MARKETPLACE id the policy belongs to, such as EBAY_IT. Omit it when the eBay connection sells on one site. A product whose eBay offer lives on another site is reported as failed, never moved. |
| fulfillmentPolicyId* | any | A fulfillmentPolicyId from list_ebay_fulfillment_policies, for the same marketplace. null removes the product's own choice so the connection default (then eBay's first policy) applies. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"fulfillmentPolicyId",
"productIds"
],
"properties": {
"productIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
},
"maxItems": 25,
"minItems": 1,
"description": "The products to change, at most 25 ids from search_products."
},
"marketplaceId": {
"enum": [
"EBAY_US",
"EBAY_GB",
"EBAY_DE",
"EBAY_AT",
"EBAY_BE",
"EBAY_FR",
"EBAY_IT",
"EBAY_NL",
"EBAY_ES",
"EBAY_IE",
"EBAY_PL",
"EBAY_CH",
"EBAY_CA",
"EBAY_AU"
],
"type": "string",
"description": "The eBay MARKETPLACE id the policy belongs to, such as EBAY_IT. Omit it when the eBay connection sells on one site. A product whose eBay offer lives on another site is reported as failed, never moved."
},
"fulfillmentPolicyId": {
"anyOf": [
{
"type": "string",
"pattern": "^[A-Za-z0-9_-]+$",
"maxLength": 64,
"minLength": 1
},
{
"type": "null"
}
],
"description": "A fulfillmentPolicyId from list_ebay_fulfillment_policies, for the same marketplace. null removes the product's own choice so the connection default (then eBay's first policy) applies."
}
}
}Check locally which products a marketplace will refuse and why — missing price, unusable price, blank name, unmapped category — grouped by what fixes them, without calling the marketplace. The response separates `blocked` (these products do NOT go out) from `warnings` (these DO go out, but probably will not be published as the merchant expects: a price in a currency the platform does not name, no words of their own in a language the channel reads, a placeholder description, characteristics the marketplace does not recognise). Local checks exist for prom, rozetka, google_merchant and olx; other platforms report their connection state through get_marketplace instead. If the channel is not connected the call fails with NOT_FOUND ("<channel> is not connected in this workspace") instead of reporting an empty channel — use list_marketplaces to see which are connected. This never publishes anything: it reports what would happen.
| Argument | Type | Description |
|---|---|---|
| platform* | string | The marketplace slug returned by list_marketplaces (prom, rozetka, woocommerce, shopify, olx, amazon, ebay, google_merchant). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"platform"
],
"properties": {
"platform": {
"type": "string",
"minLength": 1,
"description": "The marketplace slug returned by list_marketplaces (prom, rozetka, woocommerce, shopify, olx, amazon, ebay, google_merchant)."
}
}
}Mark an activity (task, call, or meeting) as completed by its id. Use list_activities first to find the activity id. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The activity id returned by list_activities. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The activity id returned by list_activities."
}
}
}Update an existing pipeline stage's name, default probability, or WIP limit. Provide the stage id (from list_pipeline_stages) and ONLY the fields to change — omitted fields keep their current value; wipLimit null removes the limit. A name cannot be blank and must be unique among stages (409 CONFLICT otherwise). Stages cannot be created here, and stage order and terminal behavior are fixed. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The pipeline stage id returned by list_pipeline_stages. |
| patch* | object | Pipeline stage fields to change: name, defaultProbability and/or wipLimit. Provide at least one; omitted fields are left as they are. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"patch"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The pipeline stage id returned by list_pipeline_stages."
},
"patch": {
"type": "object",
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "Display name of the pipeline stage."
},
"wipLimit": {
"anyOf": [
{
"type": "integer",
"maximum": 999,
"minimum": 1
},
{
"type": "null"
}
],
"description": "Work-in-progress limit (max deals allowed in the stage). Null or omit for no limit."
},
"defaultProbability": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Default win probability for deals in this stage, 0-100."
}
},
"description": "Pipeline stage fields to change: name, defaultProbability and/or wipLimit. Provide at least one; omitted fields are left as they are.",
"additionalProperties": false
}
}
}Convert a lead into a contact, company, and/or deal (select at least one via the input flags). Sets the lead status to converted. Use search_leads first to find the lead id. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The lead id returned by search_leads. |
| input* | object | Conversion options that decide whether to create/link contact, company and deal records. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"input"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The lead id returned by search_leads."
},
"input": {
"type": "object",
"properties": {
"dealTitle": {
"type": "string",
"maxLength": 255,
"description": "Title for the created deal. Required when createDeal is true."
},
"createDeal": {
"type": "boolean",
"default": false,
"description": "Create an open pipeline deal from the lead. Default false."
},
"dealAmount": {
"type": "string",
"pattern": "^\\d+(\\.\\d{1,2})?$",
"description": "Deal amount, as a decimal string. Used when createDeal is true."
},
"companyName": {
"type": "string",
"maxLength": 255,
"description": "Name for the company to create. Required when createCompany is true."
},
"createCompany": {
"type": "boolean",
"default": false,
"description": "Create (or link) a company from the lead. Default false."
},
"createContact": {
"type": "boolean",
"default": false,
"description": "Create (or link) a contact from the lead. Default false."
},
"contactLastName": {
"type": "string",
"maxLength": 120,
"description": "Last name for the contact to create. Optional."
},
"contactFirstName": {
"type": "string",
"maxLength": 120,
"description": "First name for the contact to create. Required when createContact is true."
},
"dealNextActionDate": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
"description": "ISO 8601 next-action date for the created deal. Used when createDeal is true."
},
"dealNextActionNote": {
"type": "string",
"maxLength": 500,
"description": "Next-action note for the created deal. Used when createDeal is true."
}
},
"description": "Conversion options that decide whether to create/link contact, company and deal records.",
"additionalProperties": false
}
}
}Create an activity (task, call, meeting, email, or note). Must link to at least one lead, contact, company, or deal — use search_leads/search_contacts/search_companies/search_deals to get the entity id. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| type* | string | Activity type. One of: task, call, meeting, email, note. |
| title* | string | Short title of the activity. Required. |
| dealId | any | Deal id to link the activity to (from search_deals). Link at least one entity. |
| leadId | any | Lead id to link the activity to (from search_leads). Link at least one entity. |
| dueDate | any | Due date/time, ISO 8601. Optional. |
| priority | string | Priority. Optional. One of: low, medium, high. |
| companyId | any | Company id to link the activity to (from search_companies). Link at least one entity. |
| contactId | any | Contact id to link the activity to (from search_contacts). Link at least one entity. |
| assignedTo |
Create a catalog brand with optional description, website and per-language description translations. The brand NAME is never translated: marketplaces match the vendor name verbatim, so send it exactly as the vendor is known. The slug is normalized to Latin. A name already used in this workspace is rejected, so call list_brands first to avoid duplicates. Translate only the brand's own description — add no facts the user did not give. The result is the created brand with its id (use it as brandId for create_product/update_product) and echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| name* | string | The brand name exactly as marketplaces know the vendor, up to 120 characters; unique in the workspace. Never translated. |
| slug | any | URL segment for the brand. Normalized to lowercase Latin letters, digits and hyphens whatever is sent; derived from the name when omitted. |
| website | any | The brand's website as a full https:// URL. Send null to clear it. |
| description | any | Brand description in the workspace's base language (up to 4000 characters). Send null to clear it. |
| translations | array | Brand description per locale (the brand NAME is never translated). Omit to leave existing translations untouched; when sent it REPLACES the whole set, so an empty array removes them all. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The brand name exactly as marketplaces know the vendor, up to 120 characters; unique in the workspace. Never translated."
},
"slug": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
],
"description": "URL segment for the brand. Normalized to lowercase Latin letters, digits and hyphens whatever is sent; derived from the name when omitted."
},
"website": {
"anyOf": [
{
"type": "string",
"format": "uri",
"maxLength": 255
},
{
"type": "null"
}
],
"description": "The brand's website as a full https:// URL. Send null to clear it."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 4000
},
{
"type": "null"
}
],
"description": "Brand description in the workspace's base language (up to 4000 characters). Send null to clear it."
},
"translations": {
"type": "array",
"items": {
"type": "object",
"required": [
"description",
"locale"
],
"properties": {
"locale": {
"enum": [
"uk",
"ru",
"en",
"pl",
"de",
"it",
"fr",
"es",
"pt",
"nl",
"cs",
"sk",
"hu",
"ro",
"bg",
"lt",
"lv",
"et",
"tr"
],
"type": "string",
"example": "en",
"description": "Content locale, one of the workspace's supported languages."
},
"description": {
"type": "string",
"maxLength": 4000
}
},
"additionalProperties": false
},
"maxItems": 19,
"description": "Brand description per locale (the brand NAME is never translated). Omit to leave existing translations untouched; when sent it REPLACES the whole set, so an empty array removes them all."
}
},
"additionalProperties": false
}Create a catalog category, optionally nested under an existing one, with optional description and per-language translations. The slug is normalized to Latin whatever is sent. The parent must exist in this workspace, and a name already used under the same parent is rejected, so call list_categories first to avoid duplicates. To link marketplace categories send marketplaceCategories ({ prom, rozetka, olx, amazon, google_merchant } with the id as a string, null to clear): look the ids up with search_marketplace_categories first and never guess them. The format is always checked on write, and against the marketplace while it is connected (OLX must be a leaf category; a Google id must exist in the Google taxonomy). Translate only the category's own name and description into each locale — add no facts the user did not give. The result is the created category with its id (use it as categoryId for create_product/update_product) and echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| name* | string | The category name in the workspace's base language, up to 120 characters. Must be unique among categories with the same parent. |
| slug | any | URL segment for the category. Normalized to lowercase Latin letters, digits and hyphens whatever is sent (Cyrillic is transliterated); derived from the name when omitted. |
| parentId | any | Id of the parent category from list_categories, to nest this one under it; it must exist in this workspace. Omit or send null for a top-level category. |
| description | any | Prose a storefront shows at the top of the category shelf, in the workspace's base language (up to 4000 characters). Send null to clear it. |
Create a company (B2B account). The company name must be unique in the workspace. representationState is explicitly declared (unspecified, works_alone, or has_representatives), never inferred from contacts; an individual always uses unspecified. Enforces the workspace plan limit; the result echoes the operating workspace. Use search_companies first to avoid creating a duplicate.
| Argument | Type | Description |
|---|---|---|
| iban | any | The counterparty's IBAN. Optional. |
| name* | string | The company name. Required and unique within the workspace. |
| size | string | Company size band. Optional. One of: solo, small, medium, large, enterprise. |
| tags | array | Tags for segmentation. Optional. |
| any | The company email. Optional. | |
| phone | any | The company phone. Optional. |
| edrpou | any | Tax identifier: 8-digit EDRPOU or 10-digit taxpayer number. Optional. |
| status | string | Relationship status. Optional. One of: prospect, active, inactive. |
| ownerId | any |
Create a contact (person). Use search_companies for the companyId to link an employer. Enforces the workspace plan limit and validates the company/owner links; the result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| tags | array | Tags for segmentation. Optional. |
| any | The contact's email address. Optional. | |
| phone | any | The contact's phone number. Optional. |
| ownerId | any | User id of the workspace member who owns this contact. Optional. |
| jobTitle | any | The contact's job title. Optional. |
| lastName | any | The contact's last name. Optional. |
| companyId | any | Company id to link this contact to (from search_companies). Optional. |
| firstName* | string | The contact's first name. Required. |
| documentRole | any | The contact's role on sales documents. Optional. |
Create a social post as a DRAFT — nothing is published. Give it a working title, the main text, optional hashtags, the channels (each may carry its own text), and images: public https image links (Obriym stores its own copy), files the person attached in ChatGPT (the `files` field, filled by ChatGPT), links returned by create_image_upload for local files, and/or a catalog product whose photos are attached and whose sell-out later marks the live Telegram and Threads post as sold. Each channel's text, with hashtags, must fit that channel's limit (list_content_channels). Returns the post id and warnings — a channel that is not ready, Instagram without an image — to relay to the person. Not idempotent: each call creates a new draft. Then use schedule_content_post or publish_content_post. Echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| text | string | The post's main text, in the language the audience reads. Plain text: no markdown, links are written out in full. Never invent a price, discount, stock level or date — state only facts the user or the CRM gave you. |
| files | array | Image files the person attached in ChatGPT. ChatGPT fills this field itself; any other client leaves it out and passes image links instead (or uploads files with create_image_upload). |
| title* | string | An internal working title shown in Obriym's Publications list, e.g. "Monday — new arrivals". Never published. |
| format | string | post = a regular feed post; story = an Instagram/Facebook story, which needs an image. Defaults to post. |
| channels* | array |
Create a pipeline deal. Requires a stageId, title, and next-action note. Use list_pipeline_stages for the stageId, and search_companies/search_contacts to link a company or contact. Enforces the workspace plan limit; the result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| notes | any | Free-text notes on the deal. Optional. |
| title* | string | Deal title. Required. |
| amount | string | Deal value as a decimal string, e.g. 1500.00. Optional. |
| ownerId | any | User id of the workspace member to own the deal; null/omit for none. |
| stageId* | string | Pipeline stage id for the deal (from list_pipeline_stages). Required. |
| companyId | any | Company id to link the deal to (from search_companies); null/omit for none. |
| contactId | any | Contact id to link the deal to (from search_contacts); null/omit for none. |
| lostReason | any | Reason the deal was lost. Optional (required only for Closed-lost stages). |
| probability |
Create eBay DRAFT offers for up to 25 products — real writes to the seller's eBay account, but nothing is buyer-visible until publish_ebay_drafts. Run inspect_ebay_listings first and pass only products whose nextAction is create_draft and ready is true. Each product is attempted on its own: returns created, failed (each with a reason to look up in remediation.ebayPlaybook) and notAttempted (not reached in the time budget — call again with those ids). Refused until the owner switches on AI publishing, and while draft creation is not armed on the eBay connection. Not idempotent: a product that already has a draft fails with alreadyListed. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| productIds* | array | The exact products to create eBay draft offers for, at most 25 ids fetched with search_products. This creates drafts only and never makes them live. |
| marketplaceId | string | Omit this when the eBay connection sells on exactly one marketplace — the server fills it in automatically. Pass one of the audit's armed ebayDraftSetup.marketplaceIds only when several marketplaces are armed. This is a MARKETPLACE id (e.g. EBAY_DE, EBAY_IT) — never the eBay CONNECTION/adapter id. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"productIds"
],
"properties": {
"productIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
},
"maxItems": 25,
"minItems": 1,
"description": "The exact products to create eBay draft offers for, at most 25 ids fetched with search_products. This creates drafts only and never makes them live."
},
"marketplaceId": {
"enum": [
"EBAY_US",
"EBAY_GB",
"EBAY_DE",
"EBAY_AT",
"EBAY_BE",
"EBAY_FR",
"EBAY_IT",
"EBAY_NL",
"EBAY_ES",
"EBAY_IE",
"EBAY_PL",
"EBAY_CH",
"EBAY_CA",
"EBAY_AU"
],
"type": "string",
"description": "Omit this when the eBay connection sells on exactly one marketplace — the server fills it in automatically. Pass one of the audit's armed ebayDraftSetup.marketplaceIds only when several marketplaces are armed. This is a MARKETPLACE id (e.g. EBAY_DE, EBAY_IT) — never the eBay CONNECTION/adapter id."
}
}
}Get one-time links for uploading image FILES from the agent's own machine — for clients that can read local files and send HTTP requests (Claude Code, Cursor, scripts). A chat client passes image links instead, and ChatGPT passes attached files itself through the files field. For each link, send the raw file bytes with HTTP PUT within 15 minutes — for example: curl -X PUT --data-binary @photo.jpg "<uploadUrl>". One file per link; JPEG, PNG or WebP, at most 2 MB each (a bigger file is refused — there is no resize). The PUT answers JSON with url: pass that url to add_product_images (images[].url), create_content_post (imageUrls), set_category_image or set_brand_image (url), which store their own copy. Creating links changes nothing in the CRM. Returns { uploads: [{ uploadUrl, expiresAt }], maxBytes, allowedTypes }. Needs products:write or content:write.
| Argument | Type | Description |
|---|---|---|
| count | integer | How many upload links to create — one per file, at most 10. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"count": {
"type": "integer",
"default": 1,
"maximum": 10,
"minimum": 1,
"description": "How many upload links to create — one per file, at most 10."
}
}
}Create a lead. Idempotent by externalId (re-sending the same externalId returns the existing lead). Requires an email or phone. Enforces the workspace plan limit; the result echoes the workspace it landed in. Use update_lead to change it afterward.
| Argument | Type | Description |
|---|---|---|
| name* | string | The lead's full name or label. Required. |
| string | The lead's email. Provide email or phone (at least one). | |
| notes | string | Free-text notes about the lead. Optional. |
| phone | string | The lead's phone number. Provide email or phone (at least one). |
| source | string | Lead source; fixed to "website" for MCP-created leads. |
| externalId* | string | A stable unique id for this lead in your system — the idempotency key. Re-sending the same externalId returns the existing lead instead of creating a duplicate (e.g. 'mcp-<uuid>'). |
| companyName | string | The lead's company name, if known. Optional. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"externalId",
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "The lead's full name or label. Required."
},
"email": {
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 255,
"description": "The lead's email. Provide email or phone (at least one)."
},
"notes": {
"type": "string",
"maxLength": 2000,
"description": "Free-text notes about the lead. Optional."
},
"phone": {
"type": "string",
"maxLength": 50,
"description": "The lead's phone number. Provide email or phone (at least one)."
},
"source": {
"type": "string",
"const": "website",
"default": "website",
"description": "Lead source; fixed to \"website\" for MCP-created leads."
},
"externalId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "A stable unique id for this lead in your system — the idempotency key. Re-sending the same externalId returns the existing lead instead of creating a duplicate (e.g. 'mcp-<uuid>')."
},
"companyName": {
"type": "string",
"maxLength": 255,
"description": "The lead's company name, if known. Optional."
}
},
"additionalProperties": false
}Create an order with line items. Currency is required: use trusted source facts or CRM product prices; never guess or convert. Idempotent by externalId: re-sending the same request returns the existing order. Counts toward the plan's monthly order limit (403 PLAN_LIMIT_EXCEEDED when reached). The result echoes the operating workspace. Use search_products first. For a promo code use quote_order_promotion, then send promotion.code and promotion.expectedTotal. CRM alone calculates discounts, net totals, usage limits and free shipping. Do not invent a discount, send a legacy discountAmount, or promise free shipping from your own arithmetic.
| Argument | Type | Description |
|---|---|---|
| items* | array | Order line items (1-100). Each snapshots productName/sku/unitPrice. |
| notes | string | Internal note stored on the order. For a delivery instruction from the buyer use delivery.comment instead. |
| currency* | string | Required ISO 4217 currency code from the source facts or selected CRM product prices. Never guess or convert between currencies. |
| customer | object | Optional buyer snapshot (name/email/phone, or a storefront customer externalId). Omit for an anonymous order. |
| delivery | object | How the buyer asked to receive the order: carrier, branch/courier/pickup, branch text, recipient, cash-on-delivery and a delivery note. This is the buyer's choice at checkout — it does not dispatch anything. Record what actually ships with POST /orders/{externalId}/shipments. |
Create a catalog product. Defaults to draft status — publish it by sending status 'active' once it is complete. Use list_categories, list_brands and list_warehouses for the ids; SKU is generated when omitted and must be unique in the workspace. Set trackInventory with an opening stock to start counting units, which is recorded as the first movement in the product stock history. A bundle (type bundle with bundleItems) holds no stock of its own: its stock, tracking and cost are derived from its components, so a stock sent for it is refused and trackInventory/costPrice are ignored. If the target warehouse is set to list new products on the marketplaces, this product joins those channels. When productGroupId names an existing product model, the product joins that model as a new article and takes the model's shared content (name, description, category, brand, characteristics, translations) instead of the values sent. Enforces the workspace plan limit; the result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| ean | any | GTIN/EAN-8/12/13/14 barcode. Presence-and-shape validation only, no checksum. |
| mpn | any | Manufacturer part number — the maker's own code for the item, not the shop SKU. eBay requires it beside the brand in many categories. |
| sku | any | |
| name* | string | |
| size | any | |
| tags | array | |
| type |
Permanently delete ONE catalog category by id. Its products are NOT deleted but lose this category (so they also drop out of marketplace feeds that require a category); its subcategories move to the top level; its translations and linked marketplace category ids are removed. NOT reversible. Not idempotent in effect: a second call for the same id returns NOT_FOUND. Call get_category first to read productCount and subcategoryCount, and confirm with the user before deleting a category that has products. The result reports productsUncategorized and subcategoriesMovedToRoot and echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The category id returned by list_categories. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The category id returned by list_categories."
}
}
}Delete a post that has not been published — a draft, a scheduled post (its schedule goes with it) or one whose every channel failed. Its own stored images are deleted too; a linked product's photos are never touched. Refused for a post that went out on any channel: that record stays. This cannot be undone. Echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The publication id returned by create_content_post or list_content_posts. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "The publication id returned by create_content_post or list_content_posts."
}
}
}Delete the eBay DRAFT offer of up to 25 products; a live listing is refused — end it with withdraw_ebay_listings first. The CRM product itself is untouched. Works even while draft creation is disarmed on the connection, but still needs the owner's AI publishing switch. Returns done, failed and notAttempted. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| productIds* | array | Delete the eBay DRAFT offer for each of these products, at most 25 ids fetched with search_products. Only a product whose offer is still a draft is affected — a LIVE listing is refused; end it with withdraw_ebay_listings first if it must go. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"productIds"
],
"properties": {
"productIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
},
"maxItems": 25,
"minItems": 1,
"description": "Delete the eBay DRAFT offer for each of these products, at most 25 ids fetched with search_products. Only a product whose offer is still a draft is affected — a LIVE listing is refused; end it with withdraw_ebay_listings first if it must go."
}
}
}Delete a model's UNPUBLISHED eBay multi-variation draft: every variation's offer and the inventory item group are removed from eBay; the articles stay on the channel, ready for a new listing (together or one by one). A live listing is refused — end it with withdraw_ebay_variation_listing first. Refused until the workspace owner switches on AI publishing. Returns deleted. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| model* | string | The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"model"
],
"properties": {
"model": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations."
}
}
}Fetch one CRM activity in the selected workspace by activity id, including type, due date, completion state, assignee and linked entity. Use list_activities first when you only know the related lead/deal/contact.
| Argument | Type | Description |
|---|---|---|
| id* | string | The activity id returned by list_activities. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The activity id returned by list_activities."
}
}
}Fetch one catalog category by id: name, slug, parent, description, image, translations, the linked marketplace category ids (marketplaceCategories: Prom, Rozetka, OLX, Amazon, Google Merchant, each { id, label } or null), its direct subcategories (children), and productCount and subcategoryCount. Read-only. Use list_categories first to find the id, and call this before delete_category to see what a deletion would affect.
| Argument | Type | Description |
|---|---|---|
| id* | string | The category id returned by list_categories. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The category id returned by list_categories."
}
}
}Fetch one CRM company in the selected workspace by company id, including status, industry, owner and contact links when present. Use search_companies first when you only know the company name.
| Argument | Type | Description |
|---|---|---|
| id* | string | The company id returned by search_companies. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The company id returned by search_companies."
}
}
}Fetch one CRM contact in the selected workspace by contact id, including company, owner, tags and communication fields when present. Use search_contacts first when you only know a name, email or phone.
| Argument | Type | Description |
|---|---|---|
| id* | string | The contact id returned by search_contacts. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The contact id returned by search_contacts."
}
}
}Read one social post: its main text, hashtags, images, linked product, status and schedule, and per channel the text that channel gets (ownText or the main text), its length against the channel limit, whether the channel is ready, and what publishing returned there — status, link to the live post (permalink) or the network's error. Read-only. Use list_content_posts to find the id; call it after publish_content_post to report the links.
| Argument | Type | Description |
|---|---|---|
| id* | string | The publication id returned by create_content_post or list_content_posts. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "The publication id returned by create_content_post or list_content_posts."
}
}
}Fetch one CRM customer summary in the selected workspace by company id: a company that bought (a purchase order — processing, shipped, delivered or refunded, or with a settled payment — or a won deal that never became an order). Returns health, lifetimeValue (completed-order revenue plus won deals without an order), purchases (purchase orders plus won deals without an order), repeat (two or more purchases), lastPurchaseAt and wonDealsCount (every won deal). Read-only; a company with no purchase is not found. Use list_customers first when you only know the company name; use get_person_customer for a person who bought without a company.
| Argument | Type | Description |
|---|---|---|
| companyId* | string | The company/customer id returned by list_customers. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"companyId"
],
"properties": {
"companyId": {
"type": "string",
"minLength": 1,
"description": "The company/customer id returned by list_customers."
}
}
}Return the operational 'what needs attention today' snapshot for this workspace: active/qualified/stale lead counts, pipeline value, weighted forecast and overdue activities. Takes no arguments. Use get_report for period trend analytics instead.
No arguments.
{
"type": "object",
"properties": {}
}Fetch one pipeline deal in the selected workspace by deal id, including stage, value, probability and linked company/contact data when present. Use search_deals first when you only know the title or related customer.
| Argument | Type | Description |
|---|---|---|
| id* | string | The deal id returned by search_deals. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The deal id returned by search_deals."
}
}
}Read the eBay offers of up to 25 products live and return, per offer, the fulfillment, payment and return policy ids it carries now, the shipping policy name, its eBay site and status (PUBLISHED = live, UNPUBLISHED = draft), and matchesAssignment — whether it carries the product's own choice in the CRM (null when the product has none). Products with no draft or live listing are listed in withoutOffer; notAttempted were not reached in the time budget — call again with those ids. Reads only. Use get_product_ebay_fulfillment_policy for one product's full picture.
| Argument | Type | Description |
|---|---|---|
| productIds* | array | The products whose eBay offers to read, at most 25 ids from search_products. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"productIds"
],
"properties": {
"productIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
},
"maxItems": 25,
"minItems": 1,
"description": "The products whose eBay offers to read, at most 25 ids from search_products."
}
}
}Show a product MODEL as one eBay multi-variation listing: state (none, draft, live), marketplaceId, listingId and listingUrl, the stable groupKey, and every article of the model with its sku, colour, size, channelState on eBay and inclusion — included, not_active, not_on_channel (put it on the channel with set_channel_membership) or single_listing (it has its own eBay draft or listing, which must be deleted or ended first). Also says whether eBay is connected and whether the owner armed listing creation. Reads the CRM only. Use inspect_ebay_variation_listing for eBay's own checks before saving.
| Argument | Type | Description |
|---|---|---|
| model* | string | The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"model"
],
"properties": {
"model": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations."
}
}
}Fetch one CRM lead in the selected workspace by lead id, including status, source, assignee, tags, custom fields, score, notes and next action. Use search_leads first when you only know a name, email, phone or company.
| Argument | Type | Description |
|---|---|---|
| id* | string | The lead id returned by search_leads. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The lead id returned by search_leads."
}
}
}Read one lead's customer messages, oldest to newest: { at, channel, direction (inbound = from the customer, outbound = sent by the business), text (up to 2000 characters; truncated is true when cut), media ({ kind, contentType, name } or null — the file itself is never returned) }. A person who writes on two channels has two separate conversations: pass channel to read one, omit it to get all channels interleaved by time. Returns the most recent `limit` messages (default 30, max 100). Use it before drafting a reply or to answer what the customer asked. Read-only — this server cannot send messages. Use list_conversations to find leads with messages and get_lead for the lead card.
| Argument | Type | Description |
|---|---|---|
| limit | integer | How many of the newest messages to return (default 30). |
| leadId* | string | The lead id returned by list_conversations or search_leads. |
| channel | string | Channel slug to read (e.g. instagram, telegram, olx), as returned by list_conversations. Omit for every channel. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"leadId"
],
"properties": {
"limit": {
"type": "integer",
"maximum": 100,
"minimum": 1,
"description": "How many of the newest messages to return (default 30)."
},
"leadId": {
"type": "string",
"minLength": 1,
"description": "The lead id returned by list_conversations or search_leads."
},
"channel": {
"type": "string",
"maxLength": 40,
"minLength": 1,
"description": "Channel slug to read (e.g. instagram, telegram, olx), as returned by list_conversations. Omit for every channel."
}
}
}Fetch one connected marketplace in detail: every adapter on it with its setup state, last poll, last poll error, last catalog-sync outcome (`sync`, whose `lastSuccessAt` is the last run without a connection error — it survives failures, so it says how long a channel has been broken) and last product import, a classified `problem` (kind, needsReconnect, platformMessage, whatToDo) when anything failed, plus the channel sales, leads and product counts. For google_merchant each adapter also has `setup`: setupBlock (what stands in the way: not_connected, no_account, no_country, no_terms, not_armed — owner setup, not an outage), armed, lastPreviewAt, feedLabel, currency, termsAccepted, productUrlTemplate and contentLanguageOverride. Reads stored state only, never calls the marketplace. Use list_marketplaces first to see which platforms are connected, list_channel_products for the products on the channel and check_channel_readiness for what would be refused.
| Argument | Type | Description |
|---|---|---|
| platform* | string | The marketplace slug returned by list_marketplaces (prom, rozetka, woocommerce, shopify, olx, amazon, ebay, google_merchant). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"platform"
],
"properties": {
"platform": {
"type": "string",
"minLength": 1,
"description": "The marketplace slug returned by list_marketplaces (prom, rozetka, woocommerce, shopify, olx, amazon, ebay, google_merchant)."
}
}
}Read-only facts about Obriym CRM itself: approved marketing claims, conditions, limitations, review sources, plan prices/limits and integration scenarios/readiness with beta caveats; no customer data or external calls, and implementation review does not establish workspace configuration or customer results (empty assets means no screenshot supplied). Call before writing about Obriym, narrow by topic, use list_content_channels for publishing readiness, list_published_posts to avoid repeated topics and get_content_post to inspect a draft or publication result.
| Argument | Type | Description |
|---|---|---|
| topic | string | Topic to read, or all (default) for the full guide and topic index. Use integrations for channel readiness or pricing for current plan prices and limits. |
| locale | string | Language of the approved claims and limitations: uk (default) or en. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"topic": {
"enum": [
"all",
"overview",
"crm",
"catalog",
"orders",
"promotions",
"payments",
"shipping",
"documents",
"ai",
"content",
"buyer_account",
"b2b_portal",
"automation",
"tax",
"advertising",
"team",
"api",
"pricing",
"integrations"
],
"type": "string",
"default": "all",
"description": "Topic to read, or all (default) for the full guide and topic index. Use integrations for channel readiness or pricing for current plan prices and limits."
},
"locale": {
"enum": [
"uk",
"en"
],
"type": "string",
"default": "uk",
"description": "Language of the approved claims and limitations: uk (default) or en."
}
}
}Fetch full order detail in the selected workspace by externalId, including line items, payments, shipments and returns. Use list_orders first when you only know the customer or date.
| Argument | Type | Description |
|---|---|---|
| externalId* | string | The order externalId returned by list_orders. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"externalId"
],
"properties": {
"externalId": {
"type": "string",
"minLength": 1,
"description": "The order externalId returned by list_orders."
}
}
}Fetch one person who bought without a company, by contact id: health, lifetimeValue (completed-order revenue plus won deals without an order), purchases, repeat, firstPurchaseAt, lastPurchaseAt and contact details. Read-only; a contact who never bought without a company is not found. Use list_people_customers or search_contacts first when you only know the name, email or phone; use get_customer for a company.
| Argument | Type | Description |
|---|---|---|
| contactId* | string | The contact/customer id returned by list_people_customers. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"contactId"
],
"properties": {
"contactId": {
"type": "string",
"minLength": 1,
"description": "The contact/customer id returned by list_people_customers."
}
}
}Fetch one catalog product in the selected workspace by product id or SKU — returned in any status (draft, active, or archived; check the status field) — with every catalog field: prices, cost, stock and trackInventory, availability, variant fields, all attributes (characteristics) and translations, identifiers, weight and dimensions, images, videos, bundle components and related products; plus its model, warehouse and supplier by name, supplierOffers (what the supplier last said: quantity, restock date, purchase price, state), every sales channel with its listing and moderation state, the collections it is in and its model's review summary. A bundle's stock and cost are derived from its components. Provide exactly one known identifier; use search_products first when unsure (search covers active products only).
| Argument | Type | Description |
|---|---|---|
| id | string | The product id returned by search_products. |
| sku | string | The product SKU returned by search_products. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The product id returned by search_products."
},
"sku": {
"type": "string",
"minLength": 1,
"description": "The product SKU returned by search_products."
}
}
}Show ONE product's eBay shipping policy. Per eBay site: assignedPolicyId (the product's own choice, null when it has none), defaultPolicyId (the connection default) and effectivePolicyId with effectiveSource — product, connection_default or first_available — the policy a new draft or a go-live would carry, plus that site's policies. For a product with a draft or live listing it also reads the eBay offer live: offer.fulfillmentPolicyId is what buyers see now. Reads only. Use list_ebay_fulfillment_policies for the costs of every policy and get_ebay_offer_policies to read several products' offers at once.
| Argument | Type | Description |
|---|---|---|
| productId* | string | A product id returned by search_products. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"productId"
],
"properties": {
"productId": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
}
}
}Everything about ONE product's prices in one call: its own price, old price and currency; the price-list rows (other currencies); per-channel price overrides (platform, currency, price); wholesale quantity breaks per currency; the purchase cost with its currency (a bundle's cost is derived from its components and cannot be set on it); and the markup over cost per sale currency (marginPercent = price ÷ cost − 1, in percent; not a margin on the price) — the cost crossed at the workspace's stated rate, null with missingRate true when no rate is stated. Read-only. Use search_products for the id; call it before set_product_channel_price, set_product_price_tiers or upsert_product_prices so you change the right row, and after a change to confirm it. For a whole group of products use preview_bulk_price_change.
| Argument | Type | Description |
|---|---|---|
| id* | string | The product id returned by search_products or get_product — never a SKU or a name. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The product id returned by search_products or get_product — never a SKU or a name."
}
}
}Return one aggregated analytics report over a period for this workspace, selected by the report parameter: lead_source_conversion, pipeline_velocity, team_performance, revenue_trend, product_sales (units, revenue and gross margin per brand/category/SKU) or stock_valuation (units on hand and their value per warehouse, per cost currency). Each returns aggregated rows (no per-record data); days tunes the look-back for lead_source_conversion, team_performance and product_sales, months the span for revenue_trend; pipeline_velocity and stock_valuation take no period. Use get_dashboard_overview for today's operational snapshot instead.
| Argument | Type | Description |
|---|---|---|
| days | any | Look-back window for conversion/team reports (default 90/30). |
| months | integer | Number of months for the revenue-trend report (default 6). |
| report* | string | Which analytics report to return. lead_source_conversion: leads and conversion rate per source (uses days). pipeline_velocity: average time deals spend in each stage. team_performance: revenue and activity per member (uses days). revenue_trend: won revenue by month (uses months). product_sales: units, revenue and gross margin per brand, category and SKU, plus a trend (uses days). stock_valuation: units on hand and their value at weighted-average cost, per warehouse and per cost currency — currencies are reported separately and never added together (takes no period). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"report"
],
"properties": {
"days": {
"anyOf": [
{
"type": "number",
"const": 30
},
{
"type": "number",
"const": 90
},
{
"type": "number",
"const": 365
}
],
"description": "Look-back window for conversion/team reports (default 90/30)."
},
"months": {
"type": "integer",
"maximum": 24,
"minimum": 1,
"description": "Number of months for the revenue-trend report (default 6)."
},
"report": {
"enum": [
"lead_source_conversion",
"pipeline_velocity",
"team_performance",
"revenue_trend",
"product_sales",
"stock_valuation"
],
"type": "string",
"description": "Which analytics report to return. lead_source_conversion: leads and conversion rate per source (uses days). pipeline_velocity: average time deals spend in each stage. team_performance: revenue and activity per member (uses days). revenue_trend: won revenue by month (uses months). product_sales: units, revenue and gross margin per brand, category and SKU, plus a trend (uses days). stock_valuation: units on hand and their value at weighted-average cost, per warehouse and per cost currency — currencies are reported separately and never added together (takes no period)."
}
}
}Show which account and workspace this connection operates: signed-in name/email (OAuth only), workspace name, plan, connection type and granted scopes — and the server itself: its version and every tool it has now (server.tools), with how to refresh an AI app whose tool list is older (server.refreshHint). Call this when the user asks 'which account or workspace am I connected to?', and when the user asks for something your tool list has no tool for: if server.tools has it, your list is outdated — relay server.refreshHint instead of saying Obriym cannot do it. Sign-in connections can use list_workspaces and select_workspace to see or change the bound workspace.
No arguments.
{
"type": "object",
"properties": {}
}Check up to 25 products against eBay before any write, with the same live preflight the CRM's eBay channel page and the real draft and publish calls run. Per product it returns the eBay state (off, member, draft, live, ended), nextAction (create_draft, publish_draft or none), whether that step is ready and, when not, the blocking reason with details. ebayDraftSetup lists the armed eBay sites and their currencies; remediation.ebayPlaybook maps every reason to the tool that fixes it; publishingEnabled says whether the owner allows AI to publish in this workspace. Reads eBay, never writes. Use search_products first for the ids; after a fix with update_product, upsert_product_prices, upsert_product_attributes or upsert_product_translation, call it again — a reason can change or clear.
| Argument | Type | Description |
|---|---|---|
| productIds* | array | The products to check, at most 25 ids from search_products. |
| marketplaceId | string | Omit it when the eBay connection sells on one site — the server fills it in. Pass one of ebayDraftSetup.marketplaceIds only when several are armed. A MARKETPLACE id such as EBAY_IT, never the eBay connection id. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"productIds"
],
"properties": {
"productIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
},
"maxItems": 25,
"minItems": 1,
"description": "The products to check, at most 25 ids from search_products."
},
"marketplaceId": {
"enum": [
"EBAY_US",
"EBAY_GB",
"EBAY_DE",
"EBAY_AT",
"EBAY_BE",
"EBAY_FR",
"EBAY_IT",
"EBAY_NL",
"EBAY_ES",
"EBAY_IE",
"EBAY_PL",
"EBAY_CH",
"EBAY_CA",
"EBAY_AU"
],
"type": "string",
"description": "Omit it when the eBay connection sells on one site — the server fills it in. Pass one of ebayDraftSetup.marketplaceIds only when several are armed. A MARKETPLACE id such as EBAY_IT, never the eBay connection id."
}
}
}Run every check saving a model's eBay multi-variation listing would run, writing nothing: each article's required fields and price in the marketplace currency, the variation axes (colour and/or size, named as the eBay site names them), duplicate or missing variation values, the category (suggested from the title, or the saved listing's), whether it allows variations, item condition, required item specifics, one shipping policy for all articles, business policies and inventory location. Returns ready, marketplaceId, categoryId, axes, variationCount and issues (reason, message, skus). Needs a marketplace but not the owner's arming. Reads eBay. Use save_ebay_variation_listing once ready is true.
| Argument | Type | Description |
|---|---|---|
| model* | string | The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations. |
| marketplaceId | string | eBay marketplace id (EBAY_IT, EBAY_DE…) for a FIRST save, when the connection sells on several. A saved listing keeps its marketplace; omit it then. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"model"
],
"properties": {
"model": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations."
},
"marketplaceId": {
"type": "string",
"maxLength": 32,
"minLength": 1,
"description": "eBay marketplace id (EBAY_IT, EBAY_DE…) for a FIRST save, when the connection sells on several. A saved listing keeps its marketplace; omit it then."
}
}
}List this workspace's activities (tasks, calls, meetings, emails, notes), filtered by type/assignee/overdue/completion/linked-entity and paginated. Returns summary rows (id, type, title, priority, dueDate, completed, assignee, linked lead/contact/company/deal, isOverdue) plus pagination { page, perPage, total }. Use get_activity to fetch one activity's full detail by id.
| Argument | Type | Description |
|---|---|---|
| q | string | Free-text search over the activity title. Omit for no text filter. |
| page | integer | 1-based page number of results to return. Default 1. |
| type | string | Filter by activity type. Omit for any. Allowed: task, call, meeting, email, note. |
| dealId | string | Filter to activities linked to this deal id (from search_deals). |
| leadId | string | Filter to activities linked to this lead id (from search_leads). |
| overdue | string | Set "true" to return only overdue activities (past due date, not completed). |
| perPage | integer | Number of activities per page (1-100). Default 20. |
| companyId | string |
List this workspace catalog brands with id, name, description and website. Use a brand id here as the brandId for create_product/update_product, or as the search_products brand filter.
No arguments.
{
"type": "object",
"properties": {}
}List this workspace catalog categories as a flat array, each with id, name, slug, parentId (null for a root category), description, googleProductCategory, imageUrl, translations and marketplaceCategories (the Prom, Rozetka, OLX, Amazon and Google Merchant category ids already linked, each as { id, label } or null). Categories are workspace-global, not per warehouse. Use a category id here as the categoryId for create_product/update_product, or as the search_products category filter. Use get_category for one category's product and subcategory counts, and search_marketplace_categories to find a marketplace category id to link.
No arguments.
{
"type": "object",
"properties": {}
}List the products that are on one marketplace, with each listing external id, what the marketplace last reported about it (`presence`, valid only when `observedAt` is set — null `observedAt` means the marketplace has never been asked about that listing, not that it is absent; Prom is reconciled every 15 minutes, other channels only when a sync or publish runs), whether the workspace paused syncing it, its price and stock. Also returns the honest totals over the whole channel and the ACTIVE products that have no listing there at all (the 'did not match by SKU' list), which is usually the answer when a push updated fewer products than expected. Use check_channel_readiness for why a product would be refused.
| Argument | Type | Description |
|---|---|---|
| platform* | string | The marketplace slug returned by list_marketplaces (prom, rozetka, woocommerce, shopify, olx, amazon, ebay, google_merchant). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"platform"
],
"properties": {
"platform": {
"type": "string",
"minLength": 1,
"description": "The marketplace slug returned by list_marketplaces (prom, rozetka, woocommerce, shopify, olx, amazon, ebay, google_merchant)."
}
}
}List the social channels this workspace can publish posts to — Telegram channel, Instagram, Facebook page, LinkedIn, Threads, Viber channel — with, per channel, whether it is ready, where it posts (destination), its public address (profile: profileUrl, publicFeedUrl — a public Telegram channel reads without signing in at t.me/s/<name>, older posts via ?before=<post id> — and readableBy: anyone, login_required or not_public), its text limit (maxTextLength) and, when not ready, the setup step the person must do in Obriym. Open the profile with your own browsing to read every post the channel already has, including ones written outside Obriym. Also returns now (the current time on the workspace's clock) and the workspace time zone — build schedule_content_post times from them — the image rules, and publishingEnabled: whether the workspace owner allows AI clients to publish or schedule. Read-only. Call it before create_content_post and only target ready channels.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
}List the languages this workspace writes product content in: the base language (the text stored on products, categories and brands themselves), the extra languages the owner added, and the offered set — every language the CRM shows as a translation tab. Each entry is an ISO 639-1 code with its English name. Read-only. Call it BEFORE writing any translation (upsert_product_translation, upsert_category_translation, upsert_brand_translation) and write only offered languages; never write the base language as a translation.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
}List the workspace's social posts, newest first, 20 per page: id, working title, status (draft, scheduled, publishing, published, partial, failed), channels, scheduled and published times. Filter by status or by part of the title. Read-only. Use get_content_post for one post's texts and per-channel results; use it to check what is already scheduled before planning more posts.
| Argument | Type | Description |
|---|---|---|
| page | integer | Page number, 20 publications per page, newest first. |
| query | string | Part of a publication's working title. |
| status | string | Only publications in this state: draft, scheduled, publishing, published, partial (some channels failed) or failed. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"page": {
"type": "integer",
"maximum": 500,
"minimum": 1,
"description": "Page number, 20 publications per page, newest first."
},
"query": {
"type": "string",
"maxLength": 120,
"description": "Part of a publication's working title."
},
"status": {
"enum": [
"draft",
"scheduled",
"publishing",
"published",
"partial",
"failed"
],
"type": "string",
"description": "Only publications in this state: draft, scheduled, publishing, published, partial (some channels failed) or failed."
}
}
}List customer conversations across every connected channel (Instagram, Messenger, WhatsApp and comments, Telegram, OLX, Prom, eBay, Threads replies, the B2B portal, buyer order pages …). One row per lead and channel, newest first: { leadId, leadName, channel, lastMessageAt, lastMessageText (first 300 characters), lastDirection (inbound = from the customer), awaitingReply (the customer wrote last) } plus pagination { page, perPage, total }. Open conversations only — converted or disqualified leads and closed threads are left out. Filter by channel, by awaitingReply, or by a text match on the customer's name or last message. Read-only: replies are written by a person in the CRM Inbox, this server cannot send messages. Use get_lead_conversation to read one thread's messages and get_lead for the lead card.
| Argument | Type | Description |
|---|---|---|
| page | integer | 1-based page of 25 conversations (default 1). |
| query | string | Text to match against the customer's name or the last message. |
| channel | string | Channel slug to keep, as returned in the channel field of earlier results (e.g. instagram, telegram, olx). Omit for all channels. |
| awaitingReply | boolean | True returns only conversations whose last message is from the customer and still wait for an answer. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"page": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based page of 25 conversations (default 1)."
},
"query": {
"type": "string",
"maxLength": 200,
"description": "Text to match against the customer's name or the last message."
},
"channel": {
"type": "string",
"maxLength": 40,
"minLength": 1,
"description": "Channel slug to keep, as returned in the channel field of earlier results (e.g. instagram, telegram, olx). Omit for all channels."
},
"awaitingReply": {
"type": "boolean",
"description": "True returns only conversations whose last message is from the customer and still wait for an answer."
}
}
}List CRM customers: companies that bought — a purchase order (processing, shipped, delivered or refunded, or with a settled payment) or a won deal that never became an order. Filter by health, lifetime-value bucket, owner, name search or minimum won deals; sorted by lifetime value and paginated. Returns summary rows (id, name, health, lifetimeValue = completed-order revenue plus won deals without an order, purchases = purchase orders plus won deals without an order, repeat = two or more purchases, lastPurchaseAt, wonDealsCount = every won deal, lastActivityAt, owner) plus pagination { page, perPage, total }. Read-only. Use get_customer to fetch one customer's detail by company id; use list_people_customers for people who bought without a company (shop buyers).
| Argument | Type | Description |
|---|---|---|
| q | string | Free-text search over the customer company name. Omit for no text filter. |
| ltv | string | Filter by lifetime-value bucket. Omit for any. Allowed: lt10k, 10k50k, gt50k. |
| page | integer | 1-based page number of results to return. Default 1. |
| health | string | Filter by customer health. Omit for any. Allowed: healthy, at_risk, churned. |
| ownerId | string | Filter to customers owned by this workspace member's user id. |
| perPage | integer | Number of customers per page (1-100). Default 25. |
List the eBay shipping (fulfillment) business policies the seller has on each eBay site the connection sells on: fulfillmentPolicyId, name, freeShipping, shippingCost of the first domestic service (null for CALCULATED shipping), costType, handlingTime, domestic and international services, ship-to regions, and isDefault — the connection default. productCount is how many products chose the policy themselves; staleAssignments are product choices pointing at a policy eBay no longer has. Reads the stored copy; a site never read before is read from eBay, and refresh true reads eBay now. Reads only. Use a fulfillmentPolicyId from here with set_product_ebay_fulfillment_policy, bulk_set_ebay_fulfillment_policy or set_ebay_default_fulfillment_policy; for one product's policy use get_product_ebay_fulfillment_policy.
| Argument | Type | Description |
|---|---|---|
| refresh | boolean | true reads the policies from eBay now instead of the stored copy. A marketplace never read before is read from eBay either way. |
| marketplaceId | string | An eBay MARKETPLACE id such as EBAY_IT. Omit it to list every marketplace the eBay connection sells on. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"refresh": {
"type": "boolean",
"description": "true reads the policies from eBay now instead of the stored copy. A marketplace never read before is read from eBay either way."
},
"marketplaceId": {
"enum": [
"EBAY_US",
"EBAY_GB",
"EBAY_DE",
"EBAY_AT",
"EBAY_BE",
"EBAY_FR",
"EBAY_IT",
"EBAY_NL",
"EBAY_ES",
"EBAY_IE",
"EBAY_PL",
"EBAY_CH",
"EBAY_CA",
"EBAY_AU"
],
"type": "string",
"description": "An eBay MARKETPLACE id such as EBAY_IT. Omit it to list every marketplace the eBay connection sells on."
}
}
}List this workspace's lead sources (built-in plus custom), with each source's key, label and active state. Pass includeInactive to also return archived sources. Use set_lead_sources to add or archive a source; use a source key here as the source filter for search_leads.
| Argument | Type | Description |
|---|---|---|
| includeInactive | boolean | Set true to include archived/inactive lead sources. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"includeInactive": {
"type": "boolean",
"description": "Set true to include archived/inactive lead sources."
}
}
}List every marketplace connected to this workspace with its setup state, health, last activity, any current sync error with `problem` (its kind, whether a person must reconnect the account, and what to do), orders revenue per currency, leads, product counts on the channel and how many imported products are waiting to be reviewed. advertising: true marks a channel where nothing is sold (Google Merchant), so its zero revenue is structural. Answers 'which channels do I sell on and is anything broken'. Takes no arguments. Use get_marketplace for one channel in detail, list_channel_products for what is on it, and check_channel_readiness for what it will refuse.
No arguments.
{
"type": "object",
"properties": {}
}List this workspace's orders, filtered by status/customer/created-date and paginated. Returns summary rows (externalId, status, currency, totalAmount, itemCount, timestamps) plus pagination { page, perPage, total }, newest first. Use get_order to fetch one order's full detail (line items, payments, shipments, returns) by externalId.
| Argument | Type | Description |
|---|---|---|
| to | string | Only orders created at or before this ISO 8601 timestamp (e.g. 2026-02-28T23:59:59Z). |
| from | string | Only orders created at or after this ISO 8601 timestamp (e.g. 2026-01-31T00:00:00Z). |
| page | integer | 1-based page number of results to return. Default 1. |
| status | string | Filter by order status. Omit to return every status. Allowed: pending, confirmed, processing, shipped, delivered, cancelled, refunded. |
| perPage | integer | Number of results per page (1-100). Default 20. |
| customerExternalId | string | Filter to one storefront customer by their externalId (the id from the source system). Omit to list all customers' orders. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"to": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
"description": "Only orders created at or before this ISO 8601 timestamp (e.g. 2026-02-28T23:59:59Z)."
},
"from": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
"description": "Only orders created at or after this ISO 8601 timestamp (e.g. 2026-01-31T00:00:00Z)."
},
"page": {
"type": "integer",
"default": 1,
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based page number of results to return. Default 1."
},
"status": {
"enum": [
"pending",
"confirmed",
"processing",
"shipped",
"delivered",
"cancelled",
"refunded"
],
"type": "string",
"description": "Filter by order status. Omit to return every status. Allowed: pending, confirmed, processing, shipped, delivered, cancelled, refunded."
},
"perPage": {
"type": "integer",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Number of results per page (1-100). Default 20."
},
"customerExternalId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "Filter to one storefront customer by their externalId (the id from the source system). Omit to list all customers' orders."
}
}
}List people (CRM contacts) who bought without a company — shop buyers: a purchase order without a company (processing, shipped, delivered or refunded, or with a settled payment) or a won deal of theirs without a company that never became an order. A company's purchases never count for the person who represents it. Filter by health, lifetime-value bucket, repeat (two or more purchases) or search over name, email and phone; sorted by lifetime value and paginated. Returns rows (id = contact id, firstName, lastName, email, phone, health, lifetimeValue, purchases, repeat, firstPurchaseAt, lastPurchaseAt, lastActivityAt) plus pagination { page, perPage, total }. Read-only. Use get_person_customer for one person by contact id; use list_customers for companies.
| Argument | Type | Description |
|---|---|---|
| q | string | Free-text search over the person's first name, last name, email and phone. Omit for no text filter. |
| ltv | string | Filter by lifetime-value bucket. Omit for any. Allowed: lt10k, 10k50k, gt50k. |
| page | integer | 1-based page number of results to return. Default 1. |
| health | string | Filter by customer health. Omit for any. Allowed: healthy, at_risk, churned. |
| repeat | any | true = only people with two or more purchases; false or omitted = everyone. |
| perPage | integer | Number of people per page (1-100). Default 25. |
List this workspace's pipeline stages in order, with each stage's id, name, kind, default probability, WIP limit and position. Use configure_pipeline to change a stage, and the stage id here as the stageId for create_deal / transition_deal.
No arguments.
{
"type": "object",
"properties": {}
}List what this workspace has already published to its social channels, newest first: per post the exact text each channel got (hashtags included), the channel, permalink, publishedAt, title, contentPostId and productId, plus per channel the publishing rhythm (lastPostedAt, postsLast7Days, postsLast30Days, medianGapHours, nextScheduledAt, scheduledCount) and, in sources, the channel's public address (profileUrl, publicFeedUrl) with a note. Only posts published through Obriym are listed. Posts typed directly into the network are not stored here — before planning, compare against BOTH this list and the channel itself: open sources[].publicFeedUrl or profileUrl with your own browsing to read everything posted there (a public Telegram channel reads at t.me/s/<name>; LinkedIn and Instagram may need a login; a Viber channel is read in the Viber app; a private channel cannot be read from outside). Never claim the channel had no other posts, and say so when a channel cannot be read. Use it before planning or writing new posts: avoid repeating a topic, product or phrasing, and use the rhythm to choose dates that keep a steady flow; then create_content_post and schedule_content_post. Filter by channel or by days (YYYY-MM-DD on the workspace's clock), 20 per page. Read-only. Use list_content_posts for drafts and scheduled posts, get_content_post for one post's per-channel results.
| Argument | Type | Description |
|---|---|---|
| to | string | Last day to include, YYYY-MM-DD, inclusive, on the workspace's clock. Omit for no upper bound. |
| from | string | First day to include, YYYY-MM-DD, a calendar day on the workspace's clock. Omit for no lower bound. |
| page | integer | Page number, newest posts first. Default 1. |
List the workspace's suppliers: id, name, status (active or archived), the currency they invoice in and how many products each covers (productCount). Read-only. Use it as the id source for a {kind:'supplier'} scope of preview_bulk_price_change and apply_bulk_price_change — 'raise every Sipec product by 5%'. Categories, brands and warehouses come from list_categories, list_brands and list_warehouses.
No arguments.
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {}
}List this workspace warehouses with id, name, description, phone, address (the street line), country (ISO code), city, postalCode, workingHours (free text) and pickupEnabled (whether the warehouse is offered as a self-pickup point). A product lives in at most one warehouse, and the warehouse decides the inventory-tracking default and which sales channels new products are listed on. Use a warehouse id here as the warehouseId for create_product.
No arguments.
{
"type": "object",
"properties": {}
}List every workspace the connected user belongs to (id, name, role) and mark which one this connection currently operates. OAuth sign-in connections only. Use select_workspace to switch.
No arguments.
{
"type": "object",
"properties": {}
}Dry run of a bulk price change — step 1 of 2; nothing is written. Give a rule (percent, fixed, fromCost, discount, endDiscount, compareAtMarkup, compareAtClear), a scope (a named category, brand, supplier, warehouse or model, or up to 100 explicit product ids) and optionally a target (the product's price, a price-list currency, or the purchase cost). Returns totalItems (how many products would change), a sample of up to 10 with from/to, old price and cost, belowCost (how many would sell below their cost), skipped grouped by reason (no price, no cost, no rate, unchanged, …), the currency, and a digest. Always show the person the counts, the sample, the skipped reasons and any belowCost warning BEFORE applying. Then call apply_bulk_price_change with the SAME rule, scope and target and this digest. Ids come from list_categories, list_brands, list_suppliers, list_warehouses (a category includes its sub-categories only with includeSubcategories) and search_products. Read-only and repeatable.
| Argument | Type | Description |
|---|---|---|
| rule* | any | HOW prices move. The target 'cost' accepts only op 'percent'. Pick the one that matches the request: a percent change, a fixed price, a markup over cost, a discount (and its end), or the old price. |
| scope* | any | WHICH products. Prefer a named container (category, brand, supplier, warehouse) when the person says 'all products of …' — it is read back by name in the preview. There is no free filter: a request like 'everything cheaper than 100' is not a scope; find the products first and send their ids. |
| target | any | WHICH number moves. Omit it to change the product's own selling price. Use {field:'price', currency:'EUR'} for the euro price list, {field:'cost'} for the purchase cost. |
Publish a post NOW to every ready channel of it — a real, public post in the business's name that followers see at once and that cannot be taken back from Obriym. A channel already published is never sent twice, so calling it again only retries the channels that failed or were not ready. Returns, per channel, the outcome (published, failed, already_published, skipped_not_configured with the setup step, skipped_empty, skipped_unsupported), the link to the live post and the network's error. Needs the owner's "AI may publish to social channels" switch (publishingEnabled in list_content_channels). Confirm with the person before calling it unless they asked for the publication outright. Echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The publication id returned by create_content_post or list_content_posts. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "The publication id returned by create_content_post or list_content_posts."
}
}
}Make the eBay DRAFT offers of up to 25 products LIVE and buyer-visible — a real publication on the seller's account. The item and offer are refreshed from the current product first, so a price, title, photo or characteristic fixed after the draft was made is published too. Pass only products whose nextAction from inspect_ebay_listings is publish_draft. Returns done, failed (with reasons) and notAttempted. Never tell the user a listing is live unless it is counted in done. Refused until the owner switches on AI publishing. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| productIds* | array | Make each product's eBay DRAFT offer LIVE and buyer-visible, at most 25 ids fetched with search_products. The item and offer are refreshed from current product data first, then published — this is a real, consequential publication, not a preview. Report every named per-product failure. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"productIds"
],
"properties": {
"productIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
},
"maxItems": 25,
"minItems": 1,
"description": "Make each product's eBay DRAFT offer LIVE and buyer-visible, at most 25 ids fetched with search_products. The item and offer are refreshed from current product data first, then published — this is a real, consequential publication, not a preview. Report every named per-product failure."
}
}
}Publish a product model on eBay as ONE live listing with variations: saves it first exactly like save_ebay_variation_listing (so eBay gets the articles as they are now), then publishes the whole group — a real listing buyers can purchase. Returns status: blocked (with issues — reason, message, skus — and nothing written), saved (a draft on eBay) or published, plus marketplaceId, listingId, variationCount, failed (variations eBay refused, by sku — nothing is published while any) and removedSkus (articles that left the listing). Needs listing creation armed on the eBay connection, and is refused until the workspace owner switches on AI publishing. Confirm with the user before calling. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| model* | string | The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations. |
| marketplaceId | string | eBay marketplace id (EBAY_IT, EBAY_DE…) for a FIRST save, when the connection sells on several. A saved listing keeps its marketplace; omit it then. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"model"
],
"properties": {
"model": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations."
},
"marketplaceId": {
"type": "string",
"maxLength": 32,
"minLength": 1,
"description": "eBay marketplace id (EBAY_IT, EBAY_DE…) for a FIRST save, when the connection sells on several. A saved listing keeps its marketplace; omit it then."
}
}
}Send this workspace's catalog, or just the products you name, to Google Merchant Center now — the same as the "Update now" button on the Google Merchant channel page. It is a REAL write to Google: products become or stay visible in Google Shopping. It runs only the product push the owner has ALREADY armed on the connection (otherwise it is refused) and only after the owner accepted Google's terms; it never arms anything and never changes settings. Refused until the owner switches on AI publishing. It is rarely needed: an hourly job sends the catalog anyway, so use it only when a fix must reach Google before the next run. To get one fixed product to Google immediately pass productIds (1 to 25): only those products are sent, and the result is { adapterId, adapterName, sent, failed, blocked, notOnChannel } — sent and failed (with Google's own message) name each product, blocked carries the readiness reason, notOnChannel lists ids that are not active channel members; this does not change the channel's last-run summary. Without productIds the whole catalog is sent, never-sent and changed products first, bounded by a time budget — if truncated is true, call it again. Returns { adapterId, adapterName, outcome } where outcome has pushed, failed, blocked, ready, total, truncated, lastSyncAt and failedSample (up to 5 refused products with Google's message). A failure that came back from Google carries reason (for example auth_expired) with details.needsReconnect and details.whatToDo: auth_expired, such as invalid_grant, means a person must reconnect the Google account on the adapter page, and retrying will not help. Use check_channel_readiness first to see which products would be withheld, and get_marketplace for the last run. Not idempotent. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| adapterId | string | The Google Merchant connection to push (adapter id, listed by get_marketplace for google_merchant). Omit it when the workspace has exactly one Google Merchant connection — the server picks it; with several connections the call is refused until one is named. |
Validate a known promo code against trusted cart prices, currency and buyer facts. Returns the CRM-calculated discount, net order total and delivery terms without creating an order or reserving a use. The code must be enabled for this connection's source; a personal or capture code also needs the same buyer email (or customer.externalId of a profile with it). reservesUse is false: nothing is claimed. A refusal returns a public reason (for example code_unavailable, email_mismatch, not_eligible, minimum_not_met). Promo codes run on the Team and Scale plans; on Free every code is code_unavailable. Never invent a code or discount. Then call create_order with promotion.code and promotion.expectedTotal; the CRM checks eligibility and capacity again.
| Argument | Type | Description |
|---|---|---|
| items* | array | Order line items (1-100). Each snapshots productName/sku/unitPrice. |
| currency* | string | Required ISO 4217 currency code (uppercase) of the cart lines; no default and no conversion. |
| customer | object | Optional buyer snapshot (name/email/phone, or a storefront customer externalId). Omit for an anonymous order. |
| delivery | object | How the buyer asked to receive the order: carrier, branch/courier/pickup, branch text, recipient, cash-on-delivery and a delivery note. This is the buyer's choice at checkout — it does not dispatch anything. Record what actually ships with POST /orders/{externalId}/shipments. |
| promotion |
Delete each product's eBay draft and create a fresh one from its current data, for up to 25 products. Needed only when a draft must move to another category or eBay site, or the reason is ebayDraftOfferMissing or ebayNoOfferId — ordinary edits are picked up by publish_ebay_drafts. A live listing is refused. If the delete succeeds but the new draft fails, that product is left with no draft and its failure says so. Refused until the owner switches on AI publishing. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| productIds* | array | Delete each product's existing eBay draft offer and create a fresh one from its CURRENT data, at most 25 ids fetched with search_products. Use this when a draft must move to a different category or marketplace, or eBay rejected its offer and a plain retry will not fix it. A LIVE listing is refused. If the delete succeeds but the new create fails, the failure says so explicitly — that product is then on the channel with NO draft. |
| marketplaceId | string | Omit this when the eBay connection sells on exactly one marketplace — the server fills it in automatically. Pass one of the audit's armed ebayDraftSetup.marketplaceIds only when several are armed. This is a MARKETPLACE id (e.g. EBAY_DE) — never the eBay CONNECTION/adapter id. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"productIds"
],
"properties": {
"productIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
},
"maxItems": 25,
"minItems": 1,
"description": "Delete each product's existing eBay draft offer and create a fresh one from its CURRENT data, at most 25 ids fetched with search_products. Use this when a draft must move to a different category or marketplace, or eBay rejected its offer and a plain retry will not fix it. A LIVE listing is refused. If the delete succeeds but the new create fails, the failure says so explicitly — that product is then on the channel with NO draft."
},
"marketplaceId": {
"enum": [
"EBAY_US",
"EBAY_GB",
"EBAY_DE",
"EBAY_AT",
"EBAY_BE",
"EBAY_FR",
"EBAY_IT",
"EBAY_NL",
"EBAY_ES",
"EBAY_IE",
"EBAY_PL",
"EBAY_CH",
"EBAY_CA",
"EBAY_AU"
],
"type": "string",
"description": "Omit this when the eBay connection sells on exactly one marketplace — the server fills it in automatically. Pass one of the audit's armed ebayDraftSetup.marketplaceIds only when several are armed. This is a MARKETPLACE id (e.g. EBAY_DE) — never the eBay CONNECTION/adapter id."
}
}
}Remove a line item from an order. Recomputes the order total. Only allowed while the order is pending or confirmed; otherwise it fails with 409 CONFLICT "Order lines can only be changed while the order is pending or confirmed". Use get_order to find the order's externalId and the item's itemId. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| itemId* | string | The order item id returned by get_order. |
| externalId* | string | The order externalId returned by list_orders or create_order. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"externalId",
"itemId"
],
"properties": {
"itemId": {
"type": "string",
"minLength": 1,
"description": "The order item id returned by get_order."
},
"externalId": {
"type": "string",
"minLength": 1,
"description": "The order externalId returned by list_orders or create_order."
}
}
}Save a product model on eBay as ONE listing with variations — every active article of the model on the eBay channel is a variation (its own SKU, price and stock; buyers choose colour and size). Writes the inventory items, the inventory item group and each variation's offer; a draft stays unpublished. When the listing is already LIVE this updates it in place: new variations, prices and texts reach buyers at once, and articles that no longer qualify leave it. Returns status: blocked (with issues — reason, message, skus — and nothing written), saved (a draft on eBay) or published, plus marketplaceId, listingId, variationCount, failed (variations eBay refused, by sku — nothing is published while any) and removedSkus (articles that left the listing). Needs listing creation armed on the eBay connection, and is refused until the workspace owner switches on AI publishing. Idempotent. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| model* | string | The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations. |
| marketplaceId | string | eBay marketplace id (EBAY_IT, EBAY_DE…) for a FIRST save, when the connection sells on several. A saved listing keeps its marketplace; omit it then. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"model"
],
"properties": {
"model": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations."
},
"marketplaceId": {
"type": "string",
"maxLength": 32,
"minLength": 1,
"description": "eBay marketplace id (EBAY_IT, EBAY_DE…) for a FIRST save, when the connection sells on several. A saved listing keeps its marketplace; omit it then."
}
}
}Schedule a post to be published at a time, or cancel its schedule. Obriym itself publishes it to every ready channel of the post within about 15 minutes after that time — the AI client does not need to be running then. This is how regular publishing is set up: create several drafts, then schedule each. Needs the owner's "AI may publish to social channels" switch to schedule (see publishingEnabled in list_content_channels); cancelling (scheduledAt: null) does not. A post that is published or being published cannot be scheduled. Returns a warning when no channel of the post is ready yet. Echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The publication id returned by create_content_post or list_content_posts. |
| scheduledAt* | any | When to publish, as an ISO 8601 date-time WITH its time-zone offset, e.g. "2026-10-12T10:00:00+03:00". At least one minute and at most one year ahead; list_content_channels returns the workspace time zone. Obriym publishes it itself at that time — no AI client needs to be running. null cancels the schedule and returns the post to a draft. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"scheduledAt"
],
"properties": {
"id": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "The publication id returned by create_content_post or list_content_posts."
},
"scheduledAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
],
"description": "When to publish, as an ISO 8601 date-time WITH its time-zone offset, e.g. \"2026-10-12T10:00:00+03:00\". At least one minute and at most one year ahead; list_content_channels returns the workspace time zone. Obriym publishes it itself at that time — no AI client needs to be running. null cancels the schedule and returns the post to a draft."
}
}
}List and search this workspace's companies, filtered by industry/status/owner, sorted and paginated. Returns summary rows (id, name, industry, size, status, owner, contactCount) plus pagination { page, perPage, total }. Use get_company to fetch one company's full detail by id.
| Argument | Type | Description |
|---|---|---|
| q | string | Free-text search over the company name. Omit for no text filter. |
| page | integer | 1-based page number of results to return. Default 1. |
| status | string | Filter by relationship status. Omit for any. Allowed: prospect, active, inactive. |
| ownerId | string | Filter to companies owned by this workspace member's user id. |
| perPage | integer | Number of companies per page (1-100). Default 25. |
| sortDir | string | Sort direction by name. Default asc. |
| industry | string | Filter to companies in this industry. Omit for any industry. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"q": {
"type": "string",
"maxLength": 255,
"description": "Free-text search over the company name. Omit for no text filter."
},
"page": {
"type": "integer",
"default": 1,
"maximum": 9007199254740991,
"description": "1-based page number of results to return. Default 1.",
"exclusiveMinimum": 0
},
"status": {
"enum": [
"prospect",
"active",
"inactive"
],
"type": "string",
"description": "Filter by relationship status. Omit for any. Allowed: prospect, active, inactive."
},
"ownerId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "Filter to companies owned by this workspace member's user id."
},
"perPage": {
"type": "integer",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Number of companies per page (1-100). Default 25."
},
"sortDir": {
"enum": [
"asc",
"desc"
],
"type": "string",
"default": "asc",
"description": "Sort direction by name. Default asc."
},
"industry": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "Filter to companies in this industry. Omit for any industry."
}
},
"additionalProperties": false
}List and search this workspace's contacts, filtered by company/owner/tag, sorted and paginated. Returns summary rows (id, firstName, lastName, email, phone, jobTitle, company, owner, tags) plus pagination { page, perPage, total }. Use get_contact to fetch one contact's full detail by id.
| Argument | Type | Description |
|---|---|---|
| q | string | Free-text search over name, email and company. Omit for no text filter. |
| tag | string | Filter to contacts carrying this tag. Omit for any tag. |
| page | integer | 1-based page number of results to return. Default 1. |
| sortBy | string | Field to sort by. Default name. Allowed: name, email, createdAt. |
| ownerId | string | Filter to contacts owned by this workspace member's user id. |
| perPage | integer | Number of contacts per page (1-100). Default 25. |
| sortDir | string | Sort direction. Default asc. |
| companyId | string | Filter to contacts at this company id (from search_companies). |
List and search pipeline deals, filtered by stage/owner/company/contact/stale and paginated. Returns summary rows (id, title, stage, amount, probability, owner, company, contact, next-action, isStale) plus pagination { page, perPage, total }. Use get_deal to fetch one deal's full detail by id.
| Argument | Type | Description |
|---|---|---|
| q | string | Free-text search over the deal title. Omit for no text filter. |
| page | integer | 1-based page number of results to return. Default 1. |
| stale | string | Set "true" to return only stale deals (past their next-action date or long untouched). |
| ownerId | string | Filter to deals owned by this workspace member's user id. |
| perPage | integer | Number of deals per page (1-100). Default 25. |
| stageId | string | Filter to deals in this pipeline stage id (from list_pipeline_stages). |
| companyId | string | Filter to deals linked to this company id (from search_companies). |
| contactId | string | Filter to deals linked to this contact id (from search_contacts). |
List and search this workspace's leads, filtered by text/status/source/created-date/stale and paginated. Returns summary rows (id, name, contact, company, status, source, assignee, tags, next-action, isStale, timestamps) plus pagination { page, perPage, total }, newest first. Use get_lead to fetch notes, position and score for one lead by id.
| Argument | Type | Description |
|---|---|---|
| q | string | Free-text search over lead name, email, phone, or company. Omit for no text filter. |
| to | string | Only leads created at or before this ISO 8601 timestamp (e.g. 2026-02-28T23:59:59Z). |
| from | string | Only leads created at or after this ISO 8601 timestamp (e.g. 2026-01-31T00:00:00Z). |
| page | integer | 1-based page number of results to return. Default 1. |
| stale | any | Set true to return only stale leads: not unqualified/converted and either past their next-action date or untouched for more than 7 days. |
| source | string | Filter by lead source key (e.g. website, referral, telegram). Use list_lead_sources to see the workspace's keys. Omit for all sources. |
| status | string | Filter by lead status. Omit to return every status. Allowed: new, contacted, qualified, unqualified, converted. |
Find the category id a marketplace uses, to link it to a catalog category. Read-only. Pass the platform (prom, rozetka, olx, amazon or google_merchant) and a query, or for OLX and Rozetka a parentId to browse one level of the tree (no query and no parentId lists the top level). Sources differ: Google Merchant searches the bundled Google product taxonomy and needs no connection; OLX, Rozetka and Amazon ask the marketplace through the connected adapter (connected tells you whether one exists); Prom publishes no category directory, so only rubrics already seen on this merchant's own Prom listings are returned (partial tells you the list may be incomplete, note explains why). OLX only accepts a LEAF category: check isLeaf and keep browsing with parentId until you reach one. Results are candidates for the USER to choose from: when several fit, show them and ask, never pick one silently. Then pass the chosen id in marketplaceCategories of update_category or create_category.
| Argument | Type | Description |
|---|---|---|
| query | string | Words describing the shelf, e.g. the CRM category's name ('кросівки', 'running shoes'). At least two characters. |
| parentId | any | Browse one level of the marketplace tree under this id (OLX and Rozetka). Omit, together with query, to list the top level. |
| platform* | string | The marketplace whose categories to look up. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"platform"
],
"properties": {
"query": {
"type": "string",
"maxLength": 150,
"description": "Words describing the shelf, e.g. the CRM category's name ('кросівки', 'running shoes'). At least two characters."
},
"parentId": {
"anyOf": [
{
"type": "string",
"maxLength": 60,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Browse one level of the marketplace tree under this id (OLX and Rozetka). Omit, together with query, to list the top level."
},
"platform": {
"enum": [
"prom",
"rozetka",
"olx",
"amazon",
"google_merchant"
],
"type": "string",
"description": "The marketplace whose categories to look up."
}
}
}List and search active catalog products, filtered by category/brand/collection/model (productGroupId — the other colours and sizes of one model)/size/color/price/stock/tag/type, or by supplier and the supplier's last stock report (supplierId, supplierStock), sorted by name, price, newest or popularity (units sold in the last 90 days), and paginated. Returns each product's catalog fields — price and prices per currency, stock (null when the shop does not count it; see trackInventory), availability, variant fields (productGroupId, color, size, material and the rest), attributes (every characteristic), category, brand — plus its model, warehouse and supplier by name and supplierOffers (what the supplier last said: quantity, restock date, purchase price, state), and pagination { page, perPage, total }. Use get_product to fetch one product's full detail by id or SKU.
| Argument | Type | Description |
|---|---|---|
| q | string | Free-text search over product name and SKU. Empty for no text filter. |
| tag | string | Filter to products carrying this tag. Empty means any tag. |
| page | integer | 1-based page number of results to return. Default 1. |
| size | string | Filter to products whose size equals this value, ignoring letter case (the product's own size field). Empty means any size. |
| sort | string | Sort order. Empty sorts by name. Allowed: name_asc, name_desc, price_asc, price_desc, newest, popular — popular ranks by units sold in confirmed, processing, shipped or delivered orders over the last 90 days. Ties break by name. |
Re-bind this OAuth connection to the workspace selected by the user. Takes effect on the next tool call. Use the organizationId returned by list_workspaces or by WORKSPACE_SELECTION_REQUIRED; never invent or guess it.
| Argument | Type | Description |
|---|---|---|
| organizationId* | string | The workspace organizationId chosen by the user from list_workspaces or WORKSPACE_SELECTION_REQUIRED. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"organizationId"
],
"properties": {
"organizationId": {
"type": "string",
"minLength": 1,
"description": "The workspace organizationId chosen by the user from list_workspaces or WORKSPACE_SELECTION_REQUIRED."
}
}
}Set or remove the picture (logo) of ONE brand. Pass a public https image link in url (JPEG, PNG or WebP, at most 2 MB; a bigger file is refused, there is no resize) — Obriym stores its own copy and the previous picture is deleted only after the new one is in place. Pass url: null to remove the current picture. Idempotent in effect: repeating it leaves the same picture. Use list_brands to find the brand id. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| url* | any | A public https image link (JPEG, PNG or WebP, at most 2 MB) to use as the brand picture, or null to remove the current picture. |
| brandId* | string | The brand id from list_brands. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"brandId",
"url"
],
"properties": {
"url": {
"anyOf": [
{
"type": "string",
"format": "uri",
"description": "A public https image link (JPEG, PNG or WebP, at most 2 MB). Obriym downloads it and stores its own copy in the workspace, so the link may be temporary."
},
{
"type": "null"
}
],
"description": "A public https image link (JPEG, PNG or WebP, at most 2 MB) to use as the brand picture, or null to remove the current picture."
},
"brandId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The brand id from list_brands."
}
}
}Set or remove the picture of ONE category. Pass a public https image link in url (JPEG, PNG or WebP, at most 2 MB; a bigger file is refused, there is no resize) — Obriym stores its own copy and the previous picture is deleted only after the new one is in place. Pass url: null to remove the current picture. Idempotent in effect: repeating it leaves the same picture. Use list_categories to find the category id. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| url* | any | A public https image link (JPEG, PNG or WebP, at most 2 MB) to use as the category picture, or null to remove the current picture. |
| categoryId* | string | The category id from list_categories. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"categoryId",
"url"
],
"properties": {
"url": {
"anyOf": [
{
"type": "string",
"format": "uri",
"description": "A public https image link (JPEG, PNG or WebP, at most 2 MB). Obriym downloads it and stores its own copy in the workspace, so the link may be temporary."
},
{
"type": "null"
}
],
"description": "A public https image link (JPEG, PNG or WebP, at most 2 MB) to use as the category picture, or null to remove the current picture."
},
"categoryId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The category id from list_categories."
}
}
}Mark or unmark up to 100 products for one connected sales channel (prom, rozetka, ebay, olx, …). It changes what the CRM intends to send: on Prom and Rozetka the next feed pull adds or drops the product; on eBay it only makes the product a channel member — a listing exists only after create_ebay_drafts and publish_ebay_drafts. It never arms a sync. Adding picks up active products only. Returns { affected, skipped } — skipped were already in that state. Refused until the workspace owner switches on AI publishing. Idempotent. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| listed* | boolean | true marks the products for this channel; false unmarks them. This only changes what the CRM intends to send — it never arms a sync and never creates a listing by itself. Unmarking a product on Prom drops it from the next feed pull. |
| platform* | string | The connected sales channel to change membership on (e.g. prom, rozetka, ebay, olx). |
| productIds* | array | The exact products to change, at most 100 ids fetched with search_products. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"listed",
"platform",
"productIds"
],
"properties": {
"listed": {
"type": "boolean",
"description": "true marks the products for this channel; false unmarks them. This only changes what the CRM intends to send — it never arms a sync and never creates a listing by itself. Unmarking a product on Prom drops it from the next feed pull."
},
"platform": {
"enum": [
"prom",
"rozetka",
"woocommerce",
"shopify",
"olx",
"amazon",
"ebay",
"google_merchant"
],
"type": "string",
"description": "The connected sales channel to change membership on (e.g. prom, rozetka, ebay, olx)."
},
"productIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
},
"maxItems": 100,
"minItems": 1,
"description": "The exact products to change, at most 100 ids fetched with search_products."
}
}
}Set the eBay connection's default shipping (fulfillment) policy for one eBay site, or null to remove it. Products without their own choice carry it in every new draft and when a draft goes live; LIVE listings keep the policy they have — change those with bulk_set_ebay_fulfillment_policy. The policy is checked against eBay's live list first; with no default, listings use the first policy eBay returns. Returns marketplaceId, previousFulfillmentPolicyId, fulfillmentPolicyId and the policy. Refused until the workspace owner switches on AI publishing. Idempotent. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| marketplaceId | string | An eBay MARKETPLACE id such as EBAY_IT. Omit it when the eBay connection sells on one site. |
| fulfillmentPolicyId* | any | A fulfillmentPolicyId from list_ebay_fulfillment_policies, for the same marketplace. null removes the default: listings without their own choice then use the first policy eBay returns. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"fulfillmentPolicyId"
],
"properties": {
"marketplaceId": {
"enum": [
"EBAY_US",
"EBAY_GB",
"EBAY_DE",
"EBAY_AT",
"EBAY_BE",
"EBAY_FR",
"EBAY_IT",
"EBAY_NL",
"EBAY_ES",
"EBAY_IE",
"EBAY_PL",
"EBAY_CH",
"EBAY_CA",
"EBAY_AU"
],
"type": "string",
"description": "An eBay MARKETPLACE id such as EBAY_IT. Omit it when the eBay connection sells on one site."
},
"fulfillmentPolicyId": {
"anyOf": [
{
"type": "string",
"pattern": "^[A-Za-z0-9_-]+$",
"maxLength": 64,
"minLength": 1
},
{
"type": "null"
}
],
"description": "A fulfillmentPolicyId from list_ebay_fulfillment_policies, for the same marketplace. null removes the default: listings without their own choice then use the first policy eBay returns."
}
}
}Create or update a workspace lead source: set its label and active state by key (built-in or custom, lowercase_with_underscores). Idempotent — re-sending the same key updates it. Archiving the fallback 'other' source is not allowed. Use list_lead_sources to see current sources. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| key* | string | Stable source key, lowercase_with_underscores (built-in or custom). |
| label* | string | Human-readable label shown for this source in the UI. |
| isActive* | boolean | Whether the source is selectable for new leads. Set false to archive it (the fallback 'other' source cannot be archived). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"isActive",
"key",
"label"
],
"properties": {
"key": {
"type": "string",
"pattern": "^[a-z0-9]+(?:_[a-z0-9]+)*$",
"maxLength": 80,
"minLength": 1,
"description": "Stable source key, lowercase_with_underscores (built-in or custom)."
},
"label": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "Human-readable label shown for this source in the UI."
},
"isActive": {
"type": "boolean",
"description": "Whether the source is selectable for new leads. Set false to archive it (the fallback 'other' source cannot be archived)."
}
}
}Set — or clear — the price ONE sales channel gets for ONE product, instead of the product's ordinary price in that currency. Send price as a decimal string to set it (with an optional compareAtPrice, the old price, higher than price) or price null to remove the override so the channel gets the ordinary price again. Per platform and currency: Prom, Rozetka, eBay, Amazon, Shopify, WooCommerce, OLX or Google Merchant. Send only an amount the person stated. The new price reaches the channel the same way a price edit does — only where the owner armed price writes. This is not the price-list row for a currency (upsert_product_prices). Idempotent; clearing a missing override is not an error. Returns { changed }. Read get_product_pricing first. Echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The product id returned by search_products or get_product — never a SKU or a name. |
| price* | any | The price this ONE channel gets, instead of the product's ordinary price in that currency, as a decimal string above zero. null removes the override — the channel then gets the ordinary price again. Send only an amount the person stated; never a converted or guessed value. |
| currency* | string | The currency the channel sells in (uppercase 3-letter ISO code). get_product_pricing and the channel's readiness show which currency a channel uses. |
| platform* | string | The sales channel this price is for: prom, rozetka, woocommerce, shopify, olx, amazon, ebay or google_merchant. |
Choose the eBay shipping (fulfillment) policy of ONE product, or with fulfillmentPolicyId null return it to the connection default. A product with no eBay listing stores the choice for its next draft. A draft or LIVE listing has its eBay offer updated in place — no relisting — when listing writes are armed on the eBay connection, and the offer is then read back to confirm; with listing writes off a live listing is refused and a draft stores the choice for go-live. Per-service shipping cost overrides tied to the old policy are removed (droppedShippingCostOverrides). Returns productId, sku, offerId, marketplaceId, previousFulfillmentPolicyId, newFulfillmentPolicyId, status (updated, unchanged, saved, unverified, failed), verified and error — tell the user a listing changed only when status is updated. Refused until the workspace owner switches on AI publishing. Idempotent. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| productId* | string | A product id returned by search_products. |
| marketplaceId | string | An eBay MARKETPLACE id such as EBAY_IT — never the eBay connection id. Omit it when the eBay connection sells on one site; the server uses that one. Required when the connection sells on several, unless the product already has an eBay offer (its own site is then used). |
| fulfillmentPolicyId* | any | A fulfillmentPolicyId from list_ebay_fulfillment_policies, for the same marketplace. null removes the product's own choice so the connection default (then eBay's first policy) applies. |
Replace ONE product's wholesale quantity breaks in ONE currency — 'from 12 units, 12.40 each'. The list you send becomes the whole set for that currency (at most 10; each quantity at least 2 and once; a bigger quantity must cost less per unit); an empty list removes all its breaks. The product must already be priced in that currency. Breaks apply to buyers outside the team (the customer portal and connected partners), never to the website or marketplaces, and the buyer gets the better of a break or their own discount. Idempotent. Returns { count }. Read get_product_pricing first. Echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The product id returned by search_products or get_product — never a SKU or a name. |
| tiers* | array | The wholesale breaks for that currency, at most 10. This list REPLACES the product's breaks in that currency; an empty list removes them all. Each quantity once, and a bigger quantity always costs less per unit. |
| currency* | string | The currency of these breaks (uppercase 3-letter ISO code). The product must already be priced in it — its own currency or a price-list row. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"currency",
"id",
"tiers"
],
"properties": {
"id": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The product id returned by search_products or get_product — never a SKU or a name."
},
"tiers": {
"type": "array",
"items": {
"type": "object",
"required": [
"minQuantity",
"price"
],
"properties": {
"price": {
"type": "string",
"pattern": "^\\d+(\\.\\d{1,2})?$",
"description": "The price PER UNIT from that quantity, as a decimal string. Must be lower than the price of every smaller break."
},
"minQuantity": {
"type": "integer",
"maximum": 1000000,
"minimum": 2,
"description": "From this many units. At least 2 — the price for one unit is the product's own price."
}
}
},
"maxItems": 10,
"description": "The wholesale breaks for that currency, at most 10. This list REPLACES the product's breaks in that currency; an empty list removes them all. Each quantity once, and a bigger quantity always costs less per unit."
},
"currency": {
"type": "string",
"pattern": "^[A-Z]{3}$",
"description": "The currency of these breaks (uppercase 3-letter ISO code). The product must already be priced in it — its own currency or a price-list row."
}
}
}Re-read the eBay shipping (fulfillment) policies from eBay for every site the connection sells on, or one marketplaceId, and refresh the copy the CRM keeps — after the seller created, renamed or deleted a policy in Seller Hub. Returns the same shape as list_ebay_fulfillment_policies; check staleAssignments: products whose chosen policy eBay no longer has will be refused at their next draft or go-live until another policy is chosen. Changes no listing and no choice. Use list_ebay_fulfillment_policies for an ordinary read.
| Argument | Type | Description |
|---|---|---|
| marketplaceId | string | An eBay MARKETPLACE id such as EBAY_IT. Omit it to refresh every marketplace the eBay connection sells on. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"marketplaceId": {
"enum": [
"EBAY_US",
"EBAY_GB",
"EBAY_DE",
"EBAY_AT",
"EBAY_BE",
"EBAY_FR",
"EBAY_IT",
"EBAY_NL",
"EBAY_ES",
"EBAY_IE",
"EBAY_PL",
"EBAY_CH",
"EBAY_CA",
"EBAY_AU"
],
"type": "string",
"description": "An eBay MARKETPLACE id such as EBAY_IT. Omit it to refresh every marketplace the eBay connection sells on."
}
}
}Move a deal to a pipeline stage by its id. Closed-lost stages require a lostReason. Use search_deals for the deal id and list_pipeline_stages for the target stageId. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The deal id returned by search_deals. |
| stageId* | string | The target pipeline stage id to move the deal to (from list_pipeline_stages). |
| lostReason | any | Reason the deal was lost. Required when the target stage is a Closed-lost stage; otherwise omit. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"stageId",
"id"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The deal id returned by search_deals."
},
"stageId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The target pipeline stage id to move the deal to (from list_pipeline_stages)."
},
"lostReason": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"description": "Reason the deal was lost. Required when the target stage is a Closed-lost stage; otherwise omit."
}
},
"additionalProperties": false
}Update fields on an existing catalog brand by id: name, slug, description, website and description translations. Provide a patch with at least one field; use list_brands first to find the id and current values. Renaming a brand changes the vendor name sent to marketplaces, so rename only on the user's explicit request; the name is never translated. Translations REPLACE the whole set when sent (an empty array removes them all) and are left untouched when omitted — translate only the brand's own description, add no facts. The result is the updated brand and echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The brand id returned by list_brands. |
| patch* | object | The brand fields to update; include at least one changed field. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"patch"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The brand id returned by list_brands."
},
"patch": {
"type": "object",
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The brand name exactly as marketplaces know the vendor, up to 120 characters; unique in the workspace. Never translated."
},
"slug": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
],
"description": "URL segment for the brand. Normalized to lowercase Latin letters, digits and hyphens whatever is sent; derived from the name when omitted."
},
"website": {
"anyOf": [
{
"type": "string",
"format": "uri",
"maxLength": 255
},
{
"type": "null"
}
],
"description": "The brand's website as a full https:// URL. Send null to clear it."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 4000
},
{
"type": "null"
}
],
"description": "Brand description in the workspace's base language (up to 4000 characters). Send null to clear it."
},
"translations": {
"type": "array",
"items": {
"type": "object",
"required": [
"description",
"locale"
],
"properties": {
"locale": {
"enum": [
"uk",
"ru",
"en",
"pl",
"de",
"it",
"fr",
"es",
"pt",
"nl",
"cs",
"sk",
"hu",
"ro",
"bg",
"lt",
"lv",
"et",
"tr"
],
"type": "string",
"example": "en",
"description": "Content locale, one of the workspace's supported languages."
},
"description": {
"type": "string",
"maxLength": 4000
}
},
"additionalProperties": false
},
"maxItems": 19,
"description": "Brand description per locale (the brand NAME is never translated). Omit to leave existing translations untouched; when sent it REPLACES the whole set, so an empty array removes them all."
}
},
"description": "The brand fields to update; include at least one changed field.",
"additionalProperties": false
}
}
}Update fields on an existing catalog category by id: name, parent, slug, description, Google category, marketplaceCategories and translations. Provide a patch with at least one field; use list_categories first to find the id and current values. The slug is normalized to Latin. The parent must exist in this workspace and cannot create a loop. Translations REPLACE the whole set when sent (an empty array removes them all) and are left untouched when omitted — translate only the category's own name and description, add no facts. marketplaceCategories ({ prom, rozetka, olx, amazon, google_merchant }) links marketplace category ids: a string sets one, null clears it, an omitted platform is left untouched. Look ids up with search_marketplace_categories first and never guess them; the format is always checked on write, and against the marketplace while it is connected (OLX must be a leaf category; a Google id must exist in the Google taxonomy). The result is the updated category and echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The category id returned by list_categories. |
| patch* | object | The category fields to update; include at least one changed field. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"patch"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The category id returned by list_categories."
},
"patch": {
"type": "object",
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The category name in the workspace's base language, up to 120 characters. Must be unique among categories with the same parent."
},
"slug": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
],
"description": "URL segment for the category. Normalized to lowercase Latin letters, digits and hyphens whatever is sent (Cyrillic is transliterated); derived from the name when omitted."
},
"parentId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Id of the parent category from list_categories, to nest this one under it; it must exist in this workspace. Omit or send null for a top-level category."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 4000
},
{
"type": "null"
}
],
"description": "Prose a storefront shows at the top of the category shelf, in the workspace's base language (up to 4000 characters). Send null to clear it."
},
"translations": {
"type": "array",
"items": {
"type": "object",
"required": [
"locale",
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120
},
"locale": {
"enum": [
"uk",
"ru",
"en",
"pl",
"de",
"it",
"fr",
"es",
"pt",
"nl",
"cs",
"sk",
"hu",
"ro",
"bg",
"lt",
"lv",
"et",
"tr"
],
"type": "string",
"example": "en",
"description": "Content locale, one of the workspace's supported languages."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 4000
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"maxItems": 19,
"description": "Category name (and optional description) per locale. Omit to leave existing translations untouched; when sent it REPLACES the whole set, so an empty array removes them all."
},
"googleProductCategory": {
"anyOf": [
{
"type": "string",
"maxLength": 255,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Google Product Taxonomy id or full path for this category (for Google Shopping). Prefer marketplaceCategories.google_merchant, which this field is an alias of; send the Google category in one place only. Separate from the name; send null to clear it."
},
"marketplaceCategories": {
"type": "object",
"properties": {
"olx": {
"anyOf": [
{
"type": "string",
"maxLength": 10,
"minLength": 1
},
{
"type": "null"
}
],
"description": "OLX category id (digits) that products of this category publish into. Must be a FINAL (leaf) OLX category — OLX refuses an advert in a parent. While OLX is connected it is checked against OLX and its path is stored for display. Take it from search_marketplace_categories, never guess. Not inherited by subcategories. Send null to clear it."
},
"prom": {
"anyOf": [
{
"type": "string",
"maxLength": 40,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Prom.ua rubric id (digits) — exported as <portal_category_id>; Prom refuses an offer without it. Prom publishes no category directory: take the id from search_marketplace_categories (rubrics observed on the merchant's own Prom listings) or from the user, never guess. Not inherited by subcategories. Send null to clear it."
},
"amazon": {
"anyOf": [
{
"type": "string",
"maxLength": 60,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Amazon product type (e.g. SHOES, HOME_BED_AND_BATH) — the schema Amazon validates every listing of this category against; no Amazon listing can be created without it. Upper-cased on write. While Amazon is connected it is checked against Amazon. Take it from search_marketplace_categories, never guess. Not inherited by subcategories. Send null to clear it."
},
"rozetka": {
"anyOf": [
{
"type": "string",
"maxLength": 40,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Rozetka category id (digits) — exported as rz_id, which links this category to Rozetka's tree. Take it from search_marketplace_categories, never guess. Not inherited by subcategories. Send null to clear it."
},
"google_merchant": {
"anyOf": [
{
"type": "string",
"maxLength": 255,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Google Product Taxonomy entry for Google Shopping — the numeric id (e.g. 187). An exact English taxonomy path is accepted and stored as its id. Take it from search_marketplace_categories, never guess. Subcategories without their own value inherit the nearest parent's. Send null to clear it."
}
},
"description": "The category's id on each marketplace, keyed by platform. Omit a platform to leave it untouched, send null to clear it. Every value is checked on write (format always; against the marketplace itself while it is connected) — find valid ids with search_marketplace_categories first.",
"additionalProperties": false
}
},
"description": "The category fields to update; include at least one changed field.",
"additionalProperties": false
}
}
}Update fields on a company by id. Provide a patch with at least one field. representationState is explicit and never inferred from contacts. primaryContactId can select an existing contact already linked to this same non-individual company; send null to clear it. Use search_companies first to find the company id. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The company id returned by search_companies. |
| patch* | object | The company fields to update; include at least one changed field. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"patch"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The company id returned by search_companies."
},
"patch": {
"type": "object",
"properties": {
"iban": {
"anyOf": [
{
"type": "string",
"maxLength": 34
},
{
"type": "null"
}
],
"description": "The counterparty's IBAN. Optional."
},
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "The company name (unique within the workspace)."
},
"size": {
"enum": [
"solo",
"small",
"medium",
"large",
"enterprise"
],
"type": "string",
"description": "Company size band. Optional. One of: solo, small, medium, large, enterprise."
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tags for segmentation. Optional."
},
"email": {
"anyOf": [
{
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 255,
"description": "The company email."
},
{
"type": "null"
}
],
"description": "The company email. Optional."
},
"phone": {
"anyOf": [
{
"type": "string",
"maxLength": 50,
"description": "The company phone."
},
{
"type": "null"
}
],
"description": "The company phone. Optional."
},
"edrpou": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d{8}(\\d{2})?$",
"maxLength": 20,
"description": "Tax id: 8-digit ЄДРПОУ or 10-digit ІПН."
},
{
"type": "null"
}
],
"description": "Tax identifier: 8-digit EDRPOU or 10-digit taxpayer number. Optional."
},
"status": {
"enum": [
"prospect",
"active",
"inactive"
],
"type": "string",
"description": "Relationship status. Optional. One of: prospect, active, inactive."
},
"ownerId": {
"anyOf": [
{
"type": "string",
"description": "User id of the workspace member who owns this company."
},
{
"type": "null"
}
],
"description": "User id of the workspace member who owns this company. Optional."
},
"website": {
"anyOf": [
{
"type": "string",
"format": "uri",
"maxLength": 255,
"description": "The company website URL."
},
{
"type": "null"
}
],
"description": "The company website URL. Optional."
},
"bankName": {
"anyOf": [
{
"type": "string",
"maxLength": 160
},
{
"type": "null"
}
],
"description": "The counterparty's bank name. Optional."
},
"industry": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"description": "The company's industry."
},
{
"type": "null"
}
],
"description": "The company's industry. Optional."
},
"taxGroup": {
"anyOf": [
{
"enum": [
"group_1",
"group_2",
"group_3"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "Single-tax group. Only meaningful for a sole trader on the simplified system."
},
"vatPayer": {
"type": "boolean",
"description": "Whether the counterparty is a VAT payer. Optional."
},
"taxSystem": {
"anyOf": [
{
"enum": [
"simplified",
"general"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "Tax system: simplified or general. Optional."
},
"vatNumber": {
"anyOf": [
{
"type": "string",
"maxLength": 20
},
{
"type": "null"
}
],
"description": "VAT payer identifier. Optional."
},
"creditLimit": {
"anyOf": [
{
"type": "string",
"pattern": "^(?:0|[1-9]\\d{0,11})(?:\\.\\d{1,2})?$",
"description": "Non-negative credit limit up to 999999999999.99."
},
{
"type": "null"
}
],
"description": "Maximum outstanding balance. Optional; requires creditLimitCurrency."
},
"legalAddress": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"description": "Legal address. Optional."
},
"deliveryAddress": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"description": "Delivery address. Optional."
},
"counterpartyType": {
"enum": [
"company",
"sole_trader",
"individual"
],
"type": "string",
"description": "Counterparty type: company, sole_trader, or individual. Defaults to company."
},
"paymentTermsDays": {
"anyOf": [
{
"type": "integer",
"maximum": 365,
"minimum": 0,
"description": "Payment terms in whole days from 0 to 365."
},
{
"type": "null"
}
],
"description": "Agreed payment term in days (0-365). Optional."
},
"primaryContactId": {
"anyOf": [
{
"type": "string",
"minLength": 1
},
{
"type": "null"
}
],
"description": "CRM contact id to designate as this counterparty's primary contact. Must already belong to this company; null clears it."
},
"creditLimitCurrency": {
"anyOf": [
{
"type": "string",
"pattern": "^[A-Z]{3}$",
"maxLength": 3,
"description": "Uppercase 3-letter ISO currency for the credit limit."
},
{
"type": "null"
}
],
"description": "ISO currency for creditLimit. Required when creditLimit is set."
},
"representationState": {
"enum": [
"unspecified",
"works_alone",
"has_representatives"
],
"type": "string",
"description": "Declared representation state: unspecified, works_alone, or has_representatives. Never inferred from contact count."
}
},
"description": "The company fields to update; include at least one changed field.",
"additionalProperties": false
}
}
}Update fields on a contact by id. Provide a patch with at least one field. Use search_contacts first to find the contact id. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The contact id returned by search_contacts. |
| patch* | object | The contact fields to update; include at least one changed field. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"patch"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The contact id returned by search_contacts."
},
"patch": {
"type": "object",
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80
},
"description": "Tags for segmentation. Optional."
},
"email": {
"anyOf": [
{
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 255,
"description": "The contact's email address."
},
{
"type": "null"
}
],
"description": "The contact's email address. Optional."
},
"phone": {
"anyOf": [
{
"type": "string",
"maxLength": 50,
"description": "The contact's phone number."
},
{
"type": "null"
}
],
"description": "The contact's phone number. Optional."
},
"ownerId": {
"anyOf": [
{
"type": "string",
"description": "User id of the workspace member who owns this contact."
},
{
"type": "null"
}
],
"description": "User id of the workspace member who owns this contact. Optional."
},
"jobTitle": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"description": "The contact's job title."
},
{
"type": "null"
}
],
"description": "The contact's job title. Optional."
},
"lastName": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"description": "The contact's last name."
},
{
"type": "null"
}
],
"description": "The contact's last name. Optional."
},
"companyId": {
"anyOf": [
{
"type": "string",
"description": "Company id to link this contact to (from search_companies)."
},
{
"type": "null"
}
],
"description": "Company id to link this contact to (from search_companies). Optional."
},
"firstName": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The contact's first name."
},
"documentRole": {
"anyOf": [
{
"enum": [
"signatory",
"accountant",
"manager",
"other"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "The contact's role on sales documents. Optional."
}
},
"description": "The contact fields to update; include at least one changed field.",
"additionalProperties": false
}
}
}Change a draft or scheduled post: working title, main text, hashtags, format, or its channels and their own texts (sending channels replaces the whole set). Fields you omit stay as they are; images cannot be changed here. Refused for a published post — a post already live on a network cannot be changed from Obriym; create a new one instead. Refused while the post is being published. Repeating the same call changes nothing further. Echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The publication id returned by create_content_post or list_content_posts. |
| text | string | Replaces the main text. |
| title | string | An internal working title shown in Obriym's Publications list, e.g. "Monday — new arrivals". Never published. |
| format | string | post = a regular feed post; story = an Instagram/Facebook story, which needs an image. Defaults to post. |
| channels | array | Replaces the post's channels and their texts. Omit to keep them as they are. |
| hashtags | array | Replaces the hashtags, without the "#" sign. Omit to keep them; [] removes them. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"maxLength": 64,
"minLength": 1,
"description": "The publication id returned by create_content_post or list_content_posts."
},
"text": {
"type": "string",
"maxLength": 10000,
"description": "Replaces the main text."
},
"title": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "An internal working title shown in Obriym's Publications list, e.g. \"Monday — new arrivals\". Never published."
},
"format": {
"enum": [
"post",
"story"
],
"type": "string",
"description": "post = a regular feed post; story = an Instagram/Facebook story, which needs an image. Defaults to post."
},
"channels": {
"type": "array",
"items": {
"type": "object",
"required": [
"channel"
],
"properties": {
"text": {
"type": "string",
"maxLength": 63206,
"description": "Text written for THIS network only. Omit it to publish the post's main text. It must fit the channel's maxTextLength from list_content_channels together with the hashtags (Threads allows 500 characters, Instagram 2200)."
},
"channel": {
"enum": [
"instagram",
"facebook",
"telegram",
"linkedin",
"threads",
"viber"
],
"type": "string",
"description": "A social channel: telegram (the bound Telegram channel), instagram, facebook (the Facebook page), linkedin, threads or viber (the connected Viber channel). Use only channels list_content_channels reports as ready."
}
}
},
"maxItems": 6,
"minItems": 1,
"description": "Replaces the post's channels and their texts. Omit to keep them as they are."
},
"hashtags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"maxItems": 30,
"description": "Replaces the hashtags, without the \"#\" sign. Omit to keep them; [] removes them."
}
}
}Update fields on an existing lead by id. Provide a patch with at least one field. Use search_leads first to find the lead id. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The lead id returned by search_leads. |
| patch* | object | The lead fields to update; include at least one changed field. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"patch"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The lead id returned by search_leads."
},
"patch": {
"type": "object",
"properties": {
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "The lead's full name or label."
},
"tags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"maxItems": 30,
"description": "Tags for segmentation (replaces the existing set; max 30)."
},
"email": {
"anyOf": [
{
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
},
{
"type": "null"
}
],
"description": "The lead's email; null to clear."
},
"notes": {
"anyOf": [
{
"type": "string",
"maxLength": 5000
},
{
"type": "null"
}
],
"description": "Free-text notes; null to clear."
},
"phone": {
"anyOf": [
{
"type": "string",
"maxLength": 50,
"minLength": 1
},
{
"type": "null"
}
],
"description": "The lead's phone number; null to clear."
},
"score": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Lead quality score, 0-100."
},
"source": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "Lead source key (see list_lead_sources)."
},
"status": {
"enum": [
"new",
"contacted",
"qualified",
"unqualified"
],
"type": "string",
"description": "Lead status: new, contacted, qualified, unqualified, or converted."
},
"position": {
"anyOf": [
{
"type": "string",
"maxLength": 255,
"minLength": 1
},
{
"type": "null"
}
],
"description": "The lead's job title/position; null to clear."
},
"assignedTo": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "User id of the workspace member to own the lead; null to unassign."
},
"companyName": {
"anyOf": [
{
"type": "string",
"maxLength": 255,
"minLength": 1
},
{
"type": "null"
}
],
"description": "The lead's company name; null to clear."
},
"nextActionDate": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
],
"description": "ISO 8601 timestamp of the next action; null to clear."
},
"nextActionNote": {
"anyOf": [
{
"type": "string",
"maxLength": 500,
"minLength": 1
},
{
"type": "null"
}
],
"description": "What the next action is; null to clear."
}
},
"description": "The lead fields to update; include at least one changed field.",
"additionalProperties": false
}
}
}Update a line item on an order (quantity, unit price, discount, name, or SKU). Recomputes the order total. Only allowed while the order is pending or confirmed; otherwise it fails with 409 CONFLICT "Order lines can only be changed while the order is pending or confirmed" (stock is committed from processing on). Use get_order to find the order's externalId and the item's itemId. The CRM recalculates shipping eligibility from the saved priced lines; a separate whole-order discount may require source-confirmed amount correction. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| patch* | object | The order item fields to update; include at least one changed field. |
| itemId* | string | The order item id returned by get_order. |
| externalId* | string | The order externalId returned by list_orders or create_order. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"externalId",
"itemId",
"patch"
],
"properties": {
"patch": {
"type": "object",
"properties": {
"sku": {
"type": "string",
"maxLength": 120,
"description": "Product SKU snapshot (from search_products). Optional."
},
"discount": {
"type": "number",
"maximum": 100,
"minimum": 0,
"description": "Percentage discount on this line (0-100). Default 0."
},
"quantity": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Quantity ordered (integer, at least 1).",
"exclusiveMinimum": 0
},
"unitPrice": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d+(\\.\\d{1,2})?$"
},
{
"type": "number",
"minimum": 0
}
],
"description": "Price per unit in the order currency, as a decimal (e.g. 199.99). Snapshotted onto the line."
},
"productName": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "Line item name, snapshotted onto the order. Use search_products to quote a real catalog product's name. Required."
}
},
"description": "The order item fields to update; include at least one changed field.",
"additionalProperties": false
},
"itemId": {
"type": "string",
"minLength": 1,
"description": "The order item id returned by get_order."
},
"externalId": {
"type": "string",
"minLength": 1,
"description": "The order externalId returned by list_orders or create_order."
}
}
}Move an order to a new status by externalId. Only valid transitions from the current status are allowed. Use list_orders to find the externalId and get_order to see the current status. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| status* | string | The new order status. Only valid transitions from the current status are accepted. Allowed values: pending, confirmed, processing, shipped, delivered, cancelled, refunded. |
| externalId* | string | The order externalId returned by list_orders or create_order. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"status",
"externalId"
],
"properties": {
"status": {
"enum": [
"pending",
"confirmed",
"processing",
"shipped",
"delivered",
"cancelled",
"refunded"
],
"type": "string",
"description": "The new order status. Only valid transitions from the current status are accepted. Allowed values: pending, confirmed, processing, shipped, delivered, cancelled, refunded."
},
"externalId": {
"type": "string",
"minLength": 1,
"description": "The order externalId returned by list_orders or create_order."
}
}
}Update fields on an existing catalog product by id — including status, to publish a draft or archive a product. Provide a patch with at least one field; use get_product first to see the current values. A changed stock number is applied as a relative movement and recorded in the product stock history; prefer adjust_stock when the intent is a correction with a reason. A bundle's stock is derived from its components, so a stock sent for a bundle is refused; sending bundleItems replaces its composition. A product's type (simple or bundle) cannot change after creation — create a new product instead — and a product that is a component of a bundle that is not archived cannot be archived. A change to price, stock, tracking or status is pushed to every connected sales channel. For a product that belongs to a model, a changed shared field (name, description, category, brand, unit, keywords, videos, material, pattern, gender, age group, size type, condition) is applied to the whole model and every article of it; productGroupId null detaches the product from its model, and the code of another model moves it there. The result echoes the operating workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The product id returned by search_products. |
| patch* | object | The product fields to update; include at least one changed field. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"patch"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The product id returned by search_products."
},
"patch": {
"type": "object",
"properties": {
"ean": {
"anyOf": [
{
"type": "string",
"pattern": "^[0-9]{8,14}$"
},
{
"type": "null"
}
],
"example": "4006381333931",
"description": "GTIN/EAN-8/12/13/14 barcode. Presence-and-shape validation only, no checksum."
},
"mpn": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
],
"example": "TR-1",
"description": "Manufacturer part number — the maker's own code for the item, not the shop SKU. eBay requires it beside the brand in many categories."
},
"sku": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
]
},
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"size": {
"anyOf": [
{
"type": "string",
"maxLength": 60,
"minLength": 1
},
{
"type": "null"
}
]
},
"tags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"minLength": 1
}
},
"type": {
"enum": [
"simple",
"bundle"
],
"type": "string",
"description": "simple, or bundle — one sellable item made of bundleItems, holding no stock of its own. Fixed at creation: an update that changes it is refused."
},
"unit": {
"anyOf": [
{
"type": "string",
"maxLength": 40,
"minLength": 1
},
{
"type": "null"
}
]
},
"color": {
"anyOf": [
{
"type": "string",
"maxLength": 80,
"minLength": 1
},
{
"type": "null"
}
]
},
"depth": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"price": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"stock": {
"anyOf": [
{
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
{
"type": "null"
}
],
"description": "Units on hand, for a product that tracks inventory; a change on update is recorded as a relative movement in the stock history. Refused for a bundle — its stock is derived from its components."
},
"width": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"gender": {
"anyOf": [
{
"enum": [
"male",
"female",
"unisex"
],
"type": "string"
},
{
"type": "null"
}
]
},
"height": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"url"
],
"properties": {
"alt": {
"type": "string",
"example": "White leather sneakers, side view",
"maxLength": 200,
"description": "Alternative text of the photo, up to 200 characters. Optional: when empty a storefront should use the product name."
},
"url": {
"type": "string",
"format": "uri"
},
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"size": {
"type": "integer",
"maximum": 9007199254740991,
"exclusiveMinimum": 0
},
"pathname": {
"type": "string",
"minLength": 1
},
"uploadedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
},
"contentType": {
"enum": [
"image/jpeg",
"image/png",
"image/webp"
],
"type": "string"
}
},
"additionalProperties": false
},
"maxItems": 10,
"description": "The product's photos as { url, alt }, at most 10; the first is the main photo. On an update the list you send replaces the whole set. An entry whose url equals a photo the product already has keeps that stored file and takes only the caption (alt) you send, so sending back what you read never downgrades a stored photo."
},
"status": {
"enum": [
"draft",
"active",
"archived"
],
"type": "string"
},
"videos": {
"type": "array",
"items": {
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"format": "uri"
}
}
},
"example": [
{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
],
"maxItems": 5,
"description": "Video links for the product page (YouTube, Vimeo or a direct file), https only, at most 5. Links, not uploads. On update, sending the field replaces the whole list."
},
"weight": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"brandId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
]
},
"pattern": {
"anyOf": [
{
"type": "string",
"maxLength": 80,
"minLength": 1
},
{
"type": "null"
}
]
},
"ageGroup": {
"anyOf": [
{
"enum": [
"newborn",
"infant",
"toddler",
"kids",
"adult"
],
"type": "string"
},
{
"type": "null"
}
]
},
"material": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
]
},
"sizeType": {
"anyOf": [
{
"type": "string",
"maxLength": 40,
"minLength": 1
},
{
"type": "null"
}
]
},
"condition": {
"anyOf": [
{
"enum": [
"new",
"used",
"refurbished"
],
"type": "string"
},
{
"type": "null"
}
]
},
"costPrice": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
],
"description": "Purchase price per unit, in costCurrency. Ignored for a bundle: its cost is the sum of its components' costs when all are known and in one currency."
},
"categoryId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
]
},
"sizeSystem": {
"anyOf": [
{
"enum": [
"AU",
"BR",
"CN",
"DE",
"EU",
"FR",
"IT",
"JP",
"MEX",
"UK",
"US"
],
"type": "string"
},
{
"type": "null"
}
]
},
"supplierId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
]
},
"weightUnit": {
"anyOf": [
{
"enum": [
"kg",
"g",
"lb",
"oz"
],
"type": "string"
},
{
"type": "null"
}
]
},
"bundleItems": {
"type": "array",
"items": {
"type": "object",
"required": [
"productId",
"quantity"
],
"properties": {
"quantity": {
"type": "integer",
"maximum": 9007199254740991,
"exclusiveMinimum": 0
},
"productId": {
"type": "string",
"maxLength": 160,
"minLength": 1
}
},
"additionalProperties": false
},
"description": "Components of a bundle (type bundle only): simple, non-archived products of the bundle's warehouse, each listed once. Selling the bundle deducts these components; the bundle's stock is how many whole bundles they make. On update, sending it replaces the whole composition."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
]
},
"warehouseId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
]
},
"costCurrency": {
"anyOf": [
{
"type": "string",
"pattern": "^[A-Z]{3}$"
},
{
"type": "null"
}
]
},
"dimensionUnit": {
"anyOf": [
{
"enum": [
"cm",
"mm",
"in"
],
"type": "string"
},
{
"type": "null"
}
]
},
"compareAtPrice": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"productGroupId": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
]
},
"trackInventory": {
"type": "boolean",
"description": "Whether the product counts units. Ignored for a bundle: it tracks stock exactly when one of its components does."
}
},
"description": "The product fields to update; include at least one changed field.",
"additionalProperties": false
}
}
}Reorder, caption or REMOVE the photos a product already has. Send the photos as they should be afterwards: the order given is the display order (the first is the main photo), each alt replaces the stored caption (empty clears it), and a current photo you leave out is removed from the product (the stored file is kept, exactly as when a person removes a photo in the product form). Returns the new list and how many were removed. It never adds photos: every url must already belong to the product, otherwise the call is refused and nothing changes — use add_product_images to add. Idempotent: the same call twice leaves the same result. Saves through the product form's own operation. Call get_product first and copy the urls exactly. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| images* | array | The product's photos as they should be AFTER the change: the order given becomes the display order (the first is the main photo) and each alt replaces the stored caption (empty clears it). A current photo you leave out is REMOVED from the product; the stored file is kept, as when a person removes it in the product form. Every url must already belong to the product — to add a photo use add_product_images. |
| productId* | string | The product id from search_products or get_product. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"images",
"productId"
],
"properties": {
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"url"
],
"properties": {
"alt": {
"type": "string",
"maxLength": 200,
"description": "Caption (alt text) of the photo, up to 200 characters. Empty or omitted: the storefront falls back to the product name. Do not invent a description of what you cannot see."
},
"url": {
"type": "string",
"format": "uri",
"description": "The url of a photo the product ALREADY has, exactly as get_product returns it."
}
}
},
"maxItems": 10,
"description": "The product's photos as they should be AFTER the change: the order given becomes the display order (the first is the main photo) and each alt replaces the stored caption (empty clears it). A current photo you leave out is REMOVED from the product; the stored file is kept, as when a person removes it in the product form. Every url must already belong to the product — to add a photo use add_product_images."
},
"productId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The product id from search_products or get_product."
}
}
}Set a brand's DESCRIPTION in ONE language, leaving every other language as it is; null or an empty description removes that language. Translate the text yourself — Obriym does not translate for MCP clients. Never translate a brand NAME: marketplaces match it verbatim. Call list_content_locales first; the workspace's base language is refused (use update_brand for it). update_brand's translations field REPLACES the whole set, so use this tool to change a single language. Idempotent. Returns a warning when the CRM does not show that language yet. Echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| locale* | string | The language to write, as an ISO 639-1 code. Call list_content_locales for the codes this workspace uses; never the workspace's base language. |
| brandId* | string | The brand id returned by list_brands. |
| description* | any | The brand description in this language. null or an empty string clears that language. The brand NAME is never translated. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"brandId",
"description",
"locale"
],
"properties": {
"locale": {
"enum": [
"uk",
"ru",
"en",
"pl",
"de",
"it",
"fr",
"es",
"pt",
"nl",
"cs",
"sk",
"hu",
"ro",
"bg",
"lt",
"lv",
"et",
"tr"
],
"type": "string",
"description": "The language to write, as an ISO 639-1 code. Call list_content_locales for the codes this workspace uses; never the workspace's base language."
},
"brandId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The brand id returned by list_brands."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 5000
},
{
"type": "null"
}
],
"description": "The brand description in this language. null or an empty string clears that language. The brand NAME is never translated."
}
}
}Set a category's name and/or description in ONE language, leaving every other language as it is. Translate the text yourself — Obriym does not translate for MCP clients. Call list_content_locales first; the workspace's base language is refused (use update_category for it). A language needs a translated name before it can hold a description; description null clears it. Idempotent: repeating the same call changes nothing. update_category's translations field REPLACES the whole set, so use this tool to change a single language. Returns a warning when the CRM does not show that language yet. Echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| name | string | The category name in this language. Required the first time a language is written. |
| locale* | string | The language to write, as an ISO 639-1 code. Call list_content_locales for the codes this workspace uses; never the workspace's base language. |
| categoryId* | string | The category id returned by list_categories. |
| description | any | The category description in this language. null or an empty string clears it. Cannot be stored for a language that has no translated name. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"categoryId",
"locale"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The category name in this language. Required the first time a language is written."
},
"locale": {
"enum": [
"uk",
"ru",
"en",
"pl",
"de",
"it",
"fr",
"es",
"pt",
"nl",
"cs",
"sk",
"hu",
"ro",
"bg",
"lt",
"lv",
"et",
"tr"
],
"type": "string",
"description": "The language to write, as an ISO 639-1 code. Call list_content_locales for the codes this workspace uses; never the workspace's base language."
},
"categoryId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The category id returned by list_categories."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 5000
},
{
"type": "null"
}
],
"description": "The category description in this language. null or an empty string clears it. Cannot be stored for a language that has no translated name."
}
}
}Add or update characteristics (name, value, unit) on ONE product without removing the ones not named. Names match case-insensitively; a new name is appended. For eBay, use the item-specific names exactly as inspect_ebay_listings reported them (details.aspects), in the eBay site's own language — 'Marca' on ebay.it, not 'Brand'. Never invent a value: ask the user. Saves through the same product-card operation as the CRM form, with a version check (on CONFLICT re-read and retry). On a product that belongs to a model: when it is the model's only article, the characteristics are the model's and change for the model; when the model has other articles, a value set here applies to this article only — a characteristic shared by every article is changed on the model card. Idempotent. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The product id returned by search_products or get_product. |
| attributes* | array | Characteristics to add or update. Match is case-insensitive by name; every existing characteristic not named here is preserved. Use name/value/unit objects, for example {name:'Stile',value:'Casual',unit:null}. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"attributes",
"id"
],
"properties": {
"id": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The product id returned by search_products or get_product."
},
"attributes": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"value"
],
"properties": {
"name": {
"type": "string",
"maxLength": 160,
"minLength": 1
},
"unit": {
"anyOf": [
{
"type": "string",
"maxLength": 40
},
{
"type": "null"
}
],
"default": null
},
"value": {
"type": "string",
"maxLength": 500,
"minLength": 1
}
}
},
"maxItems": 100,
"minItems": 1,
"description": "Characteristics to add or update. Match is case-insensitive by name; every existing characteristic not named here is preserved. Use name/value/unit objects, for example {name:'Stile',value:'Casual',unit:null}."
}
}
}Add, update or REMOVE the price-list rows of ONE product — the price it sells at in another currency, for example EUR for an eBay site — keeping its other currencies and its own workspace-currency price. Send only an amount the user stated: never a converted or estimated price; to drop a currency send its code in remove. The product's own currency is refused; change that with update_product's price. A price for one channel only is set_product_channel_price; see all of a product's prices with get_product_pricing. Saves through the same product-card operation as the CRM form, with a version check (on CONFLICT re-read the product and retry), and the new price reaches connected channels like a manual edit. Idempotent. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The product id returned by search_products or get_product. |
| prices | array | Price-list rows to add or update, one per currency (uppercase 3-letter ISO code, e.g. EUR), an amount greater than 0 — the price the product sells at in that currency on every channel that trades in it. Refused for the product's own workspace currency — use update_product's price field for that one. Never a converted or guessed value: send exactly the amount the user gave for that market. Not a per-channel price: a price for ONE channel only is set_product_channel_price. Omit it when you only remove currencies. |
| remove | array | Currencies whose price-list row to REMOVE (uppercase 3-letter ISO code). The product stops being sold in that currency on channels that trade in it. The product's own workspace currency cannot be removed here, and a currency named in prices cannot also be removed. A currency with no row is ignored. |
Write ONE language of ONE product's translation — title, description, keywords, colour, material, pattern and its characteristics (attributes: keyed by the characteristic's name exactly as get_product returns it, each with a translated name and/or value) in that language — keeping the other languages and every field not named. A characteristic name the product does not have is refused with the list of its names. Call list_content_locales first and write only an offered language, never the base one. Use it when a marketplace publishes in another language (ebay.it reads Italian, Prom and Rozetka read uk and ru) or inspect_ebay_listings reports a title over 80 characters in the site's language. Translate the product's OWN text from get_product and add no fact it does not state; show the user the text before writing. For a product that belongs to a model the translation is the model's, so every article of it changes. Saves through the CRM's own Переклади tab operation with its version check (on CONFLICT re-read the product and retry). Idempotent. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| id* | string | The product id returned by search_products or get_product. |
| name | string | The product title in this language. eBay shows at most 80 characters. An empty string clears it, so the base name publishes. |
| color | string | Colour name. |
| locale* | string | The language to write, as an ISO 639-1 code — for a marketplace, the site's own language (it on ebay.it, de on ebay.de, uk or ru for Prom and Rozetka). |
End the LIVE eBay listing of up to 25 products: they stop being buyer-visible and their offers return to drafts — nothing is deleted, and publish_ebay_drafts can put them back. Needs the owner's AI publishing switch. Returns done, failed and notAttempted. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| productIds* | array | End each product's LIVE eBay listing, at most 25 ids fetched with search_products. The listing stops being buyer-visible and its offer returns to a draft — it is NOT deleted. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"productIds"
],
"properties": {
"productIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
},
"maxItems": 25,
"minItems": 1,
"description": "End each product's LIVE eBay listing, at most 25 ids fetched with search_products. The listing stops being buyer-visible and its offer returns to a draft — it is NOT deleted."
}
}
}End a model's LIVE eBay multi-variation listing: every variation leaves sale at once. The group and its offers stay on eBay as a draft, so publish_ebay_variation_listing restores the same listing. Works while listing creation is disarmed (a way off eBay is never locked), but is refused until the workspace owner switches on AI publishing. Returns withdrawn. The result echoes the workspace.
| Argument | Type | Description |
|---|---|---|
| model* | string | The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"model"
],
"properties": {
"model": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The product model: its code — the productGroupId get_product and search_products return for every article of it — or its id. Its active articles on the eBay channel become the listing's variations."
}
}
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"delta",
"productId",
"reason"
],
"properties": {
"note": {
"type": "string",
"maxLength": 1000,
"minLength": 1
},
"delta": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": -9007199254740991
},
"reason": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"metadata": {
"type": "object",
"propertyNames": {
"type": "string"
},
"additionalProperties": {}
},
"productId": {
"type": "string",
"minLength": 1
},
"externalId": {
"type": "string",
"maxLength": 160,
"minLength": 1
}
},
"additionalProperties": false
}| target | any | WHICH number moves. Omit it to change the product's own selling price. Use {field:'price', currency:'EUR'} for the euro price list, {field:'cost'} for the purchase cost. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"digest",
"rule",
"scope"
],
"properties": {
"rule": {
"oneOf": [
{
"type": "object",
"required": [
"op",
"percent",
"rounding"
],
"properties": {
"op": {
"type": "string",
"const": "percent",
"description": "Raise or lower by a percent."
},
"percent": {
"type": "number",
"maximum": 900,
"minimum": -90,
"description": "Percent change: 10 raises by 10%, -10 lowers by 10%. Between -90 and 900."
},
"rounding": {
"enum": [
"cents",
"whole",
"nine",
"tens"
],
"type": "string",
"description": "How the new price is rounded: cents (to 2 decimals), whole (up to the next whole unit), nine (up to the next price ending in 9, e.g. 644.80 -> 649) or tens (up to the next ten). Everything except cents rounds UP."
}
}
},
{
"type": "object",
"required": [
"amount",
"op"
],
"properties": {
"op": {
"type": "string",
"const": "fixed",
"description": "Set one price for every product in scope."
},
"amount": {
"type": "string",
"pattern": "^\\d{1,10}(\\.\\d{1,2})?$",
"description": "One price for EVERY product in scope, as a decimal string, e.g. '1290' or '1290.50'. Rare for a whole category — check the preview."
}
}
},
{
"type": "object",
"required": [
"markupPercent",
"op",
"rounding"
],
"properties": {
"op": {
"type": "string",
"const": "fromCost",
"description": "Price = purchase cost plus a markup."
},
"rounding": {
"enum": [
"cents",
"whole",
"nine",
"tens"
],
"type": "string",
"description": "How the new price is rounded: cents (to 2 decimals), whole (up to the next whole unit), nine (up to the next price ending in 9, e.g. 644.80 -> 649) or tens (up to the next ten). Everything except cents rounds UP."
},
"markupPercent": {
"type": "number",
"maximum": 900,
"minimum": -90,
"description": "Markup over the purchase cost, in percent: 40 means price = cost x 1.4. The cost is crossed into the price's currency at the rates the workspace states; a product without a cost or a rate is skipped."
}
}
},
{
"type": "object",
"required": [
"op",
"percent",
"rounding"
],
"properties": {
"op": {
"type": "string",
"const": "discount",
"description": "Start a sale: the old price becomes the current price (or stays, if a higher one is set) and the price drops by the percent."
},
"percent": {
"type": "number",
"maximum": 90,
"minimum": 1,
"description": "Discount in percent, 1 to 90."
},
"rounding": {
"enum": [
"cents",
"whole",
"nine",
"tens"
],
"type": "string",
"description": "How the new price is rounded: cents (to 2 decimals), whole (up to the next whole unit), nine (up to the next price ending in 9, e.g. 644.80 -> 649) or tens (up to the next ten). Everything except cents rounds UP."
}
}
},
{
"type": "object",
"required": [
"op"
],
"properties": {
"op": {
"type": "string",
"const": "endDiscount",
"description": "End a sale: the price returns to the old price and the old price is cleared."
}
}
},
{
"type": "object",
"required": [
"op",
"percent",
"rounding"
],
"properties": {
"op": {
"type": "string",
"const": "compareAtMarkup",
"description": "Set the old (struck-through) price above the current price by a percent. Does not change the price."
},
"percent": {
"type": "number",
"maximum": 900,
"minimum": 1,
"description": "How far above the price the old price sits, in percent."
},
"rounding": {
"enum": [
"cents",
"whole",
"nine",
"tens"
],
"type": "string",
"description": "How the new price is rounded: cents (to 2 decimals), whole (up to the next whole unit), nine (up to the next price ending in 9, e.g. 644.80 -> 649) or tens (up to the next ten). Everything except cents rounds UP."
}
}
},
{
"type": "object",
"required": [
"op"
],
"properties": {
"op": {
"type": "string",
"const": "compareAtClear",
"description": "Remove the old price. Does not change the price."
}
}
}
],
"description": "HOW prices move. The target 'cost' accepts only op 'percent'. Pick the one that matches the request: a percent change, a fixed price, a markup over cost, a discount (and its end), or the old price."
},
"scope": {
"oneOf": [
{
"type": "object",
"required": [
"ids",
"kind"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id from search_products."
},
"maxItems": 100,
"minItems": 1,
"description": "Explicit product ids actually fetched with search_products, at most 100."
},
"kind": {
"type": "string",
"const": "ids",
"description": "Specific products you fetched. Prefer a container."
}
}
},
{
"type": "object",
"required": [
"id",
"kind"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The warehouse id returned by list_warehouses."
},
"kind": {
"type": "string",
"const": "warehouse",
"description": "Every product of one warehouse."
}
}
},
{
"type": "object",
"required": [
"id",
"kind"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The category id returned by list_categories."
},
"kind": {
"type": "string",
"const": "category",
"description": "Every product of one category."
},
"includeSubcategories": {
"type": "boolean",
"description": "true to include every sub-category under it ('everything under Backpacks'); omit it for exactly that one category. Never widen it unless the person means the whole branch."
}
}
},
{
"type": "object",
"required": [
"id",
"kind"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The brand id returned by list_brands."
},
"kind": {
"type": "string",
"const": "brand",
"description": "Every product of one brand."
}
}
},
{
"type": "object",
"required": [
"id",
"kind"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The supplier id returned by list_suppliers."
},
"kind": {
"type": "string",
"const": "supplier",
"description": "Every product of one supplier."
}
}
},
{
"type": "object",
"required": [
"id",
"kind"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The model id from get_product (its model block)."
},
"kind": {
"type": "string",
"const": "model",
"description": "Every article of one product model."
}
}
}
],
"description": "WHICH products. Prefer a named container (category, brand, supplier, warehouse) when the person says 'all products of …' — it is read back by name in the preview. There is no free filter: a request like 'everything cheaper than 100' is not a scope; find the products first and send their ids."
},
"digest": {
"type": "string",
"minLength": 1,
"description": "The digest returned by preview_bulk_price_change for THIS rule, scope and target — copied verbatim, never invented. If prices moved since, the apply returns CONFLICT and you must preview again."
},
"target": {
"oneOf": [
{
"type": "object",
"required": [
"field"
],
"properties": {
"field": {
"type": "string",
"const": "price",
"description": "Change the selling price."
},
"currency": {
"anyOf": [
{
"type": "string",
"pattern": "^[A-Z]{3}$"
},
{
"type": "null"
}
],
"default": null,
"description": "null (default) = the product's own price in the workspace currency. A 3-letter code = that currency's row of the product's price list (the workspace currency itself means null)."
}
}
},
{
"type": "object",
"required": [
"field"
],
"properties": {
"field": {
"type": "string",
"const": "cost",
"description": "Change the purchase cost (percent only). Not published to channels."
}
}
}
],
"default": {
"field": "price",
"currency": null
},
"description": "WHICH number moves. Omit it to change the product's own selling price. Use {field:'price', currency:'EUR'} for the euro price list, {field:'cost'} for the purchase cost."
}
}
}| any |
| User id of the workspace member to assign the activity to; null/omit for unassigned. |
| description | any | Detailed description or notes. Optional. |
| recurrenceRule | any | Recurrence rule: daily, weekly, or monthly. Optional (one-off if omitted). |
| recurrenceEndsAt | any | When recurrence stops, ISO 8601. Optional; only meaningful with recurrenceRule. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"title",
"type"
],
"properties": {
"type": {
"enum": [
"task",
"call",
"meeting",
"email",
"note"
],
"type": "string",
"description": "Activity type. One of: task, call, meeting, email, note."
},
"title": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "Short title of the activity. Required."
},
"dealId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Deal id to link the activity to (from search_deals). Link at least one entity."
},
"leadId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Lead id to link the activity to (from search_leads). Link at least one entity."
},
"dueDate": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
],
"description": "Due date/time, ISO 8601. Optional."
},
"priority": {
"enum": [
"low",
"medium",
"high"
],
"type": "string",
"description": "Priority. Optional. One of: low, medium, high."
},
"companyId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Company id to link the activity to (from search_companies). Link at least one entity."
},
"contactId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Contact id to link the activity to (from search_contacts). Link at least one entity."
},
"assignedTo": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "User id of the workspace member to assign the activity to; null/omit for unassigned."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 5000,
"description": "Detailed description or notes. Optional."
},
{
"type": "null"
}
],
"description": "Detailed description or notes. Optional."
},
"recurrenceRule": {
"anyOf": [
{
"enum": [
"daily",
"weekly",
"monthly"
],
"type": "string",
"description": "Recurrence rule: daily, weekly, or monthly. Optional (one-off if omitted)."
},
{
"type": "null"
}
],
"description": "Recurrence rule: daily, weekly, or monthly. Optional (one-off if omitted)."
},
"recurrenceEndsAt": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
],
"description": "When recurrence stops, ISO 8601. Optional; only meaningful with recurrenceRule."
}
},
"additionalProperties": false
}| translations |
| array |
| Category name (and optional description) per locale. Omit to leave existing translations untouched; when sent it REPLACES the whole set, so an empty array removes them all. |
| googleProductCategory | any | Google Product Taxonomy id or full path for this category (for Google Shopping). Prefer marketplaceCategories.google_merchant, which this field is an alias of; send the Google category in one place only. Separate from the name; send null to clear it. |
| marketplaceCategories | object | The category's id on each marketplace, keyed by platform. Omit a platform to leave it untouched, send null to clear it. Every value is checked on write (format always; against the marketplace itself while it is connected) — find valid ids with search_marketplace_categories first. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The category name in the workspace's base language, up to 120 characters. Must be unique among categories with the same parent."
},
"slug": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
],
"description": "URL segment for the category. Normalized to lowercase Latin letters, digits and hyphens whatever is sent (Cyrillic is transliterated); derived from the name when omitted."
},
"parentId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Id of the parent category from list_categories, to nest this one under it; it must exist in this workspace. Omit or send null for a top-level category."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 4000
},
{
"type": "null"
}
],
"description": "Prose a storefront shows at the top of the category shelf, in the workspace's base language (up to 4000 characters). Send null to clear it."
},
"translations": {
"type": "array",
"items": {
"type": "object",
"required": [
"locale",
"name"
],
"properties": {
"name": {
"type": "string",
"maxLength": 120
},
"locale": {
"enum": [
"uk",
"ru",
"en",
"pl",
"de",
"it",
"fr",
"es",
"pt",
"nl",
"cs",
"sk",
"hu",
"ro",
"bg",
"lt",
"lv",
"et",
"tr"
],
"type": "string",
"example": "en",
"description": "Content locale, one of the workspace's supported languages."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 4000
},
{
"type": "null"
}
]
}
},
"additionalProperties": false
},
"maxItems": 19,
"description": "Category name (and optional description) per locale. Omit to leave existing translations untouched; when sent it REPLACES the whole set, so an empty array removes them all."
},
"googleProductCategory": {
"anyOf": [
{
"type": "string",
"maxLength": 255,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Google Product Taxonomy id or full path for this category (for Google Shopping). Prefer marketplaceCategories.google_merchant, which this field is an alias of; send the Google category in one place only. Separate from the name; send null to clear it."
},
"marketplaceCategories": {
"type": "object",
"properties": {
"olx": {
"anyOf": [
{
"type": "string",
"maxLength": 10,
"minLength": 1
},
{
"type": "null"
}
],
"description": "OLX category id (digits) that products of this category publish into. Must be a FINAL (leaf) OLX category — OLX refuses an advert in a parent. While OLX is connected it is checked against OLX and its path is stored for display. Take it from search_marketplace_categories, never guess. Not inherited by subcategories. Send null to clear it."
},
"prom": {
"anyOf": [
{
"type": "string",
"maxLength": 40,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Prom.ua rubric id (digits) — exported as <portal_category_id>; Prom refuses an offer without it. Prom publishes no category directory: take the id from search_marketplace_categories (rubrics observed on the merchant's own Prom listings) or from the user, never guess. Not inherited by subcategories. Send null to clear it."
},
"amazon": {
"anyOf": [
{
"type": "string",
"maxLength": 60,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Amazon product type (e.g. SHOES, HOME_BED_AND_BATH) — the schema Amazon validates every listing of this category against; no Amazon listing can be created without it. Upper-cased on write. While Amazon is connected it is checked against Amazon. Take it from search_marketplace_categories, never guess. Not inherited by subcategories. Send null to clear it."
},
"rozetka": {
"anyOf": [
{
"type": "string",
"maxLength": 40,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Rozetka category id (digits) — exported as rz_id, which links this category to Rozetka's tree. Take it from search_marketplace_categories, never guess. Not inherited by subcategories. Send null to clear it."
},
"google_merchant": {
"anyOf": [
{
"type": "string",
"maxLength": 255,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Google Product Taxonomy entry for Google Shopping — the numeric id (e.g. 187). An exact English taxonomy path is accepted and stored as its id. Take it from search_marketplace_categories, never guess. Subcategories without their own value inherit the nearest parent's. Send null to clear it."
}
},
"description": "The category's id on each marketplace, keyed by platform. Omit a platform to leave it untouched, send null to clear it. Every value is checked on write (format always; against the marketplace itself while it is connected) — find valid ids with search_marketplace_categories first.",
"additionalProperties": false
}
},
"additionalProperties": false
}| User id of the workspace member who owns this company. Optional. |
| website | any | The company website URL. Optional. |
| bankName | any | The counterparty's bank name. Optional. |
| industry | any | The company's industry. Optional. |
| taxGroup | any | Single-tax group. Only meaningful for a sole trader on the simplified system. |
| vatPayer | boolean | Whether the counterparty is a VAT payer. Optional. |
| taxSystem | any | Tax system: simplified or general. Optional. |
| vatNumber | any | VAT payer identifier. Optional. |
| creditLimit | any | Maximum outstanding balance. Optional; requires creditLimitCurrency. |
| legalAddress | any | Legal address. Optional. |
| deliveryAddress | any | Delivery address. Optional. |
| counterpartyType | string | Counterparty type: company, sole_trader, or individual. Defaults to company. |
| paymentTermsDays | any | Agreed payment term in days (0-365). Optional. |
| creditLimitCurrency | any | ISO currency for creditLimit. Required when creditLimit is set. |
| representationState | string | Declared representation state: unspecified, works_alone, or has_representatives. Never inferred from contact count. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"name"
],
"properties": {
"iban": {
"anyOf": [
{
"type": "string",
"maxLength": 34
},
{
"type": "null"
}
],
"description": "The counterparty's IBAN. Optional."
},
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "The company name. Required and unique within the workspace."
},
"size": {
"enum": [
"solo",
"small",
"medium",
"large",
"enterprise"
],
"type": "string",
"description": "Company size band. Optional. One of: solo, small, medium, large, enterprise."
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"description": "Tags for segmentation. Optional."
},
"email": {
"anyOf": [
{
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 255,
"description": "The company email. Optional."
},
{
"type": "null"
}
],
"description": "The company email. Optional."
},
"phone": {
"anyOf": [
{
"type": "string",
"maxLength": 50,
"description": "The company phone. Optional."
},
{
"type": "null"
}
],
"description": "The company phone. Optional."
},
"edrpou": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d{8}(\\d{2})?$",
"maxLength": 20,
"description": "Tax id: 8-digit ЄДРПОУ or 10-digit ІПН. Optional."
},
{
"type": "null"
}
],
"description": "Tax identifier: 8-digit EDRPOU or 10-digit taxpayer number. Optional."
},
"status": {
"enum": [
"prospect",
"active",
"inactive"
],
"type": "string",
"description": "Relationship status. Optional. One of: prospect, active, inactive."
},
"ownerId": {
"anyOf": [
{
"type": "string",
"description": "User id of the workspace member who owns this company. Optional."
},
{
"type": "null"
}
],
"description": "User id of the workspace member who owns this company. Optional."
},
"website": {
"anyOf": [
{
"type": "string",
"format": "uri",
"maxLength": 255,
"description": "The company website URL. Optional."
},
{
"type": "null"
}
],
"description": "The company website URL. Optional."
},
"bankName": {
"anyOf": [
{
"type": "string",
"maxLength": 160
},
{
"type": "null"
}
],
"description": "The counterparty's bank name. Optional."
},
"industry": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"description": "The company's industry. Optional."
},
{
"type": "null"
}
],
"description": "The company's industry. Optional."
},
"taxGroup": {
"anyOf": [
{
"enum": [
"group_1",
"group_2",
"group_3"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "Single-tax group. Only meaningful for a sole trader on the simplified system."
},
"vatPayer": {
"type": "boolean",
"description": "Whether the counterparty is a VAT payer. Optional."
},
"taxSystem": {
"anyOf": [
{
"enum": [
"simplified",
"general"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "Tax system: simplified or general. Optional."
},
"vatNumber": {
"anyOf": [
{
"type": "string",
"maxLength": 20
},
{
"type": "null"
}
],
"description": "VAT payer identifier. Optional."
},
"creditLimit": {
"anyOf": [
{
"type": "string",
"pattern": "^(?:0|[1-9]\\d{0,11})(?:\\.\\d{1,2})?$",
"description": "Non-negative credit limit up to 999999999999.99."
},
{
"type": "null"
}
],
"description": "Maximum outstanding balance. Optional; requires creditLimitCurrency."
},
"legalAddress": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"description": "Legal address. Optional."
},
"deliveryAddress": {
"anyOf": [
{
"type": "string",
"maxLength": 500
},
{
"type": "null"
}
],
"description": "Delivery address. Optional."
},
"counterpartyType": {
"enum": [
"company",
"sole_trader",
"individual"
],
"type": "string",
"description": "Counterparty type: company, sole_trader, or individual. Defaults to company."
},
"paymentTermsDays": {
"anyOf": [
{
"type": "integer",
"maximum": 365,
"minimum": 0,
"description": "Payment terms in whole days from 0 to 365."
},
{
"type": "null"
}
],
"description": "Agreed payment term in days (0-365). Optional."
},
"creditLimitCurrency": {
"anyOf": [
{
"type": "string",
"pattern": "^[A-Z]{3}$",
"maxLength": 3,
"description": "Uppercase 3-letter ISO currency for the credit limit."
},
{
"type": "null"
}
],
"description": "ISO currency for creditLimit. Required when creditLimit is set."
},
"representationState": {
"enum": [
"unspecified",
"works_alone",
"has_representatives"
],
"type": "string",
"default": "unspecified",
"description": "Declared representation state: unspecified, works_alone, or has_representatives. Never inferred from contact count."
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"firstName"
],
"properties": {
"tags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80
},
"default": [],
"description": "Tags for segmentation. Optional."
},
"email": {
"anyOf": [
{
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 255,
"description": "The contact's email address. Optional."
},
{
"type": "null"
}
],
"description": "The contact's email address. Optional."
},
"phone": {
"anyOf": [
{
"type": "string",
"maxLength": 50,
"description": "The contact's phone number. Optional."
},
{
"type": "null"
}
],
"description": "The contact's phone number. Optional."
},
"ownerId": {
"anyOf": [
{
"type": "string",
"description": "User id of the workspace member who owns this contact. Optional."
},
{
"type": "null"
}
],
"description": "User id of the workspace member who owns this contact. Optional."
},
"jobTitle": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"description": "The contact's job title. Optional."
},
{
"type": "null"
}
],
"description": "The contact's job title. Optional."
},
"lastName": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"description": "The contact's last name. Optional."
},
{
"type": "null"
}
],
"description": "The contact's last name. Optional."
},
"companyId": {
"anyOf": [
{
"type": "string",
"description": "Company id to link this contact to (from search_companies). Optional."
},
{
"type": "null"
}
],
"description": "Company id to link this contact to (from search_companies). Optional."
},
"firstName": {
"type": "string",
"maxLength": 120,
"minLength": 1,
"description": "The contact's first name. Required."
},
"documentRole": {
"anyOf": [
{
"enum": [
"signatory",
"accountant",
"manager",
"other"
],
"type": "string"
},
{
"type": "null"
}
],
"description": "The contact's role on sales documents. Optional."
}
},
"additionalProperties": false
}| Where the post goes — one entry per channel, each at most once. Every channel publishes the main text unless its entry carries its own text. |
| hashtags | array | Hashtags without the "#" sign, at most 30. They are appended to every channel's text as their own line. |
| imageUrls | array | Images to attach, as public https links to JPEG, PNG or WebP files of at most 2 MB each. Obriym downloads and keeps its own copy, so the link only has to work now. Threads accepts JPEG and PNG only. |
| productId | string | A catalog product this post advertises (id from search_products). Links the post to the product, so when it sells out Obriym marks the live Telegram and Threads post as sold, and lets productPhotos attach the product's photos. |
| productPhotos | boolean | With productId: attach the product's own photos after any imageUrls, up to 10 images in total. Set false to post without them. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"channels",
"title"
],
"properties": {
"text": {
"type": "string",
"default": "",
"maxLength": 10000,
"description": "The post's main text, in the language the audience reads. Plain text: no markdown, links are written out in full. Never invent a price, discount, stock level or date — state only facts the user or the CRM gave you."
},
"files": {
"type": "array",
"items": {
"type": "object",
"required": [
"download_url",
"file_id"
],
"properties": {
"file_id": {
"type": "string",
"description": "ChatGPT's id of the attached file."
},
"file_name": {
"type": "string",
"description": "The attached file's name."
},
"mime_type": {
"type": "string",
"description": "The attached file's type."
},
"download_url": {
"type": "string",
"format": "uri",
"description": "Temporary link ChatGPT gives to the attached file."
}
}
},
"maxItems": 10,
"description": "Image files the person attached in ChatGPT. ChatGPT fills this field itself; any other client leaves it out and passes image links instead (or uploads files with create_image_upload)."
},
"title": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "An internal working title shown in Obriym's Publications list, e.g. \"Monday — new arrivals\". Never published."
},
"format": {
"enum": [
"post",
"story"
],
"type": "string",
"default": "post",
"description": "post = a regular feed post; story = an Instagram/Facebook story, which needs an image. Defaults to post."
},
"channels": {
"type": "array",
"items": {
"type": "object",
"required": [
"channel"
],
"properties": {
"text": {
"type": "string",
"maxLength": 63206,
"description": "Text written for THIS network only. Omit it to publish the post's main text. It must fit the channel's maxTextLength from list_content_channels together with the hashtags (Threads allows 500 characters, Instagram 2200)."
},
"channel": {
"enum": [
"instagram",
"facebook",
"telegram",
"linkedin",
"threads",
"viber"
],
"type": "string",
"description": "A social channel: telegram (the bound Telegram channel), instagram, facebook (the Facebook page), linkedin, threads or viber (the connected Viber channel). Use only channels list_content_channels reports as ready."
}
}
},
"maxItems": 6,
"minItems": 1,
"description": "Where the post goes — one entry per channel, each at most once. Every channel publishes the main text unless its entry carries its own text."
},
"hashtags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"maxItems": 30,
"description": "Hashtags without the \"#\" sign, at most 30. They are appended to every channel's text as their own line."
},
"imageUrls": {
"type": "array",
"items": {
"type": "string",
"format": "uri",
"maxLength": 2048,
"description": "A public https link to the image file itself."
},
"default": [],
"maxItems": 10,
"description": "Images to attach, as public https links to JPEG, PNG or WebP files of at most 2 MB each. Obriym downloads and keeps its own copy, so the link only has to work now. Threads accepts JPEG and PNG only."
},
"productId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "A catalog product this post advertises (id from search_products). Links the post to the product, so when it sells out Obriym marks the live Telegram and Threads post as sold, and lets productPhotos attach the product's photos."
},
"productPhotos": {
"type": "boolean",
"default": true,
"description": "With productId: attach the product's own photos after any imageUrls, up to 10 images in total. Set false to post without them."
}
}
}| integer |
| Win probability percent, 0-100. Optional (defaults from the stage). |
| nextActionDate* | string | Next-action date, ISO 8601. Required. |
| nextActionNote* | string | What the next action on this deal is. Required. |
| expectedCloseDate | any | Expected close date, ISO 8601. Optional. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"nextActionDate",
"nextActionNote",
"stageId",
"title"
],
"properties": {
"notes": {
"anyOf": [
{
"type": "string",
"maxLength": 5000,
"description": "Free-text notes on the deal. Optional."
},
{
"type": "null"
}
],
"description": "Free-text notes on the deal. Optional."
},
"title": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "Deal title. Required."
},
"amount": {
"type": "string",
"pattern": "^\\d+(\\.\\d{1,2})?$",
"description": "Deal value as a decimal string, e.g. 1500.00. Optional."
},
"ownerId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "User id of the workspace member to own the deal; null/omit for none."
},
"stageId": {
"type": "string",
"description": "Pipeline stage id for the deal (from list_pipeline_stages). Required."
},
"companyId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Company id to link the deal to (from search_companies); null/omit for none."
},
"contactId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
],
"description": "Contact id to link the deal to (from search_contacts); null/omit for none."
},
"lostReason": {
"anyOf": [
{
"type": "string",
"maxLength": 500,
"description": "Reason the deal was lost. Required only when moving to a Closed-lost stage."
},
{
"type": "null"
}
],
"description": "Reason the deal was lost. Optional (required only for Closed-lost stages)."
},
"probability": {
"type": "integer",
"maximum": 100,
"minimum": 0,
"description": "Win probability percent, 0-100. Optional (defaults from the stage)."
},
"nextActionDate": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
"description": "Next-action date, ISO 8601. Required."
},
"nextActionNote": {
"type": "string",
"maxLength": 500,
"minLength": 1,
"description": "What the next action on this deal is. Required."
},
"expectedCloseDate": {
"anyOf": [
{
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"
},
{
"type": "null"
}
],
"description": "Expected close date, ISO 8601. Optional."
}
},
"additionalProperties": false
}| promotion |
| object |
| Ask the CRM to validate and calculate this promo code. Do not supply promoCode, discountAmount or shippingThresholdAmount alongside it. An optional expectedTotal refuses a changed quote; the server always owns the actual discount. |
| externalId* | string | A stable unique id for this order in your system — the idempotency key. Re-sending the same externalId returns the existing order instead of creating a duplicate (e.g. 'mcp-<uuid>'). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"currency",
"externalId",
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"required": [
"productName",
"quantity",
"unitPrice"
],
"properties": {
"sku": {
"type": "string",
"maxLength": 120,
"description": "Product SKU snapshot (from search_products). Optional."
},
"discount": {
"type": "number",
"default": 0,
"maximum": 100,
"minimum": 0,
"description": "Percentage discount on this line (0-100). Default 0."
},
"quantity": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Quantity ordered (integer, at least 1).",
"exclusiveMinimum": 0
},
"unitPrice": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d+(\\.\\d{1,2})?$"
},
{
"type": "number",
"minimum": 0
}
],
"description": "Price per unit in the order currency, as a decimal (e.g. 199.99). Snapshotted onto the line."
},
"productName": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "Line item name, snapshotted onto the order. Use search_products to quote a real catalog product's name. Required."
}
},
"additionalProperties": false
},
"maxItems": 100,
"minItems": 1,
"description": "Order line items (1-100). Each snapshots productName/sku/unitPrice."
},
"notes": {
"type": "string",
"maxLength": 5000,
"description": "Internal note stored on the order. For a delivery instruction from the buyer use delivery.comment instead."
},
"currency": {
"type": "string",
"pattern": "^[A-Z]{3}$",
"maxLength": 3,
"minLength": 3,
"description": "Required ISO 4217 currency code from the source facts or selected CRM product prices. Never guess or convert between currencies."
},
"customer": {
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 255
},
"phone": {
"type": "string",
"maxLength": 50,
"minLength": 1
},
"lastName": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"firstName": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"externalId": {
"type": "string",
"maxLength": 160,
"minLength": 1
},
"shippingAddress": {
"type": "object",
"required": [
"city",
"country",
"line1"
],
"properties": {
"city": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"line1": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"line2": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"region": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"country": {
"type": "string",
"maxLength": 2,
"minLength": 2
},
"postalCode": {
"type": "string",
"maxLength": 32,
"minLength": 1
}
},
"additionalProperties": false
}
},
"description": "Optional buyer snapshot (name/email/phone, or a storefront customer externalId). Omit for an anonymous order.",
"additionalProperties": false
},
"delivery": {
"type": "object",
"properties": {
"cod": {
"type": "boolean",
"description": "True when the buyer pays on delivery (cash on delivery)."
},
"flat": {
"type": "string",
"maxLength": 35,
"description": "Apartment or office number for courier delivery."
},
"phone": {
"type": "string",
"maxLength": 50,
"description": "Recipient phone, when it differs from the buyer's own contact phone."
},
"branch": {
"type": "string",
"maxLength": 200,
"description": "Branch or parcel locker as the buyer named it, e.g. \"відділення №5\" or \"поштомат 12345\". Free text: the CRM resolves it against the live branch list of the carrier when creating a waybill."
},
"method": {
"enum": [
"branch",
"courier",
"pickup"
],
"type": "string",
"description": "How the parcel reaches the buyer: \"branch\" (carrier office/locker), \"courier\" (to the address) or \"pickup\" (buyer collects from you)."
},
"carrier": {
"type": "string",
"maxLength": 120,
"description": "Carrier slug the buyer chose, from GET /capabilities (e.g. \"nova_poshta\", \"ukrposhta\", \"pickup\"). This is a preference, not a dispatch — the shipment endpoint still records what actually ships."
},
"cityRef": {
"type": "string",
"maxLength": 64,
"description": "The carrier's own identifier for the destination city, as returned by GET /api/v1/carriers/{carrier}/cities. Required alongside branchRef or streetRef for a waybill to be created from the order alone."
},
"comment": {
"type": "string",
"maxLength": 1000,
"description": "Delivery note from the buyer, e.g. \"дзвонити після 18:00\". Not the order notes."
},
"building": {
"type": "string",
"maxLength": 35,
"description": "House number for courier delivery, structured rather than inside the address line because carriers validate it on its own (Nova Poshta accepts up to 11 characters matching digits plus an optional Cyrillic letter or block, e.g. \"12Б\" or \"12/4\")."
},
"branchRef": {
"type": "string",
"maxLength": 64,
"description": "The carrier's own identifier for the branch or parcel locker, as returned by GET /api/v1/carriers/{carrier}/warehouses. The same value the shipment-label endpoint calls warehouseRef. Sent, this removes all guessing; omitted, the CRM falls back to matching `branch` as text."
},
"streetRef": {
"type": "string",
"maxLength": 64,
"description": "The carrier's own identifier for the street, as returned by GET /api/v1/carriers/{carrier}/streets. Courier delivery only; pair it with `building`."
},
"recipientName": {
"type": "string",
"maxLength": 200,
"description": "Who receives the parcel, when that is not the buyer (a gift, an office)."
}
},
"description": "How the buyer asked to receive the order: carrier, branch/courier/pickup, branch text, recipient, cash-on-delivery and a delivery note. This is the buyer's choice at checkout — it does not dispatch anything. Record what actually ships with POST /orders/{externalId}/shipments.",
"additionalProperties": false
},
"promotion": {
"type": "object",
"required": [
"code"
],
"properties": {
"code": {
"type": "string",
"pattern": "^[A-Za-z0-9][A-Za-z0-9_-]{2,63}$",
"description": "CRM-managed promo code, 3–64 letters, digits, hyphens or underscores; case-insensitive. Must be enabled for this connection's source; a personal or capture code also needs the buyer email it was issued to."
},
"expectedTotal": {
"type": "string",
"pattern": "^\\d{1,10}(?:\\.\\d{1,2})?$",
"description": "Net merchandise total the buyer was shown, as a decimal string with up to two decimals (for example \"199.90\"), in the order currency. If the CRM now calculates a different amount the request is refused with price_changed."
}
},
"description": "Ask the CRM to validate and calculate this promo code. Do not supply promoCode, discountAmount or shippingThresholdAmount alongside it. An optional expectedTotal refuses a changed quote; the server always owns the actual discount.",
"additionalProperties": false
},
"externalId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "A stable unique id for this order in your system — the idempotency key. Re-sending the same externalId returns the existing order instead of creating a duplicate (e.g. 'mcp-<uuid>')."
}
},
"additionalProperties": false
}| string |
| simple, or bundle — one sellable item made of bundleItems, holding no stock of its own. Fixed at creation: an update that changes it is refused. |
| unit | any |
| color | any |
| depth | any |
| price | any |
| stock | any | Units on hand, for a product that tracks inventory; a change on update is recorded as a relative movement in the stock history. Refused for a bundle — its stock is derived from its components. |
| width | any |
| gender | any |
| height | any |
| images | array | The product's photos as { url, alt }, at most 10; the first is the main photo. On an update the list you send replaces the whole set. An entry whose url equals a photo the product already has keeps that stored file and takes only the caption (alt) you send, so sending back what you read never downgrades a stored photo. |
| status | string |
| videos | array | Video links for the product page (YouTube, Vimeo or a direct file), https only, at most 5. Links, not uploads. On update, sending the field replaces the whole list. |
| weight | any |
| brandId | any |
| pattern | any |
| ageGroup | any |
| material | any |
| sizeType | any |
| condition | any |
| costPrice | any | Purchase price per unit, in costCurrency. Ignored for a bundle: its cost is the sum of its components' costs when all are known and in one currency. |
| categoryId | any |
| sizeSystem | any |
| supplierId | any |
| weightUnit | any |
| bundleItems | array | Components of a bundle (type bundle only): simple, non-archived products of the bundle's warehouse, each listed once. Selling the bundle deducts these components; the bundle's stock is how many whole bundles they make. On update, sending it replaces the whole composition. |
| description | any |
| warehouseId | any |
| costCurrency | any |
| dimensionUnit | any |
| compareAtPrice | any |
| productGroupId | any |
| trackInventory | boolean | Whether the product counts units. Ignored for a bundle: it tracks stock exactly when one of its components does. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"name"
],
"properties": {
"ean": {
"anyOf": [
{
"type": "string",
"pattern": "^[0-9]{8,14}$"
},
{
"type": "null"
}
],
"example": "4006381333931",
"description": "GTIN/EAN-8/12/13/14 barcode. Presence-and-shape validation only, no checksum."
},
"mpn": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
],
"example": "TR-1",
"description": "Manufacturer part number — the maker's own code for the item, not the shop SKU. eBay requires it beside the brand in many categories."
},
"sku": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
]
},
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"size": {
"anyOf": [
{
"type": "string",
"maxLength": 60,
"minLength": 1
},
{
"type": "null"
}
]
},
"tags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 80,
"minLength": 1
},
"default": []
},
"type": {
"enum": [
"simple",
"bundle"
],
"type": "string",
"default": "simple",
"description": "simple, or bundle — one sellable item made of bundleItems, holding no stock of its own. Fixed at creation: an update that changes it is refused."
},
"unit": {
"anyOf": [
{
"type": "string",
"maxLength": 40,
"minLength": 1
},
{
"type": "null"
}
]
},
"color": {
"anyOf": [
{
"type": "string",
"maxLength": 80,
"minLength": 1
},
{
"type": "null"
}
]
},
"depth": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"price": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"stock": {
"anyOf": [
{
"type": "integer",
"maximum": 9007199254740991,
"minimum": 0
},
{
"type": "null"
}
],
"description": "Units on hand, for a product that tracks inventory; a change on update is recorded as a relative movement in the stock history. Refused for a bundle — its stock is derived from its components."
},
"width": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"gender": {
"anyOf": [
{
"enum": [
"male",
"female",
"unisex"
],
"type": "string"
},
{
"type": "null"
}
]
},
"height": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"images": {
"type": "array",
"items": {
"type": "object",
"required": [
"url"
],
"properties": {
"alt": {
"type": "string",
"example": "White leather sneakers, side view",
"maxLength": 200,
"description": "Alternative text of the photo, up to 200 characters. Optional: when empty a storefront should use the product name."
},
"url": {
"type": "string",
"format": "uri"
},
"name": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"size": {
"type": "integer",
"maximum": 9007199254740991,
"exclusiveMinimum": 0
},
"pathname": {
"type": "string",
"minLength": 1
},
"uploadedAt": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
},
"contentType": {
"enum": [
"image/jpeg",
"image/png",
"image/webp"
],
"type": "string"
}
},
"additionalProperties": false
},
"maxItems": 10,
"description": "The product's photos as { url, alt }, at most 10; the first is the main photo. On an update the list you send replaces the whole set. An entry whose url equals a photo the product already has keeps that stored file and takes only the caption (alt) you send, so sending back what you read never downgrades a stored photo."
},
"status": {
"enum": [
"draft",
"active",
"archived"
],
"type": "string",
"default": "draft"
},
"videos": {
"type": "array",
"items": {
"type": "object",
"required": [
"url"
],
"properties": {
"url": {
"type": "string",
"format": "uri"
}
}
},
"default": [],
"example": [
{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
],
"maxItems": 5,
"description": "Video links for the product page (YouTube, Vimeo or a direct file), https only, at most 5. Links, not uploads. On update, sending the field replaces the whole list."
},
"weight": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"brandId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
]
},
"pattern": {
"anyOf": [
{
"type": "string",
"maxLength": 80,
"minLength": 1
},
{
"type": "null"
}
]
},
"ageGroup": {
"anyOf": [
{
"enum": [
"newborn",
"infant",
"toddler",
"kids",
"adult"
],
"type": "string"
},
{
"type": "null"
}
]
},
"material": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
]
},
"sizeType": {
"anyOf": [
{
"type": "string",
"maxLength": 40,
"minLength": 1
},
{
"type": "null"
}
]
},
"condition": {
"anyOf": [
{
"enum": [
"new",
"used",
"refurbished"
],
"type": "string"
},
{
"type": "null"
}
]
},
"costPrice": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
],
"description": "Purchase price per unit, in costCurrency. Ignored for a bundle: its cost is the sum of its components' costs when all are known and in one currency."
},
"categoryId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
]
},
"sizeSystem": {
"anyOf": [
{
"enum": [
"AU",
"BR",
"CN",
"DE",
"EU",
"FR",
"IT",
"JP",
"MEX",
"UK",
"US"
],
"type": "string"
},
{
"type": "null"
}
]
},
"supplierId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
]
},
"weightUnit": {
"anyOf": [
{
"enum": [
"kg",
"g",
"lb",
"oz"
],
"type": "string"
},
{
"type": "null"
}
]
},
"bundleItems": {
"type": "array",
"items": {
"type": "object",
"required": [
"productId",
"quantity"
],
"properties": {
"quantity": {
"type": "integer",
"maximum": 9007199254740991,
"exclusiveMinimum": 0
},
"productId": {
"type": "string",
"maxLength": 160,
"minLength": 1
}
},
"additionalProperties": false
},
"default": [],
"description": "Components of a bundle (type bundle only): simple, non-archived products of the bundle's warehouse, each listed once. Selling the bundle deducts these components; the bundle's stock is how many whole bundles they make. On update, sending it replaces the whole composition."
},
"description": {
"anyOf": [
{
"type": "string",
"maxLength": 2000
},
{
"type": "null"
}
]
},
"warehouseId": {
"anyOf": [
{
"type": "string",
"maxLength": 160,
"minLength": 1
},
{
"type": "null"
}
]
},
"costCurrency": {
"anyOf": [
{
"type": "string",
"pattern": "^[A-Z]{3}$"
},
{
"type": "null"
}
]
},
"dimensionUnit": {
"anyOf": [
{
"enum": [
"cm",
"mm",
"in"
],
"type": "string"
},
{
"type": "null"
}
]
},
"compareAtPrice": {
"anyOf": [
{
"anyOf": [
{
"type": "number"
},
{
"type": "string",
"minLength": 1
}
]
},
{
"type": "null"
}
]
},
"productGroupId": {
"anyOf": [
{
"type": "string",
"maxLength": 120,
"minLength": 1
},
{
"type": "null"
}
]
},
"trackInventory": {
"type": "boolean",
"default": false,
"description": "Whether the product counts units. Ignored for a bundle: it tracks stock exactly when one of its components does."
}
},
"additionalProperties": false
}| Filter to activities linked to this company id (from search_companies). |
| completed | string | Filter by completion: "true" only completed, "false" only open. Omit for both. |
| contactId | string | Filter to activities linked to this contact id (from search_contacts). |
| assignedTo | string | Filter to activities assigned to this workspace member's user id. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"q": {
"type": "string",
"maxLength": 255,
"description": "Free-text search over the activity title. Omit for no text filter."
},
"page": {
"type": "integer",
"default": 1,
"maximum": 9007199254740991,
"description": "1-based page number of results to return. Default 1.",
"exclusiveMinimum": 0
},
"type": {
"enum": [
"task",
"call",
"meeting",
"email",
"note"
],
"type": "string",
"description": "Filter by activity type. Omit for any. Allowed: task, call, meeting, email, note."
},
"dealId": {
"type": "string",
"description": "Filter to activities linked to this deal id (from search_deals)."
},
"leadId": {
"type": "string",
"description": "Filter to activities linked to this lead id (from search_leads)."
},
"overdue": {
"enum": [
"true",
"false"
],
"type": "string",
"description": "Set \"true\" to return only overdue activities (past due date, not completed)."
},
"perPage": {
"type": "integer",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Number of activities per page (1-100). Default 20."
},
"companyId": {
"type": "string",
"description": "Filter to activities linked to this company id (from search_companies)."
},
"completed": {
"enum": [
"true",
"false"
],
"type": "string",
"description": "Filter by completion: \"true\" only completed, \"false\" only open. Omit for both."
},
"contactId": {
"type": "string",
"description": "Filter to activities linked to this contact id (from search_contacts)."
},
"assignedTo": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "Filter to activities assigned to this workspace member's user id."
}
},
"additionalProperties": false
}| sortDir | string | Sort direction by lifetime value. Default desc (highest first). |
| wonDealsMin | integer | Only customers with at least this many won deals (orders are not counted here). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"q": {
"type": "string",
"maxLength": 255,
"description": "Free-text search over the customer company name. Omit for no text filter."
},
"ltv": {
"enum": [
"lt10k",
"10k50k",
"gt50k"
],
"type": "string",
"description": "Filter by lifetime-value bucket. Omit for any. Allowed: lt10k, 10k50k, gt50k."
},
"page": {
"type": "integer",
"default": 1,
"maximum": 9007199254740991,
"description": "1-based page number of results to return. Default 1.",
"exclusiveMinimum": 0
},
"health": {
"enum": [
"healthy",
"at_risk",
"churned"
],
"type": "string",
"description": "Filter by customer health. Omit for any. Allowed: healthy, at_risk, churned."
},
"ownerId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "Filter to customers owned by this workspace member's user id."
},
"perPage": {
"type": "integer",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Number of customers per page (1-100). Default 25."
},
"sortDir": {
"enum": [
"asc",
"desc"
],
"type": "string",
"default": "desc",
"description": "Sort direction by lifetime value. Default desc (highest first)."
},
"wonDealsMin": {
"type": "integer",
"maximum": 9007199254740991,
"minimum": 1,
"description": "Only customers with at least this many won deals (orders are not counted here)."
}
},
"additionalProperties": false
}| sortDir | string | Sort direction by lifetime value. Default desc (highest first). |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"q": {
"type": "string",
"maxLength": 255,
"description": "Free-text search over the person's first name, last name, email and phone. Omit for no text filter."
},
"ltv": {
"enum": [
"lt10k",
"10k50k",
"gt50k"
],
"type": "string",
"description": "Filter by lifetime-value bucket. Omit for any. Allowed: lt10k, 10k50k, gt50k."
},
"page": {
"type": "integer",
"default": 1,
"maximum": 9007199254740991,
"description": "1-based page number of results to return. Default 1.",
"exclusiveMinimum": 0
},
"health": {
"enum": [
"healthy",
"at_risk",
"churned"
],
"type": "string",
"description": "Filter by customer health. Omit for any. Allowed: healthy, at_risk, churned."
},
"repeat": {
"anyOf": [
{
"type": "boolean"
},
{
"enum": [
"true",
"false"
],
"type": "string"
}
],
"description": "true = only people with two or more purchases; false or omitted = everyone."
},
"perPage": {
"type": "integer",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Number of people per page (1-100). Default 25."
},
"sortDir": {
"enum": [
"asc",
"desc"
],
"type": "string",
"default": "desc",
"description": "Sort direction by lifetime value. Default desc (highest first)."
}
},
"additionalProperties": false
}| limit |
| integer |
| Posts per page, 1–50. Default 20. |
| channel | string | Only this network's posts: instagram, facebook, telegram, linkedin, threads or viber. Omit for all channels. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"to": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "Last day to include, YYYY-MM-DD, inclusive, on the workspace's clock. Omit for no upper bound."
},
"from": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}$",
"description": "First day to include, YYYY-MM-DD, a calendar day on the workspace's clock. Omit for no lower bound."
},
"page": {
"type": "integer",
"default": 1,
"maximum": 200,
"minimum": 1,
"description": "Page number, newest posts first. Default 1."
},
"limit": {
"type": "integer",
"default": 20,
"maximum": 50,
"minimum": 1,
"description": "Posts per page, 1–50. Default 20."
},
"channel": {
"enum": [
"instagram",
"facebook",
"telegram",
"linkedin",
"threads",
"viber"
],
"type": "string",
"description": "Only this network's posts: instagram, facebook, telegram, linkedin, threads or viber. Omit for all channels."
}
}
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"rule",
"scope"
],
"properties": {
"rule": {
"oneOf": [
{
"type": "object",
"required": [
"op",
"percent",
"rounding"
],
"properties": {
"op": {
"type": "string",
"const": "percent",
"description": "Raise or lower by a percent."
},
"percent": {
"type": "number",
"maximum": 900,
"minimum": -90,
"description": "Percent change: 10 raises by 10%, -10 lowers by 10%. Between -90 and 900."
},
"rounding": {
"enum": [
"cents",
"whole",
"nine",
"tens"
],
"type": "string",
"description": "How the new price is rounded: cents (to 2 decimals), whole (up to the next whole unit), nine (up to the next price ending in 9, e.g. 644.80 -> 649) or tens (up to the next ten). Everything except cents rounds UP."
}
}
},
{
"type": "object",
"required": [
"amount",
"op"
],
"properties": {
"op": {
"type": "string",
"const": "fixed",
"description": "Set one price for every product in scope."
},
"amount": {
"type": "string",
"pattern": "^\\d{1,10}(\\.\\d{1,2})?$",
"description": "One price for EVERY product in scope, as a decimal string, e.g. '1290' or '1290.50'. Rare for a whole category — check the preview."
}
}
},
{
"type": "object",
"required": [
"markupPercent",
"op",
"rounding"
],
"properties": {
"op": {
"type": "string",
"const": "fromCost",
"description": "Price = purchase cost plus a markup."
},
"rounding": {
"enum": [
"cents",
"whole",
"nine",
"tens"
],
"type": "string",
"description": "How the new price is rounded: cents (to 2 decimals), whole (up to the next whole unit), nine (up to the next price ending in 9, e.g. 644.80 -> 649) or tens (up to the next ten). Everything except cents rounds UP."
},
"markupPercent": {
"type": "number",
"maximum": 900,
"minimum": -90,
"description": "Markup over the purchase cost, in percent: 40 means price = cost x 1.4. The cost is crossed into the price's currency at the rates the workspace states; a product without a cost or a rate is skipped."
}
}
},
{
"type": "object",
"required": [
"op",
"percent",
"rounding"
],
"properties": {
"op": {
"type": "string",
"const": "discount",
"description": "Start a sale: the old price becomes the current price (or stays, if a higher one is set) and the price drops by the percent."
},
"percent": {
"type": "number",
"maximum": 90,
"minimum": 1,
"description": "Discount in percent, 1 to 90."
},
"rounding": {
"enum": [
"cents",
"whole",
"nine",
"tens"
],
"type": "string",
"description": "How the new price is rounded: cents (to 2 decimals), whole (up to the next whole unit), nine (up to the next price ending in 9, e.g. 644.80 -> 649) or tens (up to the next ten). Everything except cents rounds UP."
}
}
},
{
"type": "object",
"required": [
"op"
],
"properties": {
"op": {
"type": "string",
"const": "endDiscount",
"description": "End a sale: the price returns to the old price and the old price is cleared."
}
}
},
{
"type": "object",
"required": [
"op",
"percent",
"rounding"
],
"properties": {
"op": {
"type": "string",
"const": "compareAtMarkup",
"description": "Set the old (struck-through) price above the current price by a percent. Does not change the price."
},
"percent": {
"type": "number",
"maximum": 900,
"minimum": 1,
"description": "How far above the price the old price sits, in percent."
},
"rounding": {
"enum": [
"cents",
"whole",
"nine",
"tens"
],
"type": "string",
"description": "How the new price is rounded: cents (to 2 decimals), whole (up to the next whole unit), nine (up to the next price ending in 9, e.g. 644.80 -> 649) or tens (up to the next ten). Everything except cents rounds UP."
}
}
},
{
"type": "object",
"required": [
"op"
],
"properties": {
"op": {
"type": "string",
"const": "compareAtClear",
"description": "Remove the old price. Does not change the price."
}
}
}
],
"description": "HOW prices move. The target 'cost' accepts only op 'percent'. Pick the one that matches the request: a percent change, a fixed price, a markup over cost, a discount (and its end), or the old price."
},
"scope": {
"oneOf": [
{
"type": "object",
"required": [
"ids",
"kind"
],
"properties": {
"ids": {
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"description": "A product id from search_products."
},
"maxItems": 100,
"minItems": 1,
"description": "Explicit product ids actually fetched with search_products, at most 100."
},
"kind": {
"type": "string",
"const": "ids",
"description": "Specific products you fetched. Prefer a container."
}
}
},
{
"type": "object",
"required": [
"id",
"kind"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The warehouse id returned by list_warehouses."
},
"kind": {
"type": "string",
"const": "warehouse",
"description": "Every product of one warehouse."
}
}
},
{
"type": "object",
"required": [
"id",
"kind"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The category id returned by list_categories."
},
"kind": {
"type": "string",
"const": "category",
"description": "Every product of one category."
},
"includeSubcategories": {
"type": "boolean",
"description": "true to include every sub-category under it ('everything under Backpacks'); omit it for exactly that one category. Never widen it unless the person means the whole branch."
}
}
},
{
"type": "object",
"required": [
"id",
"kind"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The brand id returned by list_brands."
},
"kind": {
"type": "string",
"const": "brand",
"description": "Every product of one brand."
}
}
},
{
"type": "object",
"required": [
"id",
"kind"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The supplier id returned by list_suppliers."
},
"kind": {
"type": "string",
"const": "supplier",
"description": "Every product of one supplier."
}
}
},
{
"type": "object",
"required": [
"id",
"kind"
],
"properties": {
"id": {
"type": "string",
"minLength": 1,
"description": "The model id from get_product (its model block)."
},
"kind": {
"type": "string",
"const": "model",
"description": "Every article of one product model."
}
}
}
],
"description": "WHICH products. Prefer a named container (category, brand, supplier, warehouse) when the person says 'all products of …' — it is read back by name in the preview. There is no free filter: a request like 'everything cheaper than 100' is not a scope; find the products first and send their ids."
},
"target": {
"oneOf": [
{
"type": "object",
"required": [
"field"
],
"properties": {
"field": {
"type": "string",
"const": "price",
"description": "Change the selling price."
},
"currency": {
"anyOf": [
{
"type": "string",
"pattern": "^[A-Z]{3}$"
},
{
"type": "null"
}
],
"default": null,
"description": "null (default) = the product's own price in the workspace currency. A 3-letter code = that currency's row of the product's price list (the workspace currency itself means null)."
}
}
},
{
"type": "object",
"required": [
"field"
],
"properties": {
"field": {
"type": "string",
"const": "cost",
"description": "Change the purchase cost (percent only). Not published to channels."
}
}
}
],
"default": {
"field": "price",
"currency": null
},
"description": "WHICH number moves. Omit it to change the product's own selling price. Use {field:'price', currency:'EUR'} for the euro price list, {field:'cost'} for the purchase cost."
}
}
}| productIds | array | Product ids (1 to 25) to send to Google right now instead of the whole catalog. Use it to get a fixed product to Google at once. Each id must be an active member of the Google channel; others come back as notOnChannel, products the readiness rule withholds as blocked (with the reason), and Google's refusals as failed (with Google's own message). Omit it to push the whole catalog in priority order. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"adapterId": {
"type": "string",
"minLength": 1,
"description": "The Google Merchant connection to push (adapter id, listed by get_marketplace for google_merchant). Omit it when the workspace has exactly one Google Merchant connection — the server picks it; with several connections the call is refused until one is named."
},
"productIds": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"maxItems": 25,
"minItems": 1,
"description": "Product ids (1 to 25) to send to Google right now instead of the whole catalog. Use it to get a fixed product to Google at once. Each id must be an active member of the Google channel; others come back as notOnChannel, products the readiness rule withholds as blocked (with the reason), and Google's refusals as failed (with Google's own message). Omit it to push the whole catalog in priority order."
}
}
}| object |
| Ask the CRM to validate and calculate this promo code. Do not supply promoCode, discountAmount or shippingThresholdAmount alongside it. An optional expectedTotal refuses a changed quote; the server always owns the actual discount. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"currency",
"items",
"promotion"
],
"properties": {
"items": {
"type": "array",
"items": {
"type": "object",
"required": [
"productName",
"quantity",
"unitPrice"
],
"properties": {
"sku": {
"type": "string",
"maxLength": 120,
"description": "Product SKU snapshot (from search_products). Optional."
},
"discount": {
"type": "number",
"default": 0,
"maximum": 100,
"minimum": 0,
"description": "Percentage discount on this line (0-100). Default 0."
},
"quantity": {
"type": "integer",
"maximum": 9007199254740991,
"description": "Quantity ordered (integer, at least 1).",
"exclusiveMinimum": 0
},
"unitPrice": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d+(\\.\\d{1,2})?$"
},
{
"type": "number",
"minimum": 0
}
],
"description": "Price per unit in the order currency, as a decimal (e.g. 199.99). Snapshotted onto the line."
},
"productName": {
"type": "string",
"maxLength": 255,
"minLength": 1,
"description": "Line item name, snapshotted onto the order. Use search_products to quote a real catalog product's name. Required."
}
},
"additionalProperties": false
},
"maxItems": 100,
"minItems": 1,
"description": "Order line items (1-100). Each snapshots productName/sku/unitPrice."
},
"currency": {
"type": "string",
"pattern": "^[A-Z]{3}$",
"description": "Required ISO 4217 currency code (uppercase) of the cart lines; no default and no conversion."
},
"customer": {
"type": "object",
"properties": {
"email": {
"type": "string",
"format": "email",
"pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
"maxLength": 255
},
"phone": {
"type": "string",
"maxLength": 50,
"minLength": 1
},
"lastName": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"firstName": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"externalId": {
"type": "string",
"maxLength": 160,
"minLength": 1
},
"shippingAddress": {
"type": "object",
"required": [
"city",
"country",
"line1"
],
"properties": {
"city": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"line1": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"line2": {
"type": "string",
"maxLength": 255,
"minLength": 1
},
"region": {
"type": "string",
"maxLength": 120,
"minLength": 1
},
"country": {
"type": "string",
"maxLength": 2,
"minLength": 2
},
"postalCode": {
"type": "string",
"maxLength": 32,
"minLength": 1
}
},
"additionalProperties": false
}
},
"description": "Optional buyer snapshot (name/email/phone, or a storefront customer externalId). Omit for an anonymous order.",
"additionalProperties": false
},
"delivery": {
"type": "object",
"properties": {
"cod": {
"type": "boolean",
"description": "True when the buyer pays on delivery (cash on delivery)."
},
"flat": {
"type": "string",
"maxLength": 35,
"description": "Apartment or office number for courier delivery."
},
"phone": {
"type": "string",
"maxLength": 50,
"description": "Recipient phone, when it differs from the buyer's own contact phone."
},
"branch": {
"type": "string",
"maxLength": 200,
"description": "Branch or parcel locker as the buyer named it, e.g. \"відділення №5\" or \"поштомат 12345\". Free text: the CRM resolves it against the live branch list of the carrier when creating a waybill."
},
"method": {
"enum": [
"branch",
"courier",
"pickup"
],
"type": "string",
"description": "How the parcel reaches the buyer: \"branch\" (carrier office/locker), \"courier\" (to the address) or \"pickup\" (buyer collects from you)."
},
"carrier": {
"type": "string",
"maxLength": 120,
"description": "Carrier slug the buyer chose, from GET /capabilities (e.g. \"nova_poshta\", \"ukrposhta\", \"pickup\"). This is a preference, not a dispatch — the shipment endpoint still records what actually ships."
},
"cityRef": {
"type": "string",
"maxLength": 64,
"description": "The carrier's own identifier for the destination city, as returned by GET /api/v1/carriers/{carrier}/cities. Required alongside branchRef or streetRef for a waybill to be created from the order alone."
},
"comment": {
"type": "string",
"maxLength": 1000,
"description": "Delivery note from the buyer, e.g. \"дзвонити після 18:00\". Not the order notes."
},
"building": {
"type": "string",
"maxLength": 35,
"description": "House number for courier delivery, structured rather than inside the address line because carriers validate it on its own (Nova Poshta accepts up to 11 characters matching digits plus an optional Cyrillic letter or block, e.g. \"12Б\" or \"12/4\")."
},
"branchRef": {
"type": "string",
"maxLength": 64,
"description": "The carrier's own identifier for the branch or parcel locker, as returned by GET /api/v1/carriers/{carrier}/warehouses. The same value the shipment-label endpoint calls warehouseRef. Sent, this removes all guessing; omitted, the CRM falls back to matching `branch` as text."
},
"streetRef": {
"type": "string",
"maxLength": 64,
"description": "The carrier's own identifier for the street, as returned by GET /api/v1/carriers/{carrier}/streets. Courier delivery only; pair it with `building`."
},
"recipientName": {
"type": "string",
"maxLength": 200,
"description": "Who receives the parcel, when that is not the buyer (a gift, an office)."
}
},
"description": "How the buyer asked to receive the order: carrier, branch/courier/pickup, branch text, recipient, cash-on-delivery and a delivery note. This is the buyer's choice at checkout — it does not dispatch anything. Record what actually ships with POST /orders/{externalId}/shipments.",
"additionalProperties": false
},
"promotion": {
"type": "object",
"required": [
"code"
],
"properties": {
"code": {
"type": "string",
"pattern": "^[A-Za-z0-9][A-Za-z0-9_-]{2,63}$",
"description": "CRM-managed promo code, 3–64 letters, digits, hyphens or underscores; case-insensitive. Must be enabled for this connection's source; a personal or capture code also needs the buyer email it was issued to."
},
"expectedTotal": {
"type": "string",
"pattern": "^\\d{1,10}(?:\\.\\d{1,2})?$",
"description": "Net merchandise total the buyer was shown, as a decimal string with up to two decimals (for example \"199.90\"), in the order currency. If the CRM now calculates a different amount the request is refused with price_changed."
}
},
"description": "Ask the CRM to validate and calculate this promo code. Do not supply promoCode, discountAmount or shippingThresholdAmount alongside it. An optional expectedTotal refuses a changed quote; the server always owns the actual discount.",
"additionalProperties": false
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"q": {
"type": "string",
"maxLength": 255,
"description": "Free-text search over name, email and company. Omit for no text filter."
},
"tag": {
"type": "string",
"maxLength": 80,
"minLength": 1,
"description": "Filter to contacts carrying this tag. Omit for any tag."
},
"page": {
"type": "integer",
"default": 1,
"maximum": 9007199254740991,
"description": "1-based page number of results to return. Default 1.",
"exclusiveMinimum": 0
},
"sortBy": {
"enum": [
"name",
"email",
"createdAt"
],
"type": "string",
"default": "name",
"description": "Field to sort by. Default name. Allowed: name, email, createdAt."
},
"ownerId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "Filter to contacts owned by this workspace member's user id."
},
"perPage": {
"type": "integer",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Number of contacts per page (1-100). Default 25."
},
"sortDir": {
"enum": [
"asc",
"desc"
],
"type": "string",
"default": "asc",
"description": "Sort direction. Default asc."
},
"companyId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "Filter to contacts at this company id (from search_companies)."
}
},
"additionalProperties": false
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"q": {
"type": "string",
"maxLength": 255,
"description": "Free-text search over the deal title. Omit for no text filter."
},
"page": {
"type": "integer",
"default": 1,
"maximum": 9007199254740991,
"description": "1-based page number of results to return. Default 1.",
"exclusiveMinimum": 0
},
"stale": {
"enum": [
"true",
"false"
],
"type": "string",
"description": "Set \"true\" to return only stale deals (past their next-action date or long untouched)."
},
"ownerId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "Filter to deals owned by this workspace member's user id."
},
"perPage": {
"type": "integer",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Number of deals per page (1-100). Default 25."
},
"stageId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "Filter to deals in this pipeline stage id (from list_pipeline_stages)."
},
"companyId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "Filter to deals linked to this company id (from search_companies)."
},
"contactId": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "Filter to deals linked to this contact id (from search_contacts)."
}
},
"additionalProperties": false
}| perPage | integer | Number of results per page (1-100). Default 20. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"q": {
"type": "string",
"maxLength": 255,
"description": "Free-text search over lead name, email, phone, or company. Omit for no text filter."
},
"to": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
"description": "Only leads created at or before this ISO 8601 timestamp (e.g. 2026-02-28T23:59:59Z)."
},
"from": {
"type": "string",
"format": "date-time",
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
"description": "Only leads created at or after this ISO 8601 timestamp (e.g. 2026-01-31T00:00:00Z)."
},
"page": {
"type": "integer",
"default": 1,
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based page number of results to return. Default 1."
},
"stale": {
"anyOf": [
{
"type": "boolean"
},
{
"enum": [
"true",
"false"
],
"type": "string"
}
],
"description": "Set true to return only stale leads: not unqualified/converted and either past their next-action date or untouched for more than 7 days."
},
"source": {
"type": "string",
"maxLength": 80,
"description": "Filter by lead source key (e.g. website, referral, telegram). Use list_lead_sources to see the workspace's keys. Omit for all sources."
},
"status": {
"enum": [
"new",
"contacted",
"qualified",
"unqualified",
"converted"
],
"type": "string",
"description": "Filter by lead status. Omit to return every status. Allowed: new, contacted, qualified, unqualified, converted."
},
"perPage": {
"type": "integer",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Number of results per page (1-100). Default 20."
}
}
}| type | string | Filter by product type. Empty for any; "simple" or "bundle". |
| color | string | Filter to products whose color equals this value, ignoring letter case (the product's own color field, not a free-form attribute). Empty means any color. |
| status | string | Filter by catalog status. Empty keeps the storefront default of active only. Use "draft" to find products waiting to be reviewed (marketplace imports and unknown SKUs from orders land there), or "any" for every status. |
| brandId | string | Filter to one brand by its id. Empty string means any brand. |
| inStock | string | Set "true" to return only products with stock available. Empty means include out-of-stock. |
| perPage | integer | Number of products per page (1-100). Default 20. |
| maxPrice | number | Only products priced at or below this amount (workspace currency). |
| minPrice | number | Only products priced at or above this amount (workspace currency). |
| categoryId | string | Filter to one category by its id. Empty string means any category. |
| collection | string | Filter to the products of one collection, by its slug from GET /collections. Only a collection that is visible and in season matches — an unknown, hidden or out-of-season slug is reported as not found, exactly like GET /collections/{slug}. Empty means no collection filter. |
| stockState | string | Filter by stock state, for products that track inventory. "low" returns products at or under their reorder threshold; "out" returns products with nothing left. Empty applies no stock-state filter. |
| supplierId | string | Only products bought from this supplier — an id from list_suppliers — or "none" for products with no supplier. Omit for any supplier. |
| warehouseId | string | Filter to products in one warehouse by its id, from the warehouse list. Use "none" for products assigned to no warehouse — they match no id, so nothing else surfaces them. Empty means any warehouse. An id absent from this workspace is reported as an error, never as an empty result. |
| supplierStock | string | Only products whose supplier feed (e.g. Sipec) last reported this: in_stock (quantity above zero), arriving (none now, a restock date given), out_of_stock (none, no date), unknown (the supplier has not said). Omit for any. |
| productGroupId | string | Filter to the variants of one model: products whose productGroupId equals this value exactly. It is the merchant's (or supplier's) own model code, so letter case is part of it. Use it to render the other colours and sizes of the product a buyer is looking at. Empty means any model. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"q": {
"type": "string",
"default": "",
"maxLength": 200,
"description": "Free-text search over product name and SKU. Empty for no text filter."
},
"tag": {
"type": "string",
"default": "",
"maxLength": 100,
"description": "Filter to products carrying this tag. Empty means any tag."
},
"page": {
"type": "integer",
"default": 1,
"maximum": 9007199254740991,
"minimum": 1,
"description": "1-based page number of results to return. Default 1."
},
"size": {
"type": "string",
"default": "",
"maxLength": 60,
"description": "Filter to products whose size equals this value, ignoring letter case (the product's own size field). Empty means any size."
},
"sort": {
"enum": [
"",
"name_asc",
"name_desc",
"price_asc",
"price_desc",
"newest",
"popular"
],
"type": "string",
"default": "",
"description": "Sort order. Empty sorts by name. Allowed: name_asc, name_desc, price_asc, price_desc, newest, popular — popular ranks by units sold in confirmed, processing, shipped or delivered orders over the last 90 days. Ties break by name."
},
"type": {
"enum": [
"",
"simple",
"bundle"
],
"type": "string",
"default": "",
"description": "Filter by product type. Empty for any; \"simple\" or \"bundle\"."
},
"color": {
"type": "string",
"default": "",
"maxLength": 80,
"description": "Filter to products whose color equals this value, ignoring letter case (the product's own color field, not a free-form attribute). Empty means any color."
},
"status": {
"enum": [
"",
"draft",
"active",
"archived",
"any"
],
"type": "string",
"default": "",
"description": "Filter by catalog status. Empty keeps the storefront default of active only. Use \"draft\" to find products waiting to be reviewed (marketplace imports and unknown SKUs from orders land there), or \"any\" for every status."
},
"brandId": {
"type": "string",
"default": "",
"maxLength": 40,
"description": "Filter to one brand by its id. Empty string means any brand."
},
"inStock": {
"enum": [
"",
"true"
],
"type": "string",
"default": "",
"description": "Set \"true\" to return only products with stock available. Empty means include out-of-stock."
},
"perPage": {
"type": "integer",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Number of products per page (1-100). Default 20."
},
"maxPrice": {
"type": "number",
"minimum": 0,
"description": "Only products priced at or below this amount (workspace currency)."
},
"minPrice": {
"type": "number",
"minimum": 0,
"description": "Only products priced at or above this amount (workspace currency)."
},
"categoryId": {
"type": "string",
"default": "",
"maxLength": 40,
"description": "Filter to one category by its id. Empty string means any category."
},
"collection": {
"type": "string",
"default": "",
"maxLength": 120,
"description": "Filter to the products of one collection, by its slug from GET /collections. Only a collection that is visible and in season matches — an unknown, hidden or out-of-season slug is reported as not found, exactly like GET /collections/{slug}. Empty means no collection filter."
},
"stockState": {
"enum": [
"",
"low",
"out"
],
"type": "string",
"default": "",
"description": "Filter by stock state, for products that track inventory. \"low\" returns products at or under their reorder threshold; \"out\" returns products with nothing left. Empty applies no stock-state filter."
},
"supplierId": {
"type": "string",
"minLength": 1,
"description": "Only products bought from this supplier — an id from list_suppliers — or \"none\" for products with no supplier. Omit for any supplier."
},
"warehouseId": {
"type": "string",
"default": "",
"maxLength": 40,
"description": "Filter to products in one warehouse by its id, from the warehouse list. Use \"none\" for products assigned to no warehouse — they match no id, so nothing else surfaces them. Empty means any warehouse. An id absent from this workspace is reported as an error, never as an empty result."
},
"supplierStock": {
"enum": [
"in_stock",
"arriving",
"out_of_stock",
"unknown"
],
"type": "string",
"description": "Only products whose supplier feed (e.g. Sipec) last reported this: in_stock (quantity above zero), arriving (none now, a restock date given), out_of_stock (none, no date), unknown (the supplier has not said). Omit for any."
},
"productGroupId": {
"type": "string",
"default": "",
"maxLength": 120,
"description": "Filter to the variants of one model: products whose productGroupId equals this value exactly. It is the merchant's (or supplier's) own model code, so letter case is part of it. Use it to render the other colours and sizes of the product a buyer is looking at. Empty means any model."
}
}
}| compareAtPrice | any | The old (struck-through) price on this channel, higher than price; omit or null for none. Ignored when price is null. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"currency",
"id",
"platform",
"price"
],
"properties": {
"id": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The product id returned by search_products or get_product — never a SKU or a name."
},
"price": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d+(\\.\\d{1,2})?$"
},
{
"type": "null"
}
],
"description": "The price this ONE channel gets, instead of the product's ordinary price in that currency, as a decimal string above zero. null removes the override — the channel then gets the ordinary price again. Send only an amount the person stated; never a converted or guessed value."
},
"currency": {
"type": "string",
"pattern": "^[A-Z]{3}$",
"description": "The currency the channel sells in (uppercase 3-letter ISO code). get_product_pricing and the channel's readiness show which currency a channel uses."
},
"platform": {
"enum": [
"prom",
"rozetka",
"woocommerce",
"shopify",
"olx",
"amazon",
"ebay",
"google_merchant"
],
"type": "string",
"description": "The sales channel this price is for: prom, rozetka, woocommerce, shopify, olx, amazon, ebay or google_merchant."
},
"compareAtPrice": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d+(\\.\\d{1,2})?$"
},
{
"type": "null"
}
],
"description": "The old (struck-through) price on this channel, higher than price; omit or null for none. Ignored when price is null."
}
}
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"fulfillmentPolicyId",
"productId"
],
"properties": {
"productId": {
"type": "string",
"minLength": 1,
"description": "A product id returned by search_products."
},
"marketplaceId": {
"enum": [
"EBAY_US",
"EBAY_GB",
"EBAY_DE",
"EBAY_AT",
"EBAY_BE",
"EBAY_FR",
"EBAY_IT",
"EBAY_NL",
"EBAY_ES",
"EBAY_IE",
"EBAY_PL",
"EBAY_CH",
"EBAY_CA",
"EBAY_AU"
],
"type": "string",
"description": "An eBay MARKETPLACE id such as EBAY_IT — never the eBay connection id. Omit it when the eBay connection sells on one site; the server uses that one. Required when the connection sells on several, unless the product already has an eBay offer (its own site is then used)."
},
"fulfillmentPolicyId": {
"anyOf": [
{
"type": "string",
"pattern": "^[A-Za-z0-9_-]+$",
"maxLength": 64,
"minLength": 1
},
{
"type": "null"
}
],
"description": "A fulfillmentPolicyId from list_ebay_fulfillment_policies, for the same marketplace. null removes the product's own choice so the connection default (then eBay's first policy) applies."
}
}
}{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id"
],
"properties": {
"id": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The product id returned by search_products or get_product."
},
"prices": {
"type": "array",
"items": {
"type": "object",
"required": [
"currency",
"price"
],
"properties": {
"price": {
"type": "string",
"pattern": "^\\d+(\\.\\d{1,2})?$"
},
"currency": {
"type": "string",
"maxLength": 3,
"minLength": 3
},
"compareAtPrice": {
"anyOf": [
{
"type": "string",
"pattern": "^\\d+(\\.\\d{1,2})?$"
},
{
"type": "null"
}
]
}
}
},
"maxItems": 10,
"description": "Price-list rows to add or update, one per currency (uppercase 3-letter ISO code, e.g. EUR), an amount greater than 0 — the price the product sells at in that currency on every channel that trades in it. Refused for the product's own workspace currency — use update_product's price field for that one. Never a converted or guessed value: send exactly the amount the user gave for that market. Not a per-channel price: a price for ONE channel only is set_product_channel_price. Omit it when you only remove currencies."
},
"remove": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[A-Z]{3}$"
},
"maxItems": 10,
"description": "Currencies whose price-list row to REMOVE (uppercase 3-letter ISO code). The product stops being sold in that currency on channels that trade in it. The product's own workspace currency cannot be removed here, and a currency named in prices cannot also be removed. A currency with no row is ignored."
}
}
}| pattern | string | Pattern. |
| keywords | array | Search keywords in this language; replaces the list. |
| material | string | Material. |
| attributes | object | Translated characteristics, keyed by the characteristic's BASE name exactly as the product shows it (see get_product). Each key is merged into what is stored; other characteristics and languages stay. A name the product does not have is refused. |
| description | string | The description in this language. An empty string clears it. |
{
"type": "object",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"required": [
"id",
"locale"
],
"properties": {
"id": {
"type": "string",
"maxLength": 160,
"minLength": 1,
"description": "The product id returned by search_products or get_product."
},
"name": {
"type": "string",
"maxLength": 255,
"description": "The product title in this language. eBay shows at most 80 characters. An empty string clears it, so the base name publishes."
},
"color": {
"type": "string",
"maxLength": 80,
"description": "Colour name."
},
"locale": {
"enum": [
"uk",
"ru",
"en",
"pl",
"de",
"it",
"fr",
"es",
"pt",
"nl",
"cs",
"sk",
"hu",
"ro",
"bg",
"lt",
"lv",
"et",
"tr"
],
"type": "string",
"description": "The language to write, as an ISO 639-1 code — for a marketplace, the site's own language (it on ebay.it, de on ebay.de, uk or ru for Prom and Rozetka)."
},
"pattern": {
"type": "string",
"maxLength": 80,
"description": "Pattern."
},
"keywords": {
"type": "array",
"items": {
"type": "string",
"maxLength": 120
},
"maxItems": 20,
"description": "Search keywords in this language; replaces the list."
},
"material": {
"type": "string",
"maxLength": 120,
"description": "Material."
},
"attributes": {
"type": "object",
"description": "Translated characteristics, keyed by the characteristic's BASE name exactly as the product shows it (see get_product). Each key is merged into what is stored; other characteristics and languages stay. A name the product does not have is refused.",
"propertyNames": {
"type": "string",
"maxLength": 160,
"minLength": 1
},
"additionalProperties": {
"type": "object",
"properties": {
"name": {
"type": "string",
"maxLength": 160,
"description": "The characteristic's name in this language. An empty string clears it."
},
"value": {
"type": "string",
"maxLength": 500,
"description": "The characteristic's value in this language. An empty string clears it."
}
}
}
},
"description": {
"type": "string",
"maxLength": 20000,
"description": "The description in this language. An empty string clears it."
}
}
}