CRM

Deals & pipelines

Pipelines and their stages, deals with contacts and line items, won / lost, forecasting fields.

A deal lives in a pipeline, at a stage. Its status follows the stage type (open, won, lost). Responses add computed fields: stage_name, stage_probability, weighted_amount, days_in_stage, is_rotting (stuck longer than the stage allows) and is_overdue (past its close date).

In a chat
Copy a ready promptPaste it in any AI: it reads the docs and follows the rules of the API.
Open in Claude or ChatGPTA new conversation with the prompt already written.
This page as MarkdownFor an AI that cannot open links: paste the text itself.
In your editor
Claude Code or CodexAdd this line to CLAUDE.md or AGENTS.md.Meetzy API reference (read before calling the API): https://www.meetzy.ai/llms-full.txt
CursorSettings › Indexing & Docs › Add Doc, then type @Meetzy in the chat.https://www.meetzy.ai/llms-full.txt
Connect Meetzy as tools (MCP)The AI can then read and change your CRM itself — Claude Code:claude mcp add --transport http meetzy https://meetzy.me/api/mcp/mcp
Same for Codexcodex mcp add meetzy --url https://meetzy.me/api/mcp/mcp
GET/pipelines

List pipelines

Every pipeline with its stages. Each sales cycle has its own pipeline (its deal board): sales_cycle gives that cycle ({ id, name }), null for a pipeline of your own. Renaming one renames the other.

Scope: read
Request
curl "https://meetzy.me/api/v1/pipelines" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/pipelines", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/pipelines",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "pipelines": [
    {
      "id": "cacafee6-6c63-407f-a948-5d6570c20143",
      "user_from": "acme",
      "name": "Sales pipeline",
      "is_default": true,
      "position": 0,
      "stages": [
        {
          "id": "qualification",
          "name": "Qualification",
          "type": "open",
          "color": "#6366F1",
          "rot_days": 14,
          "probability": 10
        },
        {
          "id": "discovery",
          "name": "Discovery call",
          "type": "open",
          "color": "#3B82F6",
          "rot_days": 14,
          "probability": 20
        },
        {
          "id": "demo",
          "name": "Demo / Meeting",
          "type": "open",
          "color": "#06B6D4",
          "rot_days": 10,
          "probability": 40
        }
      ],
      "currency": "EUR",
      "created_at": "2026-10-07T13:09:25.305055+00:00",
      "updated_at": "2026-10-07T13:09:25.305055+00:00"
    }
  ]
}
POST/pipelines

Create a pipeline

Creates a pipeline. Each stage: name, probability (0–100), color, type (open, won, lost), rot_days (days before the deal counts as stuck). A won and a lost stage are added when missing.

Scope: write

Body

namestringrequired
Pipeline name.
stagesobject[]
Stages in order. Default: the B2B template (Qualification → Negotiation).
currencystring
Currency of its deals. Default EUR.
Request
curl -X POST "https://meetzy.me/api/v1/pipelines" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Partners",
    "currency": "EUR",
    "stages": [
      {
        "name": "New",
        "probability": 10
      },
      {
        "name": "Contract sent",
        "probability": 60,
        "rot_days": 10
      }
    ]
  }'
const res = await fetch("https://meetzy.me/api/v1/pipelines", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Partners",
    "currency": "EUR",
    "stages": [
      {
        "name": "New",
        "probability": 10
      },
      {
        "name": "Contract sent",
        "probability": 60,
        "rot_days": 10
      }
    ]
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/pipelines",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "name": "Partners",
        "currency": "EUR",
        "stages": [
            {
                "name": "New",
                "probability": 10
            },
            {
                "name": "Contract sent",
                "probability": 60,
                "rot_days": 10
            }
        ]
    },
)
data = res.json()
Response201
{
  "id": "d9b0bf57-c46d-451f-adc0-adb7d2d43938",
  "user_from": "acme",
  "name": "Partners",
  "is_default": false,
  "position": 1,
  "stages": [
    {
      "id": "new",
      "name": "New",
      "type": "open",
      "color": "#6366F1",
      "rot_days": null,
      "probability": 10
    },
    {
      "id": "proposal",
      "name": "Proposal",
      "type": "open",
      "color": "#6366F1",
      "rot_days": null,
      "probability": 50
    }
  ],
  "currency": "EUR",
  "created_at": "2026-10-07T13:22:29.376133+00:00",
  "updated_at": "2026-10-07T13:22:29.376133+00:00"
}
PATCH/pipelines/{id}

Update a pipeline

Rename, reorder, change stages or make it the default. Each stage: name, probability (0–100), color, type (open, won, lost), rot_days (days before the deal counts as stuck). A won and a lost stage are added when missing.

Scope: write

Path parameters

idstringrequired
Id of the record (UUID).

Body

namestring
Name.
stagesobject[]
Full list of stages (replaces the current one).
currencystring
Currency.
positioninteger
Order among pipelines.
is_defaultboolean
true makes it the default pipeline.
Request
curl -X PATCH "https://meetzy.me/api/v1/pipelines/e43414d6-f56f-42be-a64c-a836d6015efc" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Partners & resellers"
  }'
const res = await fetch("https://meetzy.me/api/v1/pipelines/e43414d6-f56f-42be-a64c-a836d6015efc", {
  method: "PATCH",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Partners & resellers"
  }),
});
const data = await res.json();
import os, requests

res = requests.patch(
    "https://meetzy.me/api/v1/pipelines/e43414d6-f56f-42be-a64c-a836d6015efc",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "name": "Partners & resellers"
    },
)
data = res.json()
Response200
{
  "id": "d9b0bf57-c46d-451f-adc0-adb7d2d43938",
  "user_from": "acme",
  "name": "Partners",
  "is_default": false,
  "position": 1,
  "stages": [
    {
      "id": "new",
      "name": "New",
      "type": "open",
      "color": "#6366F1",
      "rot_days": null,
      "probability": 10
    },
    {
      "id": "proposal",
      "name": "Proposal",
      "type": "open",
      "color": "#6366F1",
      "rot_days": null,
      "probability": 50
    }
  ],
  "currency": "EUR",
  "created_at": "2026-10-07T13:22:29.376133+00:00",
  "updated_at": "2026-10-07T13:22:30.283636+00:00"
}
DELETE/pipelines/{id}

Delete a pipeline

Only an empty pipeline can be deleted (409 otherwise) — never the default one, nor the deal board of a sales cycle (delete the cycle instead, PUT /crm/cycles).

Scope: delete

Path parameters

idstringrequired
Id of the record (UUID).
Request
curl -X DELETE "https://meetzy.me/api/v1/pipelines/e43414d6-f56f-42be-a64c-a836d6015efc" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/pipelines/e43414d6-f56f-42be-a64c-a836d6015efc", {
  method: "DELETE",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.delete(
    "https://meetzy.me/api/v1/pipelines/e43414d6-f56f-42be-a64c-a836d6015efc",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "deleted": true
}
GET/deals/sources

Deals from your ERP

With an ERP or shop connected, deals fill themselves from what it syncs, whatever the system: every open quote is a deal (amount, validity, customer, salesperson, products — won when an order follows, lost when it closes without one), and customers who buy regularly get an expected reorder deal when their next order is due (their usual amount, a probability from how regular they are; their next order closes it as won with its real amount). This returns the settings, where each kind of deal goes (routes), and counts per kind. Refreshes on its own when older than 15 minutes, and after every sync. Generated deals carry custom.auto (kind, ref…).

Scope: read

Query parameters

refreshstring
1 updates now, 0 never (default: when stale).
Request
curl "https://meetzy.me/api/v1/deals/sources" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/deals/sources", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/deals/sources",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "connected": true,
  "provider": "sap_b1",
  "settings": {
    "enabled": true,
    "quotes": {
      "enabled": true,
      "pipeline_id": null,
      "stage_id": null,
      "max_age_days": 180
    },
    "reorders": {
      "enabled": true,
      "pipeline_id": null,
      "stage_id": null,
      "window_days": 30,
      "min_orders": 3,
      "lose_after_cycles": 2
    }
  },
  "routes": {
    "quotes": {
      "pipeline_id": "5f1e…",
      "stage_id": "proposal"
    },
    "reorders": {
      "pipeline_id": "5f1e…",
      "stage_id": "qualification"
    }
  },
  "counts": {
    "reorder": {
      "open": 53,
      "won": 12,
      "lost": 2,
      "open_amount": 822882
    },
    "quote": {
      "open": 1,
      "won": 4,
      "lost": 1,
      "open_amount": 20669
    }
  },
  "last_run_at": "2026-10-07T16:20:00Z"
}
PUT/deals/sources

Set what fills the deals

Turn each kind on or off, choose its pipeline and stage (null = automatic), the reorder window and how many orders it takes to know a customer’s rhythm. Saves, then updates the deals.

Scope: write

Body

enabledboolean
Deals from the ERP at all.
quotesobject
{ enabled, pipeline_id, stage_id, max_age_days }.
reordersobject
{ enabled, pipeline_id, stage_id, window_days, min_orders, lose_after_cycles }.

Returns the same as GET /deals/sources.

Request
curl -X PUT "https://meetzy.me/api/v1/deals/sources" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reorders": {
      "window_days": 21,
      "min_orders": 4
    }
  }'
const res = await fetch("https://meetzy.me/api/v1/deals/sources", {
  method: "PUT",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "reorders": {
      "window_days": 21,
      "min_orders": 4
    }
  }),
});
const data = await res.json();
import os, requests

res = requests.put(
    "https://meetzy.me/api/v1/deals/sources",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "reorders": {
            "window_days": 21,
            "min_orders": 4
        }
    },
)
data = res.json()
Response200

See the notes on the left.

POST/deals/sources/refresh

Update the deals from the ERP now

Creates the new ones, closes the ones whose order arrived (won) or whose quote closed without an order (lost), moves the others. A deal you deleted is never created again; an amount you changed by hand is kept.

Scope: write
Request
curl -X POST "https://meetzy.me/api/v1/deals/sources/refresh" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/deals/sources/refresh", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/deals/sources/refresh",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response201
{
  "created": 4,
  "updated": 2,
  "won": 1,
  "lost": 0,
  "skipped": 0
}
GET/deals

List deals

Deals with their company and primary contact, plus the pipelines (for stage names). Sorted by last update.

Scope: read

Query parameters

pipeline_iduuid
One pipeline, or several separated by commas.
statusstring
open, won, lost or all (default: all).
stage_idstring
Stage id.
ownerstring
Owner email.
company_iduuid
Deals of a company.
lead_iduuid
Deals where this contact is primary or linked.
prioritystring
Priority.
close_fromdate
Close date on or after.
close_todate
Close date on or before.
qstring
Search in the deal name.
sortstring
Column to sort by. Default updated_at.
orderstring
asc or desc (default).
limitinteger
Page size, 1–1000. Default 500.
offsetinteger
Rows to skip.
Request
curl "https://meetzy.me/api/v1/deals?status=open&close_to=2026-12-31" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/deals?status=open&close_to=2026-12-31", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/deals?status=open&close_to=2026-12-31",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "deals": [
    {
      "id": "d74acfa5-9877-4d7f-a369-3a505bac042a",
      "user_from": "acme",
      "name": "Payfit — rollout",
      "pipeline_id": "cacafee6-6c63-407f-a948-5d6570c20143",
      "stage_id": "qualification",
      "status": "open",
      "amount": 12000,
      "currency": "EUR",
      "probability": null,
      "close_date": "2026-11-06",
      "owner_email": "olivia@acme.com",
      "company_id": "166c436d-a874-4730-a0d8-c8d7fa090268",
      "primary_lead_id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
      "priority": "medium",
      "deal_type": "new_business",
      "source": null,
      "recurring": false,
      "mrr": null,
      "next_step": null,
      "next_step_date": null,
      "description": null,
      "lost_reason": null,
      "won_reason": null,
      "competitors": [],
      "tags": [],
      "custom": {},
      "stage_entered_at": "2026-10-07T13:22:48.038488+00:00",
      "stage_history": [],
      "closed_at": null,
      "last_activity_at": null,
      "created_by": "olivia@acme.com",
      "created_at": "2026-10-07T13:22:48.038488+00:00",
      "updated_at": "2026-10-07T13:22:48.038488+00:00",
      "stage_name": "Qualification",
      "stage_color": "#6366F1",
      "stage_probability": 10,
      "weighted_amount": 1200,
      "days_in_stage": 0,
      "is_rotting": false,
      "is_overdue": false,
      "company": {
        "id": "166c436d-a874-4730-a0d8-c8d7fa090268",
        "name": "Payfit",
        "domain": "payfit.com",
        "logo_url": null
      },
      "primary_contact": {
        "id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
        "display_name": "Camille Laurent",
        "primary_email": "camille@payfit.com",
        "avatar_url": null,
        "title": "Head of Sales"
      }
    }
  ],
  "total": 1,
  "pipelines": [
    {
      "id": "cacafee6-6c63-407f-a948-5d6570c20143",
      "user_from": "acme",
      "name": "Sales pipeline",
      "is_default": true,
      "position": 0,
      "stages": [
        {
          "id": "qualification",
          "name": "Qualification",
          "type": "open",
          "color": "#6366F1",
          "rot_days": 14,
          "probability": 10
        },
        {
          "id": "discovery",
          "name": "Discovery call",
          "type": "open",
          "color": "#3B82F6",
          "rot_days": 14,
          "probability": 20
        },
        {
          "id": "demo",
          "name": "Demo / Meeting",
          "type": "open",
          "color": "#06B6D4",
          "rot_days": 10,
          "probability": 40
        }
      ],
      "currency": "EUR",
      "created_at": "2026-10-07T13:09:25.305055+00:00",
      "updated_at": "2026-10-07T13:09:25.305055+00:00"
    },
    {
      "id": "d9b0bf57-c46d-451f-adc0-adb7d2d43938",
      "user_from": "acme",
      "name": "Partners",
      "is_default": false,
      "position": 1,
      "stages": [
        {
          "id": "new",
          "name": "New",
          "type": "open",
          "color": "#6366F1",
          "rot_days": null,
          "probability": 10
        },
        {
          "id": "proposal",
          "name": "Proposal",
          "type": "open",
          "color": "#6366F1",
          "rot_days": null,
          "probability": 50
        },
        {
          "id": "won",
          "name": "Closed won",
          "type": "won",
          "color": "#10B981",
          "probability": 100
        }
      ],
      "currency": "EUR",
      "created_at": "2026-10-07T13:22:29.376133+00:00",
      "updated_at": "2026-10-07T13:22:30.283636+00:00"
    }
  ]
}
POST/deals

Create a deal

Creates a deal, links its contacts and line items and logs it on the timeline. When primary_lead_id is set, the deal joins that contact’s sales cycle pipeline and company.

Scope: write

Body

namestringrequired
Deal name.
amountnumber
Value of the deal. Computed from line_items when you send lines and no amount.
currencystring
ISO currency (EUR, USD…). Defaults to the pipeline currency.
pipeline_iduuid
Pipeline. Default: the contact’s sales cycle pipeline, else the default pipeline.
stage_idstring
Stage id in that pipeline (see GET /pipelines). Default: the first open stage. Moving to a won / lost stage sets status.
statusstring
open, won or lost. Setting it moves the deal to the matching stage. Winning a deal makes its contacts and company customers.
probabilityinteger
Win probability override (0–100). Default: the stage probability.
close_datedate
Expected close date (YYYY-MM-DD). Default: in 30 days.
owner_emailstring
Owner. Default: the key’s user.
company_iduuid
Company. Found from the primary contact when omitted.
primary_lead_iduuid
Main contact of the deal.
prioritystring
low, medium or high.
deal_typestring
e.g. new_business, upsell, renewal.
sourcestring
Where the deal came from.
recurringboolean
Recurring revenue deal.
mrrnumber
Monthly recurring revenue (computed from monthly / yearly line items).
next_stepstring
Next step.
next_step_datedate
When the next step is due.
descriptionstring
Notes about the deal.
lost_reasonstring
Why it was lost (see lost_reasons in the reference).
won_reasonstring
Why it was won.
competitorsstring[]
Competitors in the deal.
tagsstring[]
Free labels.
customobject
Custom properties.
contact_idsuuid[]
Other contacts to link.
line_itemsobject[]
Products of the deal. Each line: name, quantity, unit_price, optional product_id, discount_pct, tax_pct, billing (one_time, monthly, yearly).
Request
curl -X POST "https://meetzy.me/api/v1/deals" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Payfit — rollout",
    "primary_lead_id": "e43414d6-f56f-42be-a64c-a836d6015efc",
    "close_date": "2026-11-30",
    "line_items": [
      {
        "name": "Licence",
        "quantity": 10,
        "unit_price": 1200,
        "billing": "yearly"
      }
    ]
  }'
const res = await fetch("https://meetzy.me/api/v1/deals", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "name": "Payfit — rollout",
    "primary_lead_id": "e43414d6-f56f-42be-a64c-a836d6015efc",
    "close_date": "2026-11-30",
    "line_items": [
      {
        "name": "Licence",
        "quantity": 10,
        "unit_price": 1200,
        "billing": "yearly"
      }
    ]
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/deals",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "name": "Payfit — rollout",
        "primary_lead_id": "e43414d6-f56f-42be-a64c-a836d6015efc",
        "close_date": "2026-11-30",
        "line_items": [
            {
                "name": "Licence",
                "quantity": 10,
                "unit_price": 1200,
                "billing": "yearly"
            }
        ]
    },
)
data = res.json()
Response201
{
  "id": "d74acfa5-9877-4d7f-a369-3a505bac042a",
  "user_from": "acme",
  "name": "Payfit — rollout",
  "pipeline_id": "cacafee6-6c63-407f-a948-5d6570c20143",
  "stage_id": "qualification",
  "status": "open",
  "amount": 12000,
  "currency": "EUR",
  "probability": null,
  "close_date": "2026-11-06",
  "owner_email": "olivia@acme.com",
  "company_id": "166c436d-a874-4730-a0d8-c8d7fa090268",
  "primary_lead_id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
  "priority": "medium",
  "deal_type": "new_business",
  "source": null,
  "recurring": false,
  "mrr": null,
  "next_step": null,
  "next_step_date": null,
  "description": null,
  "lost_reason": null,
  "won_reason": null,
  "competitors": [],
  "tags": [],
  "custom": {},
  "stage_entered_at": "2026-10-07T13:22:48.038488+00:00",
  "stage_history": [],
  "closed_at": null,
  "last_activity_at": null,
  "created_by": "olivia@acme.com",
  "created_at": "2026-10-07T13:22:48.038488+00:00",
  "updated_at": "2026-10-07T13:22:48.038488+00:00",
  "stage_name": "Qualification",
  "stage_color": "#6366F1",
  "stage_probability": 10,
  "weighted_amount": 1200,
  "days_in_stage": 0,
  "is_rotting": false,
  "is_overdue": false
}
GET/deals/{id}

Get a deal

The deal with its pipeline, company, contacts (with role), line items, tasks, timeline and quotes — plus origin for a deal made from the ERP (the quote, or the customer’s buying rhythm for an expected reorder) and company_summary (bought in the last 12 months, last order, open quotes, unpaid).

Scope: read

Path parameters

idstringrequired
Id of the record (UUID).
Request
curl "https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "deal": {
    "id": "d74acfa5-9877-4d7f-a369-3a505bac042a",
    "user_from": "acme",
    "name": "Payfit — rollout",
    "pipeline_id": "cacafee6-6c63-407f-a948-5d6570c20143",
    "stage_id": "qualification",
    "status": "open",
    "amount": 12000,
    "currency": "EUR",
    "probability": null,
    "close_date": "2026-11-06",
    "owner_email": "olivia@acme.com",
    "company_id": "166c436d-a874-4730-a0d8-c8d7fa090268",
    "primary_lead_id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
    "priority": "medium",
    "deal_type": "new_business",
    "source": null,
    "recurring": false,
    "mrr": null,
    "next_step": null,
    "next_step_date": null,
    "description": null,
    "lost_reason": null,
    "won_reason": null,
    "competitors": [],
    "tags": [],
    "custom": {},
    "stage_entered_at": "2026-10-07T13:22:48.038488+00:00",
    "stage_history": [],
    "closed_at": null,
    "last_activity_at": null,
    "created_by": "olivia@acme.com",
    "created_at": "2026-10-07T13:22:48.038488+00:00",
    "updated_at": "2026-10-07T13:22:48.038488+00:00",
    "stage_name": "Qualification",
    "stage_color": "#6366F1",
    "stage_probability": 10,
    "weighted_amount": 1200,
    "days_in_stage": 0,
    "is_rotting": false,
    "is_overdue": false
  },
  "pipeline": {
    "id": "cacafee6-6c63-407f-a948-5d6570c20143",
    "user_from": "acme",
    "name": "Sales pipeline",
    "is_default": true,
    "position": 0,
    "stages": [
      {
        "id": "qualification",
        "name": "Qualification",
        "type": "open",
        "color": "#6366F1",
        "rot_days": 14,
        "probability": 10
      },
      {
        "id": "discovery",
        "name": "Discovery call",
        "type": "open",
        "color": "#3B82F6",
        "rot_days": 14,
        "probability": 20
      },
      {
        "id": "demo",
        "name": "Demo / Meeting",
        "type": "open",
        "color": "#06B6D4",
        "rot_days": 10,
        "probability": 40
      }
    ],
    "currency": "EUR",
    "created_at": "2026-10-07T13:09:25.305055+00:00",
    "updated_at": "2026-10-07T13:09:25.305055+00:00"
  },
  "company": {
    "id": "166c436d-a874-4730-a0d8-c8d7fa090268",
    "user_from": "acme",
    "name": "Payfit",
    "domain": "payfit.com",
    "website": null,
    "industry": "Software",
    "employees": 42,
    "annual_revenue": null,
    "country": null,
    "city": null,
    "address": null,
    "phone": null,
    "linkedin_url": null,
    "description": null,
    "logo_url": null,
    "owner_email": "olivia@acme.com",
    "lifecycle_stage": "lead",
    "company_type": "prospect",
    "tier": "B",
    "health_score": null,
    "tags": [
      "api",
      "vip"
    ],
    "custom": {},
    "parent_company_id": null,
    "apollo_id": null,
    "last_activity_at": null,
    "created_by": "olivia@acme.com",
    "created_at": "2026-10-07T13:22:31.105534+00:00",
    "updated_at": "2026-10-07T13:22:37.766452+00:00"
  },
  "contacts": [
    {
      "id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
      "display_name": "Camille Laurent",
      "first_name": "Camille",
      "last_name": "Laurent",
      "primary_email": "camille@payfit.com",
      "phone": "+33612345678",
      "title": "Head of Sales",
      "company": "Payfit",
      "company_id": "166c436d-a874-4730-a0d8-c8d7fa090268",
      "avatar_url": null,
      "lead_score": 40,
      "lead_status": "cold",
      "pipeline_stage": "new_leads",
      "lifecycle_stage": "mql",
      "assigned_to": null,
      "primary_source": "manual",
      "last_contact_at": null,
      "created_at": "2026-10-07T13:22:38.585893+00:00",
      "linkedin_profile_url": null,
      "country": null,
      "city": null,
      "tags": [
        "inbound"
      ],
      "role": "decision_maker",
      "is_primary": true
    }
  ],
  "line_items": [
    {
      "id": "f660389d-a1c3-409b-a31b-b6245997bed1",
      "deal_id": "d74acfa5-9877-4d7f-a369-3a505bac042a",
      "product_id": null,
      "name": "Licence",
      "quantity": 10,
      "unit_price": 1200,
      "discount_pct": 0,
      "tax_pct": 0,
      "billing": "one_time",
      "position": 0,
      "created_at": "2026-10-07T13:22:48.311396+00:00"
    }
  ],
  "tasks": [],
  "activities": [
    {
      "id": "d7d99f47-ec01-46ec-aaf8-128b52670227",
      "user_from": "acme",
      "type": "system",
      "subject": "Deal created: Payfit — rollout",
      "body": null,
      "outcome": null,
      "direction": null,
      "duration_sec": null,
      "occurred_at": "2026-10-07T13:22:48.418+00:00",
      "actor_email": "olivia@acme.com",
      "lead_id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
      "deal_id": "d74acfa5-9877-4d7f-a369-3a505bac042a",
      "company_id": "166c436d-a874-4730-a0d8-c8d7fa090268",
      "metadata": {
        "amount": 12000
      },
      "created_at": "2026-10-07T13:22:48.454794+00:00"
    }
  ],
  "quotes": []
}
PATCH/deals/{id}

Update a deal — move, win, lose

Send only what changes. Move with stage_id; win or lose with status (or by moving to the won / lost stage). Stage moves are logged and the contact follows on the CRM board.

Scope: write

Path parameters

idstringrequired
Id of the record (UUID).

Body

namestring
Deal name.
amountnumber
Value of the deal. Computed from line_items when you send lines and no amount.
currencystring
ISO currency (EUR, USD…). Defaults to the pipeline currency.
pipeline_iduuid
Pipeline. Default: the contact’s sales cycle pipeline, else the default pipeline.
stage_idstring
Stage id in that pipeline (see GET /pipelines). Default: the first open stage. Moving to a won / lost stage sets status.
statusstring
open, won or lost. Setting it moves the deal to the matching stage. Winning a deal makes its contacts and company customers.
probabilityinteger
Win probability override (0–100). Default: the stage probability.
close_datedate
Expected close date (YYYY-MM-DD). Default: in 30 days.
owner_emailstring
Owner. Default: the key’s user.
company_iduuid
Company. Found from the primary contact when omitted.
primary_lead_iduuid
Main contact of the deal.
prioritystring
low, medium or high.
deal_typestring
e.g. new_business, upsell, renewal.
sourcestring
Where the deal came from.
recurringboolean
Recurring revenue deal.
mrrnumber
Monthly recurring revenue (computed from monthly / yearly line items).
next_stepstring
Next step.
next_step_datedate
When the next step is due.
descriptionstring
Notes about the deal.
lost_reasonstring
Why it was lost (see lost_reasons in the reference).
won_reasonstring
Why it was won.
competitorsstring[]
Competitors in the deal.
tagsstring[]
Free labels.
customobject
Custom properties.
Request
curl -X PATCH "https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "won",
    "won_reason": "Best integration with SAP"
  }'
const res = await fetch("https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc", {
  method: "PATCH",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "status": "won",
    "won_reason": "Best integration with SAP"
  }),
});
const data = await res.json();
import os, requests

res = requests.patch(
    "https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "status": "won",
        "won_reason": "Best integration with SAP"
    },
)
data = res.json()
Response200
{
  "id": "d74acfa5-9877-4d7f-a369-3a505bac042a",
  "user_from": "acme",
  "name": "Payfit — rollout",
  "pipeline_id": "cacafee6-6c63-407f-a948-5d6570c20143",
  "stage_id": "proposal",
  "status": "open",
  "amount": 12000,
  "currency": "EUR",
  "probability": null,
  "close_date": "2026-11-06",
  "owner_email": "olivia@acme.com",
  "company_id": "166c436d-a874-4730-a0d8-c8d7fa090268",
  "primary_lead_id": "8028ff76-1da4-451f-a0e7-dd91db772c20",
  "priority": "medium",
  "deal_type": "new_business",
  "source": null,
  "recurring": false,
  "mrr": null,
  "next_step": null,
  "next_step_date": null,
  "description": null,
  "lost_reason": null,
  "won_reason": null,
  "competitors": [],
  "tags": [],
  "custom": {},
  "stage_entered_at": "2026-10-07T13:22:51.622676+00:00",
  "stage_history": [
    {
      "at": "2026-10-07T13:22:51.622676+00:00",
      "to": "proposal",
      "from": "qualification",
      "days_in_stage": 0.000041483657407407404
    }
  ],
  "closed_at": null,
  "last_activity_at": null,
  "created_by": "olivia@acme.com",
  "created_at": "2026-10-07T13:22:48.038488+00:00",
  "updated_at": "2026-10-07T13:22:51.622676+00:00",
  "stage_name": "Proposal sent",
  "stage_color": "#F59E0B",
  "stage_probability": 60,
  "weighted_amount": 7200,
  "days_in_stage": 0,
  "is_rotting": false,
  "is_overdue": false
}
DELETE/deals/{id}

Delete a deal

Deletes the deal with its line items and contact links.

Scope: delete

Path parameters

idstringrequired
Id of the record (UUID).
Request
curl -X DELETE "https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc", {
  method: "DELETE",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.delete(
    "https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "deleted": true
}
PUT/deals/{id}/contacts

Set the contacts of a deal

Replaces the contacts linked to the deal (the buying committee).

Scope: write

Path parameters

idstringrequired
Id of the record (UUID).

Body

contactsobject[]required
Each { lead_id, role } — role is free text (champion, decision_maker, user…).
Request
curl -X PUT "https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc/contacts" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contacts": [
      {
        "lead_id": "e43414d6-f56f-42be-a64c-a836d6015efc",
        "role": "champion"
      }
    ]
  }'
const res = await fetch("https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc/contacts", {
  method: "PUT",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "contacts": [
      {
        "lead_id": "e43414d6-f56f-42be-a64c-a836d6015efc",
        "role": "champion"
      }
    ]
  }),
});
const data = await res.json();
import os, requests

res = requests.put(
    "https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc/contacts",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "contacts": [
            {
                "lead_id": "e43414d6-f56f-42be-a64c-a836d6015efc",
                "role": "champion"
            }
        ]
    },
)
data = res.json()
Response200
{
  "linked": 1
}
PUT/deals/{id}/line-items

Set the line items of a deal

Replaces the products of the deal. The amount and MRR are recomputed unless sync_amount is false. Each line: name, quantity, unit_price, optional product_id, discount_pct, tax_pct, billing (one_time, monthly, yearly).

Scope: write

Path parameters

idstringrequired
Id of the record (UUID).

Body

line_itemsobject[]required
Products of the deal.
sync_amountboolean
Recompute amount and mrr from the lines. Default true.
Request
curl -X PUT "https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc/line-items" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "line_items": [
      {
        "product_id": "0f6b1c2a-7d84-4b1e-9e0a-3c5d7e9f1a2b",
        "name": "Licence",
        "quantity": 12,
        "unit_price": 1000,
        "discount_pct": 10,
        "billing": "yearly"
      }
    ]
  }'
const res = await fetch("https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc/line-items", {
  method: "PUT",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "line_items": [
      {
        "product_id": "0f6b1c2a-7d84-4b1e-9e0a-3c5d7e9f1a2b",
        "name": "Licence",
        "quantity": 12,
        "unit_price": 1000,
        "discount_pct": 10,
        "billing": "yearly"
      }
    ]
  }),
});
const data = await res.json();
import os, requests

res = requests.put(
    "https://meetzy.me/api/v1/deals/e43414d6-f56f-42be-a64c-a836d6015efc/line-items",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "line_items": [
            {
                "product_id": "0f6b1c2a-7d84-4b1e-9e0a-3c5d7e9f1a2b",
                "name": "Licence",
                "quantity": 12,
                "unit_price": 1000,
                "discount_pct": 10,
                "billing": "yearly"
            }
        ]
    },
)
data = res.json()
Response200
{
  "items": 1
}