Skip to main content

Bit CRM Deals API Documentation for Developers

Estimated reading: 14 minutes 44 views

The Bit CRM Deals API lets you create, search, retrieve, and update deals, move them through pipeline stages, and list the stages themselves. All endpoints are relative to your base URL and authenticated with an API key — see Introduction & Authentication.

Deal field keys

Create and update requests take deal fields inside a systemDefinedFieldsValues object. name, stage, and contact_id are required.

  • name — required
  • stage — required; a stage key such as qualification (see List deal stages below)
  • contact_id — required; ID of the contact the deal belongs to
  • company_id — ID of the related company
  • email, type, lead_source, probability, amount, description
  • owner_id — WordPress user ID of the deal owner
  • currency — currency code; defaults to your home currency. Send it at the top level of the payload (beside systemDefinedFieldsValues, not inside it — a nested value is ignored). Bit CRM converts amount into your home currency automatically and stores it as home_currency_amount.

Note: If you have defined custom fields for deals (a Pro feature), 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, and come back in the response as custom_fields_values.

Create a deal

POST /deals/store — requires capability bit_crm_deal_create.

  • systemDefinedFieldsValues — object, required. Deal fields (see above).
  • tagIds — array of integers, optional. IDs of existing deal tags to attach.
  • newTagTitles — array of strings, optional. New tags to create and attach.
  • lineItems — array, optional. Each item may carry product_name (string), unit_price (number), quantity (integer), discount_percentage (number, 0–100), tax_rate (number, 0–1000), product_code (string), product_source (string), description (string), and product_id (integer).
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/store
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/store" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "systemDefinedFieldsValues": {
      "name": "Acme annual license",
      "stage": "qualification",
      "contact_id": "42",
      "amount": "4800"
    },
    "currency": "USD",
    "customFieldsValues": {
      "contract_term": {
        "field_id": 9,
        "field_value": "12 months"
      }
    },
    "lineItems": [
      {
        "product_id": 7,
        "product_name": "Annual license",
        "unit_price": 400,
        "quantity": 12
      }
    ]
  }'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/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' => 'Acme annual license',
            'stage' => 'qualification',
            'contact_id' => '42',
            'amount' => '4800',
        ],
        'currency' => 'USD',
        'customFieldsValues' => [
            'contract_term' => [
                'field_id' => 9,
                'field_value' => '12 months',
            ],
        ],
        'lineItems' => [
            [
                'product_id' => 7,
                'product_name' => 'Annual license',
                'unit_price' => 400,
                'quantity' => 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/v1/deals/store', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({
    "systemDefinedFieldsValues": {
      "name": "Acme annual license",
      "stage": "qualification",
      "contact_id": "42",
      "amount": "4800"
    },
    "currency": "USD",
    "customFieldsValues": {
      "contract_term": {
        "field_id": 9,
        "field_value": "12 months"
      }
    },
    "lineItems": [
      {
        "product_id": 7,
        "product_name": "Annual license",
        "unit_price": 400,
        "quantity": 12
      }
    ]
  }),
});
const result = await response.json();

Example response — data is the created deal, including home_currency_amount. Line items are stored but not echoed back; retrieve the deal to see them.

{
  "status": "success",
  "code": "SUCCESS",
  "data": {
    "id": 23,
    "name": "Acme annual license",
    "stage": "qualification",
    "contact_id": "42",
    "amount": 4800,
    "currency": "USD",
    "home_currency_amount": 4800,
    "reference_uuid": "1e9d4c7a-2f5b-4d8e-9a6c-3b7f1d5e8c20",
    "created_by": 1,
    "created_at": "2026-08-04 10:30:00",
    "updated_at": "2026-08-04 10:30:00",
    "custom_fields_values": {
      "contract_term": { "field_id": 9, "field_value": "12 months", "field_key": "contract_term" }
    }
  }
}

Search deals

POST /deals/search — requires capability bit_crm_deal_view.

  • table — boolean, required. Send true for a standard paginated list (recommended for API use). false returns the kanban-board shape described below.
  • page — integer, optional, minimum 1, default 1.
  • perPage — integer, optional, between 1 and 100, default 10.
  • searchTerm — string. Matches deal name, email, and description. Send "" when not searching.
  • sortBy — string, optional, default id.
  • sortOrder — asc or desc, optional, default desc.
  • tags — array of tag IDs, optional.
  • advancedFilterGroups — array, optional. Same shape as the CRM’s own filter UI (field_key, operator, field_type, is_custom, value).
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/search
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/search" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"table": true, "page": 1, "perPage": 10, "searchTerm": ""}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/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(['table' => true, 'page' => 1, 'perPage' => 10, 'searchTerm' => '']),
]);
$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/v1/deals/search', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"table": true, "page": 1, "perPage": 10, "searchTerm": ""}),
});
const result = await response.json();

With table: true, data is the standard paginated object; each row also carries contact_name, company_name, and owner_name.

Note: with table: false (and page 1 or omitted), the response instead groups deals for a kanban board: data holds up to perPage deals per active stage, alongside a stageStatistics object, and total is always 0 in this shape.

Retrieve a deal

GET /deals/{id} — requires capability bit_crm_deal_view.

data holds every deal field plus created_by_name and updated_by_name, the deal’s lineItems and tags (each present only when the deal has them), and previous_id / next_id. Trashed deals are not returned.

GET https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/23
  • Bash
  • PHP
  • JavaScript
curl "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/23" \
  --user "your-username:YOUR API KEY"
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/23');
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/v1/deals/23', {
  headers: { 'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY') },
});
const result = await response.json();

Update a deal

POST /deals/{id} — requires capability bit_crm_deal_update.

Send the fields to change inside systemDefinedFieldsValues, and optionally a lineItems array (same item shape as create). Only id is required — updates are partial, so send just the fields you want to change.

POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/23
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/23" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "systemDefinedFieldsValues": {
      "name": "Acme annual license",
      "stage": "proposal",
      "contact_id": "42",
      "probability": "50"
    }
  }'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/23');
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' => 'Acme annual license',
            'stage' => 'proposal',
            'contact_id' => '42',
            'probability' => '50',
        ],
    ]),
]);
$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/v1/deals/23', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({
    "systemDefinedFieldsValues": {
      "name": "Acme annual license",
      "stage": "proposal",
      "contact_id": "42",
      "probability": "50"
    }
  }),
});
const result = await response.json();

Example response — message confirms the update and data is the updated deal.

Update a deal’s stage

POST /deals/update-stage — requires capability bit_crm_deal_update. A lighter endpoint for moving a deal through the pipeline without resending its fields.

  • id — integer, required. The deal ID.
  • stage — string, required. The new stage key.
  • probability — integer, required. The win probability to set; the CRM UI uses 0–100, but the API does not enforce a range.
  • amount — number, optional. When sent, the home-currency amount is recalculated automatically.
  • closed_at — string, optional. Closing date for won/lost deals.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/update-stage
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/update-stage" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"id": 23, "stage": "won", "probability": 100, "closed_at": "2026-08-04"}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/update-stage');
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' => 23, 'stage' => 'won', 'probability' => 100, 'closed_at' => '2026-08-04']),
]);
$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/v1/deals/update-stage', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"id": 23, "stage": "won", "probability": 100, "closed_at": "2026-08-04"}),
});
const result = await response.json();

Example response — data is the string "Deal stage updated successfully."

List deal stages

GET /deals/stages — returns the active pipeline stages, including any custom stages you have added in deal settings.

GET https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/stages
  • Bash
  • PHP
  • JavaScript
curl "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/stages" \
  --user "your-username:YOUR API KEY"
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/stages');
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/v1/deals/stages', {
  headers: { 'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY') },
});
const result = await response.json();
{
  "status": "success",
  "message": "Deal stages retrieved successfully.",
  "code": "SUCCESS",
  "data": [
    {
      "key": "initial_contact",
      "name": "Initial Contact",
      "color": "#595959",
      "deal_category": "open",
      "probability": 10,
      "system_defined": true
    }
  ]
}

The default system-defined stage keys are initial_contact, qualification, proposal, negotiation, won, and lost. deal_category is open, closed_won, or closed_lost. Use the key values as the stage field when creating or updating deals.

Attach a tag

POST /deals/attach-tag — requires capability bit_crm_deal_update.

  • title — string, required. Matched against the tag’s slug in the deal 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.
  • deal_id — integer, required.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/attach-tag
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/attach-tag" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"title":"vip","deal_id":12}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/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', 'deal_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/v1/deals/attach-tag', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"title":"vip","deal_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 deal already holds the tag.

Detach a tag

POST /deals/detach-tag — requires capability bit_crm_deal_update.

  • tag_id — integer, required. The tag’s ID (find it with the Tags API).
  • deal_id — integer, required.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/detach-tag
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/detach-tag" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"tag_id":7,"deal_id":12}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/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, 'deal_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/v1/deals/detach-tag', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"tag_id":7,"deal_id":12}),
});
const result = await response.json();

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

Attach tags in bulk

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

  • deal_ids — array of integers, required.
  • tag_ids — array of integers, required. Tag IDs from the Tags API; the tags must belong to the deal module.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/attach-tags
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/attach-tags" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"deal_ids":[12,15],"tag_ids":[7,9]}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/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(['deal_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/v1/deals/attach-tags', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"deal_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 /deals/detach-tags — requires capability bit_crm_deal_update. Removes one or more tags from one or more deals in a single request.

  • deal_ids — array of integers, required.
  • tag_ids — array of integers, required.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/detach-tags
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/detach-tags" \
  --user "your-username:YOUR API KEY" \
  -H "Content-Type: application/json" \
  -d '{"deal_ids":[12,15],"tag_ids":[7]}'
$ch = curl_init('https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/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(['deal_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/v1/deals/detach-tags', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Basic ' + btoa('your-username:YOUR API KEY'),
  },
  body: JSON.stringify({"deal_ids":[12,15],"tag_ids":[7]}),
});
const result = await response.json();

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

Move deals to the trash

POST /deals/trash — requires capability bit_crm_deal_delete. This is a soft delete: the records move to the recycle bin (Settings → Data Management) and can be restored from there.

  • ids — array of integers, required. The deal IDs to trash.
POST https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/trash
  • Bash
  • PHP
  • JavaScript
curl -X POST "https://your-site.com/wp-json/bit-crm-sales-marketing-automation/v1/deals/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/v1/deals/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/v1/deals/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:

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

Bit CRM Deals API Documentation for Developers

Or copy link

CONTENTS

Subscribe

×
Cancel