Data

Data sources

Bring companies, contacts, deals, products, quotes, orders, invoices and credit notes in from any ERP, shop or CRM — through a connector, by pushing them yourself, or as rows from a file.

Three ways in, one set of rules. Connectors (SAP Business One, Odoo, Shopify, WooCommerce, HubSpot, Pipedrive, Close, Attio, Copper, Capsule, Insightly, product feeds) read your system on a schedule. Push — any other system (Sage, Cegid, Dynamics, NetSuite, a home-grown ERP, n8n, a script) sends its records to POST /sync/ingest under its own source id custom:<name>. Import sends rows once, like a file. Every record goes through the same normalisation (field names in English, French, German, Spanish and the SAP / Odoo / Sage vocabularies; dates in any format; European decimals; statuses) and the same matching — companies by link, then customer code, then email domain, then name — so nothing is duplicated.

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
POST/sync/ingest

Push records from any system

Send up to 5,000 records of one object per call. The source is created on the first call (it then appears in Meetzy › Integrations with its status). Records are matched to what Meetzy already has: the same external_id updates, the customer code links invoices to companies, unknown customers named on documents are created. The answer counts what was created, updated, unchanged or skipped and lists rejected records with the reason. Field names don’t need to match: N° facture, Code client, Total TTC, Kunde, Importe are recognised — see the field reference below.

Scope: write

Body

providerstringrequired
Source id: custom:<name> for your system (custom:sage-100), or a connector id (sap_b1, odoo…) when you send on its behalf.
objectstringrequired
companies, contacts, products, deals, quotes, orders, invoices, credit_notes, or documents (mixed, each record with a type).
recordsobject[]required
The records, in your own field names.
labelstring
Display name of your system (“Sage 100”), set on the first call.
date_orderstring
dmy or mdy when your dates are ambiguous (05/10/2026). Detected from the batch otherwise.
firstboolean
First batch of a full run: resets the run counters.
lastboolean
Last batch of a run: marks the object as synced (its since moves forward).
sincedate
This run only sent changes since this date (not a full run).
started_atdatetime
When your run started — recorded as the last success.
keep_onlystring[]
Products: the ids still alive in your system — the others are archived.
currencystring
Default currency for records without one.

Batches can also carry lifecycle markers for long runs: object: "_start", "_error" (for, message) and "_end" (owners, currency).

Up to 5,000 records per call (60,000 for price_rules). 413 above.

Request
curl -X POST "https://meetzy.me/api/v1/sync/ingest" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "custom:sage-100",
    "label": "Sage 100",
    "object": "invoices",
    "records": [
      {
        "N° facture": "F2026-0412",
        "Date": "30/09/2026",
        "Échéance": "29/11/2026",
        "Code client": "C-1001",
        "Client": "Parfumerie Lumière",
        "Total HT": "1 250,00",
        "Total TTC": "1 500,00",
        "Reste dû": "1 000,00",
        "Commercial": "Alice Martin",
        "lines": [
          {
            "Référence": "SKU-100",
            "Désignation": "Eau de parfum 50 ml",
            "Qté": 24,
            "PU HT": 42,
            "Montant HT": 1008
          }
        ]
      }
    ]
  }'
const res = await fetch("https://meetzy.me/api/v1/sync/ingest", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "provider": "custom:sage-100",
    "label": "Sage 100",
    "object": "invoices",
    "records": [
      {
        "N° facture": "F2026-0412",
        "Date": "30/09/2026",
        "Échéance": "29/11/2026",
        "Code client": "C-1001",
        "Client": "Parfumerie Lumière",
        "Total HT": "1 250,00",
        "Total TTC": "1 500,00",
        "Reste dû": "1 000,00",
        "Commercial": "Alice Martin",
        "lines": [
          {
            "Référence": "SKU-100",
            "Désignation": "Eau de parfum 50 ml",
            "Qté": 24,
            "PU HT": 42,
            "Montant HT": 1008
          }
        ]
      }
    ]
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/sync/ingest",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "provider": "custom:sage-100",
        "label": "Sage 100",
        "object": "invoices",
        "records": [
            {
                "N° facture": "F2026-0412",
                "Date": "30/09/2026",
                "Échéance": "29/11/2026",
                "Code client": "C-1001",
                "Client": "Parfumerie Lumière",
                "Total HT": "1 250,00",
                "Total TTC": "1 500,00",
                "Reste dû": "1 000,00",
                "Commercial": "Alice Martin",
                "lines": [
                    {
                        "Référence": "SKU-100",
                        "Désignation": "Eau de parfum 50 ml",
                        "Qté": 24,
                        "PU HT": 42,
                        "Montant HT": 1008
                    }
                ]
            }
        ]
    },
)
data = res.json()
Response201
{
  "created": 0,
  "updated": 1,
  "unchanged": 0,
  "skipped": 0,
  "archived": 0,
  "received": 1,
  "rejected": 0,
  "rejected_samples": [],
  "date_order": "dmy"
}
POST/sync/import

Import rows once (like a file)

Rows from a spreadsheet or an export, without setting up a source — records are tagged with the source import. Same normalisation and matching as sync/ingest. Invoices spread over several rows (one per line) are grouped by number. Send big files in parts of up to 5,000 rows; first: false on the following parts.

Scope: write

Body

objectstringrequired
companies, contacts, deals, quotes, orders, invoices, credit_notes or documents.
recordsobject[]required
The rows, with the file’s own column names.
date_orderstring
dmy or mdy for ambiguous dates.
overwriteboolean
Update fields of records that already exist (default: only fill what is empty).
cyclestring
Contacts: sales cycle to put new contacts in.
firstboolean
false for the second part of a file onwards.
Request
curl -X POST "https://meetzy.me/api/v1/sync/import" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "object": "companies",
    "records": [
      {
        "Code client": "C-1001",
        "Raison sociale": "Parfumerie Lumière",
        "Pays": "France",
        "Ville": "Lyon",
        "Commercial": "Alice Martin"
      }
    ]
  }'
const res = await fetch("https://meetzy.me/api/v1/sync/import", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "object": "companies",
    "records": [
      {
        "Code client": "C-1001",
        "Raison sociale": "Parfumerie Lumière",
        "Pays": "France",
        "Ville": "Lyon",
        "Commercial": "Alice Martin"
      }
    ]
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/sync/import",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "object": "companies",
        "records": [
            {
                "Code client": "C-1001",
                "Raison sociale": "Parfumerie Lumière",
                "Pays": "France",
                "Ville": "Lyon",
                "Commercial": "Alice Martin"
            }
        ]
    },
)
data = res.json()
Response201
{
  "created": 0,
  "updated": 0,
  "unchanged": 1,
  "skipped": 0,
  "archived": 0,
  "received": 1,
  "rejected": 0,
  "rejected_samples": [],
  "date_order": "dmy"
}
GET/sync/providers

Available connectors

Every source Meetzy can connect: id, name, category, what it can bring in (objects) and by default, its connection methods with the fields they need (secret fields are write-only), options per object, the sync intervals and the object list.

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

res = requests.get(
    "https://meetzy.me/api/v1/sync/providers",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "categories": [
    {
      "id": "erp",
      "label": "ERP & accounting"
    }
  ],
  "intervals": [
    {
      "min": 15,
      "label": "Every 15 minutes"
    },
    {
      "min": 60,
      "label": "Every hour"
    }
  ],
  "providers": [
    {
      "id": "odoo",
      "name": "Odoo",
      "category": "erp",
      "versions": "Odoo 14 to 18 — Online, Odoo.sh or on-premise.",
      "objects": [
        "products",
        "companies",
        "contacts",
        "deals",
        "quotes",
        "orders",
        "invoices",
        "credit_notes"
      ],
      "defaults": [
        "products",
        "companies",
        "contacts",
        "deals",
        "orders",
        "invoices"
      ],
      "oauth": false,
      "push": false,
      "methods": {
        "api": {
          "label": "Direct connection",
          "fields": [
            {
              "key": "url",
              "label": "Odoo address",
              "secret": false,
              "optional": false
            },
            {
              "key": "database",
              "label": "Database",
              "secret": false,
              "optional": false
            },
            {
              "key": "login",
              "label": "Login (email)",
              "secret": false,
              "optional": false
            },
            {
              "key": "key",
              "label": "API key",
              "secret": true,
              "optional": false
            }
          ],
          "options": []
        }
      },
      "object_options": {
        "invoices": [
          {
            "key": "months",
            "label": "History",
            "type": "select",
            "default": 24
          },
          {
            "key": "lines",
            "label": "Include the lines (products, quantities, prices)",
            "type": "toggle",
            "default": false
          }
        ]
      }
    }
  ]
}
GET/sync

Connected sources

Every connected source: method, account, what it syncs, status (idle, running, error), last run and last success, last error, per-object counters, and how many records each brought in. Secrets are never returned (has_secret tells which are set).

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

res = requests.get(
    "https://meetzy.me/api/v1/sync",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "migrated": true,
  "connected": [],
  "counts": {},
  "hubspot_oauth": false
}
GET/sync/{provider}

One source

One connection (same shape as in GET /sync) and its record counts. provider is the source id (odoo, custom:sage-100…).

Scope: read

Path parameters

providerstringrequired
Source id: odoo, sap_b1, shopify, custom:sage-100…
Request
curl "https://meetzy.me/api/v1/sync/custom:sage-100" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/sync/custom:sage-100", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/sync/custom:sage-100",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "connection": {
    "provider": "custom:sage-100",
    "method": "push",
    "account_label": "Sage 100",
    "credentials": {},
    "has_secret": {},
    "oauth": false,
    "objects": {
      "products": {
        "enabled": false,
        "mode": "sync",
        "options": {}
      },
      "companies": {
        "enabled": true,
        "mode": "sync",
        "options": {}
      },
      "contacts": {
        "enabled": true,
        "mode": "sync",
        "options": {
          "cycle": ""
        }
      },
      "deals": {
        "enabled": false,
        "mode": "sync",
        "options": {}
      },
      "quotes": {
        "enabled": false,
        "mode": "sync",
        "options": {
          "months": 24,
          "lines": false
        }
      },
      "orders": {
        "enabled": true,
        "mode": "sync",
        "options": {
          "months": 24,
          "lines": false
        }
      },
      "invoices": {
        "enabled": true,
        "mode": "sync",
        "options": {
          "months": 24,
          "lines": false
        }
      },
      "credit_notes": {
        "enabled": false,
        "mode": "sync",
        "options": {
          "months": 24,
          "lines": false
        }
      }
    },
    "settings": {
      "interval_min": 60
    },
    "status": "idle",
    "stats": {
      "phase": "Done",
      "objects": {
        "invoices": {
          "created": 0,
          "skipped": 0,
          "updated": 1,
          "archived": 0,
          "unchanged": 0
        }
      }
    },
    "last_error": null,
    "last_run_at": "2026-10-07T13:23:58.796+00:00",
    "last_success_at": "2026-10-07T13:23:58.796+00:00",
    "started_at": null,
    "agent_last_seen_at": "2026-10-07T13:23:58.796+00:00",
    "agent_info": {
      "runtime": "API"
    },
    "has_agent_key": false,
    "created_at": "2026-10-07T13:23:58.721716+00:00",
    "interrupted": false
  },
  "counts": {
    "companies": 0,
    "price_rules": 0,
    "contacts": 0,
    "deals": 0,
    "products": 0,
    "orders": 0,
    "credit_notes": 0,
    "invoices": 1,
    "quotes": 0
  }
}
PUT/sync/{provider}

Connect a source

Saves the connection: method, credentials, what to bring in, options. For api methods Meetzy tests the credentials first (400 with the provider’s message if they fail) and starts a first run. To connect your own system, use provider: custom with credentials.name — it becomes custom:<name>. HubSpot signs in with OAuth from the app.

Scope: write

Path parameters

providerstringrequired
Source id: odoo, sap_b1, shopify, custom:sage-100…

Body

methodstring
Connection method of the provider (api, agent, push).
credentialsobjectrequired
Values for the method’s fields (see GET /sync/providers). A secret left empty keeps the saved one.
objectsobject
{ "invoices": { "enabled": true, "mode": "sync" | "import", "options": { "months": 24, "lines": true } } }. Default: the provider’s defaults.
settingsobject
interval_min (15, 60, 360 or 1440), no_owner (none or creator), method options (e.g. insecure_tls).
startboolean
Run right away. Default true.

Returns the saved connection, like GET /sync/{provider}.

Request
curl -X PUT "https://meetzy.me/api/v1/sync/custom:sage-100" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "method": "api",
    "credentials": {
      "url": "https://acme.odoo.com",
      "database": "acme",
      "login": "olivia@acme.com",
      "key": "odoo_api_key"
    },
    "objects": {
      "invoices": {
        "enabled": true,
        "mode": "sync",
        "options": {
          "months": 24,
          "lines": true
        }
      },
      "companies": {
        "enabled": true,
        "mode": "sync"
      }
    },
    "settings": {
      "interval_min": 60
    }
  }'
const res = await fetch("https://meetzy.me/api/v1/sync/custom:sage-100", {
  method: "PUT",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "method": "api",
    "credentials": {
      "url": "https://acme.odoo.com",
      "database": "acme",
      "login": "olivia@acme.com",
      "key": "odoo_api_key"
    },
    "objects": {
      "invoices": {
        "enabled": true,
        "mode": "sync",
        "options": {
          "months": 24,
          "lines": true
        }
      },
      "companies": {
        "enabled": true,
        "mode": "sync"
      }
    },
    "settings": {
      "interval_min": 60
    }
  }),
});
const data = await res.json();
import os, requests

res = requests.put(
    "https://meetzy.me/api/v1/sync/custom:sage-100",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "method": "api",
        "credentials": {
            "url": "https://acme.odoo.com",
            "database": "acme",
            "login": "olivia@acme.com",
            "key": "odoo_api_key"
        },
        "objects": {
            "invoices": {
                "enabled": True,
                "mode": "sync",
                "options": {
                    "months": 24,
                    "lines": True
                }
            },
            "companies": {
                "enabled": True,
                "mode": "sync"
            }
        },
        "settings": {
            "interval_min": 60
        }
    },
)
data = res.json()
Response200

See the notes on the left.

POST/sync/{provider}/test

Test credentials

Checks api credentials without saving them (400 with the provider’s message when they fail). Returns the account label and what was found (currency, price lists).

Scope: write

Path parameters

providerstringrequired
Source id: odoo, sap_b1, shopify, custom:sage-100…

Body

methodstring
Method.
credentialsobjectrequired
Credentials to test.
Request
curl -X POST "https://meetzy.me/api/v1/sync/custom:sage-100/test" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "method": "api",
    "credentials": {
      "url": "https://acme.odoo.com",
      "database": "acme",
      "login": "olivia@acme.com",
      "key": "odoo_api_key"
    }
  }'
const res = await fetch("https://meetzy.me/api/v1/sync/custom:sage-100/test", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "method": "api",
    "credentials": {
      "url": "https://acme.odoo.com",
      "database": "acme",
      "login": "olivia@acme.com",
      "key": "odoo_api_key"
    }
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/sync/custom:sage-100/test",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "method": "api",
        "credentials": {
            "url": "https://acme.odoo.com",
            "database": "acme",
            "login": "olivia@acme.com",
            "key": "odoo_api_key"
        }
    },
)
data = res.json()
Response201
{
  "label": "Acme · Odoo",
  "options": {
    "currency": "EUR"
  }
}
PATCH/sync/{provider}

Change what a source syncs

Turn objects on or off, switch them between sync and one-time import, change options or the interval, and map salespeople — without touching credentials. An object whose options change (lines turned on, more history) is read in full on the next run. Mappings are applied to what is already synced unless apply: false.

Scope: write

Path parameters

providerstringrequired
Source id: odoo, sap_b1, shopify, custom:sage-100…

Body

objectsobject
Objects and their options.
settingsobject
Interval and options.
ownersobject
Salesperson mapping: { "<salesperson code in your system>": "teammate@acme.com" } (empty string removes).
country_ownersobject
Owner of customers without a salesperson, per country: { "Nigeria": "alice@acme.com" }.
country_firstboolean
When true, the country rules win even over the salesperson of the source: every customer of a country with a rule goes to its owner (with contacts, documents and open deals). false gives them back to their salesperson.
applyboolean
Re-assign existing companies, contacts, documents and deals. Default true.
apply_allboolean
Re-apply every mapping, not only the changed ones.

Returns the updated connection, plus reassigned (companies, contacts, documents, deals) when a mapping changed.

Request
curl -X PATCH "https://meetzy.me/api/v1/sync/custom:sage-100" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "objects": {
      "credit_notes": {
        "enabled": true,
        "mode": "sync"
      }
    },
    "owners": {
      "12": "alice@acme.com"
    }
  }'
const res = await fetch("https://meetzy.me/api/v1/sync/custom:sage-100", {
  method: "PATCH",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "objects": {
      "credit_notes": {
        "enabled": true,
        "mode": "sync"
      }
    },
    "owners": {
      "12": "alice@acme.com"
    }
  }),
});
const data = await res.json();
import os, requests

res = requests.patch(
    "https://meetzy.me/api/v1/sync/custom:sage-100",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "objects": {
            "credit_notes": {
                "enabled": True,
                "mode": "sync"
            }
        },
        "owners": {
            "12": "alice@acme.com"
        }
    },
)
data = res.json()
Response200

See the notes on the left.

POST/sync/{provider}/run

Run a sync now

Starts a run of a connector (all objects or some). For pushing sources (push, agent) Meetzy cannot start them: full: true asks the next run to send everything again.

Scope: write

Path parameters

providerstringrequired
Source id: odoo, sap_b1, shopify, custom:sage-100…

Body

objectsstring[]
Only these objects.
fullboolean
Read everything, not only changes.
Request
curl -X POST "https://meetzy.me/api/v1/sync/custom:sage-100/run" \
  -H "Authorization: Bearer $MEETZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "objects": [
      "invoices"
    ],
    "full": false
  }'
const res = await fetch("https://meetzy.me/api/v1/sync/custom:sage-100/run", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({
    "objects": [
      "invoices"
    ],
    "full": false
  }),
});
const data = await res.json();
import os, requests

res = requests.post(
    "https://meetzy.me/api/v1/sync/custom:sage-100/run",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
    json={
        "objects": ["invoices"],
        "full": False
    },
)
data = res.json()
Response201
{
  "ok": true
}
GET/sync/agent/config

What a pushing system should send now

For a source that pushes (a script, a job in your ERP): per enabled object, its mode, options and since — the date of the last success, so you only send what changed. Call it at the start of each run.

Scope: read

Query parameters

providerstringrequired
Source id, e.g. custom:sage-100.
Request
curl "https://meetzy.me/api/v1/sync/agent/config?provider=custom:sage-100" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/sync/agent/config?provider=custom:sage-100", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/sync/agent/config?provider=custom:sage-100",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "provider": "custom:sage-100",
  "objects": {
    "companies": {
      "mode": "sync",
      "options": {},
      "since": null
    },
    "contacts": {
      "mode": "sync",
      "options": {
        "cycle": ""
      },
      "since": null
    },
    "orders": {
      "mode": "sync",
      "options": {
        "months": 24,
        "lines": false
      },
      "since": null
    },
    "invoices": {
      "mode": "sync",
      "options": {
        "months": 24,
        "lines": false
      },
      "since": null
    }
  },
  "interval_min": 60,
  "run_id": "vVAO_Wf0K6M"
}
GET/sync/{provider}/countries

Customers per country

How many companies of this source are in each country, and how many have no salesperson — to set country_owners.

Scope: read

Path parameters

providerstringrequired
Source id: odoo, sap_b1, shopify, custom:sage-100…
Request
curl "https://meetzy.me/api/v1/sync/custom:sage-100/countries" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/sync/custom:sage-100/countries", {
  headers: { Authorization: `Bearer ${process.env.MEETZY_API_KEY}` },
});
const data = await res.json();
import os, requests

res = requests.get(
    "https://meetzy.me/api/v1/sync/custom:sage-100/countries",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "countries": [
    {
      "country": "Nigeria",
      "companies": 41,
      "without_salesperson": 41
    },
    {
      "country": "France",
      "companies": 812,
      "without_salesperson": 3
    }
  ]
}
DELETE/sync/{provider}

Disconnect a source

Stops syncing and forgets the credentials (and the source’s own key, if any). Records already brought in stay.

Scope: delete

Path parameters

providerstringrequired
Source id: odoo, sap_b1, shopify, custom:sage-100…
Request
curl -X DELETE "https://meetzy.me/api/v1/sync/custom:sage-100" \
  -H "Authorization: Bearer $MEETZY_API_KEY"
const res = await fetch("https://meetzy.me/api/v1/sync/custom:sage-100", {
  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/sync/custom:sage-100",
    headers={"Authorization": f"Bearer {os.environ['MEETZY_API_KEY']}"},
)
data = res.json()
Response200
{
  "ok": true
}

Field reference

Send records in your own field names — or these canonical ones. Names are compared without case, accents, spaces or punctuation (N° Facture reads as nfacture); a few of the recognised names are listed per field — there are many more, in English, French, German, Spanish and the SAP / Odoo / Sage vocabularies. Unknown fields are kept in extra. Documents (quotes, orders, invoices, credit_notes) share the same fields; lines unlock brand and product analytics.

Companies

FieldWhat it isAlso recognised
external_idrequiredId in your system (customer code) — required to update laterid · externalref · sourceid · erpid · uid
namerequiredCompany namecompanyname · company · account · accountname · customer
domainEmail domain (lumiere.fr): matches companies Meetzy already knowsemaildomain · websitedomain
websiteWebsiteurl · site · web · siteweb · homepage
emailGeneric email — its domain is used when there is no websitemail · emailaddress · courriel · e_mail
phonePhonetelephone · tel · phonenumber · phone1 · mobile
addressStreetadresse · street · address1 · addressline1 · street1
zipPostal codezipcode · postalcode · postcode · codepostal · cp
cityCityville · town · locality · commune · stadt
countryCountry — name or 2-letter codepays · countryname · countrycode · land · pais
industryIndustrysector · secteur · activity · activite · branche
employeesHeadcountheadcount · employeecount · nbemployees · numberofemployees · effectif
typecustomer · lead · supplierkind · customertype · partnertype · cardtype · relationship
vat_numberVAT / tax numbervat · vatid · taxid · tva · numerotva
groupCustomer group in your systemgroupe · customergroup · groupname · groupcode · bpgroup
payment_termsPayment termsterms · conditionsdepaiement · paymentcondition · pymntgroup
currencyDefault currencydevise · currencycode · curr
credit_limitCredit limitcreditline · limitedecredit
balanceAccount balanceaccountbalance · solde · balancedue · currentbalance
owner{ code, name, email } — the salesperson; mapped to a Meetzy user in Integrationssalesperson · salesrep · rep · seller · accountmanager
owner_emailOwner by email (a Meetzy user)salespersonemail · repemail · assignedto · assignee · assignedemail
tagsList of labelslabels · tag · label · etiquettes · groups
linkedin_urlLinkedIn pagelinkedin · linkedincompanypage
notesFree textnote · comment · comments · remarks · description
updated_atLast change — lets Meetzy skip unchanged recordsmodified · modifiedat · lastmodified · lastmodifieddate · writedate
extraAny other fields: kept and shown on the companycustom · customfields · meta · metadata · properties
Example record
{
  "external_id": "C-1001",
  "name": "Parfumerie Lumière",
  "domain": "lumiere.fr",
  "phone": "+33 4 72 00 00 00",
  "city": "Lyon",
  "country": "FR",
  "type": "customer",
  "industry": "Retail",
  "owner": {
    "code": "12",
    "name": "Alice Martin",
    "email": "alice@yourcompany.com"
  },
  "tags": [
    "Perfumery"
  ],
  "updated_at": "2026-10-01T09:00:00Z"
}

Contacts

FieldWhat it isAlso recognised
external_idId in your systemid · externalref · sourceid · erpid · uid
first_nameFirst nameprenom · givenname · first · forename · vorname
last_nameLast namenom · surname · familyname · last · nachname
nameFull name, when not splitfullname · contactname · displayname · person · nomcomplet
emailrequiredEmail — matches contacts Meetzy already knowsprimaryemail · mail · emailaddress · courriel · e_mail
phonePhonetelephone · tel · phonenumber · mobile · mobilephone
titleJob titlejobtitle · position · fonction · role · job
company_external_idId of the company in your system (links to it)companyid · accountid · customerid · customercode · clientid
companyCompany namecompanyname · organization · organisation · societe · account
cityCityville · town · locality
countryCountrypays · countryname · countrycode
lifecyclelead · mql · sql · opportunity · customerlifecyclestage · stage · statut · leadstatus · contactstatus
owner{ code, name, email }salesperson · salesrep · rep · seller · accountmanager
owner_emailOwner by emailsalespersonemail · repemail · assignedto · assignee · assignedemail
tagsList of labelslabels · tag · label · etiquettes · groups
linkedin_urlLinkedIn profilelinkedin · linkedinprofile · linkedinprofileurl
updated_atLast changemodified · modifiedat · lastmodified · lastmodifieddate · writedate
Example record
{
  "external_id": "P-5002",
  "first_name": "Nadia",
  "last_name": "Benali",
  "email": "nadia@lumiere.fr",
  "phone": "+33 6 00 00 00 00",
  "title": "Buyer",
  "company_external_id": "C-1001",
  "company": "Parfumerie Lumière",
  "country": "FR",
  "owner_email": "alice@yourcompany.com",
  "updated_at": "2026-10-01T09:00:00Z"
}

Deals

FieldWhat it isAlso recognised
external_idrequiredId in your systemid · externalref · sourceid · erpid · uid
namerequiredDeal nametitle · dealname · opportunity · opportunityname · subject
amountAmountvalue · total · expectedrevenue · montant · revenue
currencyCurrencydevise · currencycode · dealcurrencycode
statusopen · won · loststate · dealstatus · outcome · result · won
stage_nameStage name — matched to your Meetzy pipeline stages by namestage · dealstage · etape · pipelinestage · step
probability0–100probabilite · winprobability · likelihood
close_dateExpected or actual close dateexpectedclosedate · closingdate · datecloture · close · expectedclose
company_external_idId of the companycompanyid · accountid · customerid · customercode · clientid
contact_external_idsIds of the contactscontactids · contacts · personids · contactexternalid · contactid
owner{ code, name, email }salesperson · salesrep · rep · seller · accountmanager
owner_emailOwner by emailsalespersonemail · repemail · assignedto · assignee · assignedemail
updated_atLast changemodified · modifiedat · lastmodified · lastmodifieddate · writedate
Example record
{
  "external_id": "D-77",
  "name": "Spring order — Lumière",
  "amount": 12500,
  "currency": "EUR",
  "status": "open",
  "stage_name": "Proposal",
  "close_date": "2026-11-15",
  "company_external_id": "C-1001",
  "contact_external_ids": [
    "P-5002"
  ],
  "owner_email": "alice@yourcompany.com"
}

Products

FieldWhat it isAlso recognised
external_idId in your system (or the SKU)id · externalref · sourceid · erpid · uid
skurequiredSKU / item codeitemcode · reference · ref · code · productcode
namerequiredNametitle · productname · nom · designation · libelle
descriptionDescriptionlongdescription · body · bodyhtml · details · remarks
unit_priceSales priceprice · prix · prixunitaire · prixht · salesprice
currencyCurrencydevise · currencycode · curr
costUnit costunitcost · cout · prixachat · purchaseprice · costprice
tax_pctVAT %vat · tva · tax · taxrate · vatrate
barcodeEAN / GTINean · ean13 · gtin · upc · codebarre
categoryCategorycategorie · itemgroup · itmsgrpnam · groupe · productgroup
brandBrandmarque · vendor · manufacturer · fabricant · maker
stock_qtyStockstock · instock · onhand · quantity · qty
unitUnitunite · uom · salesunit · unitofmeasure · baseunit
image_urlImage URLimage · imagesrc · picture · photo · imagelink
urlProduct pagelink · producturl · permalink · productpage
activetrue / falseactif · status · valid · enabled · published
Example record
{
  "external_id": "SKU-100",
  "sku": "SKU-100",
  "name": "Eau de parfum 50 ml",
  "unit_price": 42,
  "currency": "EUR",
  "cost": 18,
  "barcode": "3401234567890",
  "category": "Fragrances",
  "brand": "Maison X",
  "stock_qty": 120,
  "active": true
}

Quotes, orders, invoices, credit notes

FieldWhat it isAlso recognised
external_idrequiredId in your system — or the numberid · externalref · sourceid · erpid · uid
numberNumber shown to the customerdocnumber · documentnumber · docnum · invoicenumber · invoiceno
typeinvoice · order · quote · credit_note (only for a mixed "documents" batch)doctype · documenttype · kind · movetype · typedocument
daterequiredDocument datedocdate · documentdate · invoicedate · orderdate · issuedate
due_dateDue date (invoices) or validity date (quotes)due · paymentdue · echeance · dateecheance · datedecheance
statusopen · paid · closed · cancelled — or whatever your system says; worked out from the amounts when missingstate · paymentstatus · paymentstate · paidstatus · documentstatus
company_external_idrequiredId of the customer in your system — matches companies by their codecustomerid · customercode · clientid · clientcode · partnerid
company_nameCustomer name — used when the id is unknown to Meetzycustomer · customername · client · clientname · company
contact_external_idId of the contactcontactid · personid · cntctcode · contactpersoncode
currencyCurrencydevise · currencycode · cur · doccurrency · currencyid
totalrequiredTotal incl. taxamount · grandtotal · totalttc · ttc · amounttotal
net_totalTotal excl. tax — analytics use itsubtotal · net · amountuntaxed · totalht · ht
tax_totalTaxtax · vat · tva · amounttax · taxamount
paidAmount received so farpaidamount · amountpaid · paidtodate · payments · settled
unpaidAmount still due (either paid or unpaid is enough)balance · amountdue · amountresidual · outstanding · remaining
linesArray of { sku, name, quantity, unit_price, discount_pct, total } — brands and products analytics need themitems · lineitems · details · positions · rows
owner{ code, name, email } — the salespersonsalesperson · salesrep · rep · seller · accountmanager
customer_refCustomer PO / referenceponumber · purchaseorder · customerreference · yourreference · clientorderref
notesCommentsnote · comment · comments · remarks · memo
updated_atLast changemodified · modifiedat · lastmodified · lastmodifieddate · writedate
Example record
{
  "external_id": "INV-2026-0412",
  "number": "F2026-0412",
  "date": "2026-09-30",
  "due_date": "2026-11-29",
  "status": "open",
  "company_external_id": "C-1001",
  "company_name": "Parfumerie Lumière",
  "currency": "EUR",
  "total": 1500,
  "net_total": 1250,
  "tax_total": 250,
  "paid": 500,
  "lines": [
    {
      "sku": "SKU-100",
      "name": "Eau de parfum 50 ml",
      "quantity": 24,
      "unit_price": 42,
      "discount_pct": 0,
      "total": 1008
    }
  ],
  "owner": {
    "code": "12",
    "name": "Alice Martin"
  },
  "customer_ref": "PO-889"
}

How records are matched

OrderCompaniesContactsDocuments
1Same source and id (external_id)Same source and idSame source, type and id
2Customer code in any source (custom.erp.code)Email address—
3Email / website domainCompany by company_external_idCustomer by company_external_id → code
4Normalised name (“ACME S.A.S.” = “Acme SAS”)—Customer by name — created when unknown

Dates: ISO, DD/MM/YYYY, MM/DD/YYYY (decided on the whole batch, or forced with date_order), Excel serial numbers, Unix timestamps. Numbers: 1 234,56, 1,234.56, €1.234,56. Countries: names in any language or ISO codes. Statuses: open, paid, closed, cancelled — or what your system writes (Soldée, bezahlt, O/C…); worked out from the amounts when missing.