Skip to main content
Bit CRM REST API Documentation for Developers

Bit CRM Products API Documentation for Developers

Estimated reading: 12 minutes 23 views

The Bit CRM Products API lets you create, search, retrieve, and update products, and activate or deactivate them. Products are a Bit CRM Pro feature, these endpoints work only while the Pro plugin is active, and they use a different base URL than the rest of this reference:

https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1

Authentication, permissions, rate limiting, pagination, and response formats work exactly as described in Introduction & Authentication, only the base URL differs.

Product field keys

Create and update requests take product fields inside a systemDefinedFieldsValues object. All values are sent as strings, including price, tax_rate, and status. name and code are required.

  • name — required
  • code — required. The product code/SKU; must be unique, otherwise validation fails with Product Code/SKU must be unique!
  • typegoods (default) or service
  • brand — manufacturer / brand
  • description
  • price — unit price
  • cost_price
  • tax_rate — percentage
  • statustrue (Active, default) or false (Inactive)

Note: If you have defined custom fields for products, send their values in a separate customFieldsValues object alongside systemDefinedFieldsValues, keyed by field key — each entry carries the field’s field_id and its field_value. Custom field values are accepted on both create and update.

Note: The CRM’s remaining product endpoints (import, export, and the admin table-configuration endpoints) are internal-only and return bit_crm_endpoint_not_public to API-key callers.

Create a product

POST /products/store — requires capability bit_crm_product_create.

  • systemDefinedFieldsValues — object, required. Product fields (see above); name and code are required.
  • tagIds — array of integers, optional. IDs of existing product tags to attach.
  • newTagTitles — array of strings, optional. New tags to create and attach.
  • customFieldsValues — object, optional. Custom field values (see above).
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/store
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/store" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "systemDefinedFieldsValues": {
      "name": "Annual license",
      "code": "LIC-001",
      "type": "goods",
      "price": "400",
      "tax_rate": "10"
    },
    "customFieldsValues": {
      "warranty_period": {
        "field_id": 11,
        "field_value": "1 year"
      }
    },
    "newTagTitles": [
      "Software"
    ]
  }'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/store');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'systemDefinedFieldsValues' => [
            'name' => 'Annual license',
            'code' => 'LIC-001',
            'type' => 'goods',
            'price' => '400',
            'tax_rate' => '10',
        ],
        'customFieldsValues' => [
            'warranty_period' => [
                'field_id' => 11,
                'field_value' => '1 year',
            ],
        ],
        'newTagTitles' => [
            'Software',
        ],
    ]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/store', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({
    "systemDefinedFieldsValues": {
      "name": "Annual license",
      "code": "LIC-001",
      "type": "goods",
      "price": "400",
      "tax_rate": "10"
    },
    "customFieldsValues": {
      "warranty_period": {
        "field_id": 11,
        "field_value": "1 year"
      }
    },
    "newTagTitles": [
      "Software"
    ]
  }),
});
const result = await response.json();

Example response — data is the created product:

{
  "status": "success",
  "code": "SUCCESS",
  "data": {
    "id": 31,
    "name": "Annual license",
    "code": "LIC-001",
    "type": "goods",
    "price": 400,
    "tax_rate": 10,
    "status": true,
    "reference_uuid": "7a3e9d1c-5b2f-4c8a-9e6d-1f4b7c2a8e30",
    "created_by": 1,
    "created_at": "2026-08-05 10:30:00",
    "updated_at": "2026-08-05 10:30:00",
    "custom_fields_values": {
      "warranty_period": {
        "field_id": 11,
        "field_value": "1 year",
        "field_key": "warranty_period"
      }
    }
  }
}

Search products

POST /products/search — requires capability bit_crm_product_view.

  • page — integer, optional, minimum 1, default 1.
  • perPage — integer, optional, between 1 and 100, default 10.
  • searchTerm — string. Matches product name, description, and code. Send "" when not searching.
  • sortBy — string, optional, default id.
  • sortOrderasc or desc, optional, default desc.
  • tags — array of tag IDs, optional.
  • filters — object of field: value pairs, optional.
  • advancedFilterGroups — array, optional. Same shape as the CRM’s own filter UI.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/search
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/search" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"page": 1, "perPage": 10, "searchTerm": "license"}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/search');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['page' => 1, 'perPage' => 10, 'searchTerm' => 'license']),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/search', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"page": 1, "perPage": 10, "searchTerm": "license"}),
});
const result = await response.json();

Example response — the standard paginated object. Custom field values appear as flat columns on each row, named by field key. Numeric and boolean columns may come back as raw database strings on this endpoint:

{
  "status": "success",
  "code": "SUCCESS",
  "data": {
    "data": [
      {
        "id": 31,
        "name": "Annual license",
        "code": "LIC-001",
        "type": "goods",
        "price": "400.00",
        "status": "1",
        "warranty_period": "1 year",
        "created_at": "2026-08-05 10:30:00"
      }
    ],
    "pages": 1,
    "total": 1,
    "current_total": 1,
    "current_page": 1,
    "last_page": 1,
    "per_page": 10
  }
}

Retrieve a product

GET /products/{id} — requires capability bit_crm_product_view.

data holds every product field plus created_by_name and updated_by_name, the product’s tags (each {id, title, slug} — present only when the product has tags), and previous_id / next_id. Custom field values are merged in as top-level keys named by field key. Trashed products are not returned.

GET https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/31
  • Bash
  • PHP
  • JavaScript
curl "https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/31" \
  --user "your-username:YOUR API KEY"
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/31');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/31', {
  headers: { 'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY') },
});
const result = await response.json();

Update a product

POST /products/{id} — requires capability bit_crm_product_update.

Send the fields to change inside systemDefinedFieldsValues, and optionally customFieldsValues. Always include name and code — they are validated as required even when you are updating other fields.

POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/31
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/31" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "systemDefinedFieldsValues": {
      "name": "Annual license",
      "code": "LIC-001",
      "price": "450"
    }
  }'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/31');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode([
        'systemDefinedFieldsValues' => [
            'name' => 'Annual license',
            'code' => 'LIC-001',
            'price' => '450',
        ],
    ]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/31', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({
    "systemDefinedFieldsValues": {
      "name": "Annual license",
      "code": "LIC-001",
      "price": "450"
    }
  }),
});
const result = await response.json();

Example response — note that data is the confirmation string on this endpoint, not the updated product:

{
  "status": "success",
  "code": "SUCCESS",
  "data": "Product updated successfully."
}

Activate or deactivate a product

POST /products/update-status — requires capability bit_crm_product_update. A lighter endpoint for toggling a product’s Status without resending its fields.

  • id — integer, required. The product ID.
  • status — boolean, required. true for Active, false for Inactive.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/update-status
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/update-status" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"id": 31, "status": false}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/update-status');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['id' => 31, 'status' => false]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/update-status', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"id": 31, "status": false}),
});
const result = await response.json();

Example response:

{
  "status": "success",
  "message": "Product status updated successfully.",
  "code": "SUCCESS",
  "data": null
}

Attach a tag

POST /products/attach-tag — requires capability bit_crm_product_update.

  • title — string, required. Matched against the tag’s slug in the product module. If no such tag exists and the key’s user can create tags (bit_crm_tag_create), a new tag is created from this value.
  • product_id — integer, required.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/attach-tag
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/attach-tag" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"vip","product_id":12}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/attach-tag');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['title' => 'vip', 'product_id' => 12]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/attach-tag', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"title":"vip","product_id":12}),
});
const result = await response.json();

Example response — note that data is a plain string on this endpoint: "Tag added successfully.", or "Tag already added" when the product already holds the tag.

Detach a tag

POST /products/detach-tag — requires capability bit_crm_product_update.

  • tag_id — integer, required. The tag’s ID (find it with the Tags API).
  • product_id — integer, required.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/detach-tag
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/detach-tag" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"tag_id":7,"product_id":12}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/detach-tag');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['tag_id' => 7, 'product_id' => 12]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/detach-tag', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"tag_id":7,"product_id":12}),
});
const result = await response.json();

Example response — data is the string "Tag removed successfully."

Attach tags in bulk

POST /products/attach-tags — requires capability bit_crm_product_update. Attaches one or more existing tags to one or more products in a single request. Unlike attach-tag, this endpoint takes tag IDs and never creates tags. Pairs that already exist are skipped.

  • product_ids — array of integers, required.
  • tag_ids — array of integers, required. Tag IDs from the Tags API; the tags must belong to the product module.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/attach-tags
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/attach-tags" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"product_ids":[12,15],"tag_ids":[7,9]}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/attach-tags');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['product_ids' => [12, 15], 'tag_ids' => [7, 9]]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/attach-tags', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"product_ids":[12,15],"tag_ids":[7,9]}),
});
const result = await response.json();

Example response — data is the string "Tag added successfully.". If every requested pair already exists, the request fails with the message Tags already added.

Detach tags in bulk

POST /products/detach-tags — requires capability bit_crm_product_update. Removes one or more tags from one or more products in a single request.

  • product_ids — array of integers, required.
  • tag_ids — array of integers, required.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/detach-tags
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/detach-tags" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"product_ids":[12,15],"tag_ids":[7]}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/detach-tags');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['product_ids' => [12, 15], 'tag_ids' => [7]]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/detach-tags', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"product_ids":[12,15],"tag_ids":[7]}),
});
const result = await response.json();

Example response — data is the string "Tag(s) removed successfully."

Move products to the trash

POST /products/trash — requires capability bit_crm_product_delete. This is a soft delete: the records move to the recycle bin (Settings → Data Management) and can be restored from there. Products associated with deals or invoices are skipped; the response message then reports how many were deleted and how many were skipped.

  • ids — array of integers, required. The product IDs to trash.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/trash
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/trash" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids":[12,15]}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/trash');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_USERPWD        => 'your-username:YOUR API KEY',
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS     => json_encode(['ids' => [12, 15]]),
]);
$response = json_decode(curl_exec($ch), true);
curl_close($ch);
const response = await fetch('https://your-site.com/wp-json/bit-crm-sales-marketing-automation-pro/v1/products/trash', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"ids":[12,15]}),
});
const result = await response.json();

Example response. When some products are skipped due to deal or invoice associations, message instead reads %1$d product(s) deleted. %2$d product(s) skipped due to associated deals or invoices. with the counts filled in:

{
  "status": "success",
  "message": "Deleted successfully.",
  "code": "SUCCESS",
  "data": []
}
Share this Doc

Bit CRM Products API Documentation for Developers

Or copy link

CONTENTS

Subscribe

×
Cancel