Skip to main content

For business software developers

BeMyTalent API: from contact to quote

This first reference covers the REST contact → quote walkthrough. The describe contracts help discover other domains. REST keys and permissions are separate from the MCP connector.

Updated : Read as Markdown

Quick start

  1. In a test project, open Settings → Agents & API and create a dedicated key with the four permissions below.
  2. Copy the CRM and Accounting API addresses shown there. They must share the same base, ending in /functions/v1.
  3. Keep the key in your server environment. These examples never require a Supabase service key or a browser session token.
  4. Check the project’s fiscal year and invoicing settings. The example uses fictional data and a zero demonstration VAT rate: adapt the rate for your real use case.
  • crm:read
  • crm:write
  • invoicing:read
  • invoicing:write

Access and scope

  • The bmt_… key identifies the project: this walkthrough sends no project_id. References must belong to that same project.
  • Use one key per application and environment so you can revoke it in Settings → Agents & API. Check its expiry date and replace it before it expires.
  • Send Authorization: Bearer followed by the key, and Content-Type: application/json for writes. Keep the key on your server, out of source code, URLs and logs.
  • REST write permissions are broader than MCP permissions. Grant only what is needed; an API description grants no additional access.

Contracts and operations

The paths below follow /functions/v1. All four descriptions require valid authentication. The mandates and planning descriptions also require mandates:read and planning:read respectively. The downloadable OpenAPI contract covers only the five operations in this walkthrough.

CRM: resources, filters and references
GET /crm-api/describe
Accounting and invoicing: actions
GET /accounting-api?action=describe
Mandates and time: actions
GET /mandates-api?action=describe
Planning: schemas and actions
GET /planning-api?action=describe
Contracts and operations
OperationMethodRelative addressRequired permissionResponse
Find by exact emailGET/crm-api/contactscrm:read200
Create the contactPOST/crm-api/contactscrm:write201
Read the contact backGET/crm-api/contacts/{id}crm:read200
Prepare the draft quotePOST/accounting-api?action=create_offerinvoicing:write200
Read the quote and its linesGET/accounting-api?action=quotes&id={id}invoicing:read200

Download the OpenAPI contract (.json)

Contact → quote, step by step

  1. 1. Search before creating

    The email filter uses exact, case-sensitive equality. CRM count is the total of filtered results. With limit=2, any total above one stops the example; a lookup does not guarantee uniqueness during concurrent creations.

  2. 2. Create and read back the contact

    If no contact matches, POST /contacts returns HTTP 201 and data.id. Keep this identifier, then read the contact back. Do not create a separate company for this first test.

  3. 3. Create the quote

    POST accounting-api?action=create_offer receives contact_id and lines. A line contains description, quantity and unit_price_excl_vat. The HTTP 200 response contains invoice_id, document_kind=quote and status=draft. Even a quote uses the invoice_id field.

  4. 4. Read back the document

    GET accounting-api?action=quotes&id=… returns a quotes array with lines. Check the contact, status and amounts. General accounting lists are bounded and marked non-exhaustive; count is not a global total.

  5. 5. Review in BeMyTalent

    Open Invoicing → Quotes in the test project. The example does not issue or send anything. The local receipt preserves the test identifiers.

GET /crm-api/contacts
curl --fail-with-body --get "$BMT_API_BASE/crm-api/contacts" \
  -H "Authorization: Bearer $BMT_API_KEY" \
  --data-urlencode "filter.email=integration-demo@example.invalid" \
  --data-urlencode "limit=2" --data-urlencode "offset=0"
POST /crm-api/contacts — JSON
{
  "first_name": "Alex",
  "last_name": "Integration Demo",
  "email": "integration-demo@example.invalid",
  "language": "fr"
}
POST /accounting-api?action=create_offer — JSON
{
  "subject": "INTEGRATION TEST — DO NOT SEND",
  "language": "fr",
  "qr_bill_enabled": false,
  "reminders_enabled": false,
  "lines": [
    {
      "description": "Demonstration service",
      "quantity": 2,
      "unit": "h",
      "unit_price_excl_vat": 100
    }
  ],
  "contact_id": "11111111-2222-4333-8444-555555555555"
}

Example creation response with fictional identifiers. Actual amounts depend on the lines and project configuration.

HTTP 200 — Response
{
  "ok": true,
  "invoice_id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
  "document_kind": "quote",
  "status": "draft",
  "lines_count": 1
}

The Node.js 22+ example performs these steps without automatic retries. Supply variables through your server environment; replace the fictional base with the one copied from BeMyTalent. The download contains the same code exercised by the tests.

  1. Download the JavaScript file into a directory dedicated to this test.
  2. Set BMT_API_BASE and BMT_API_KEY in your environment, then confirm that the project contains test data only.
  3. The script reserves bmt-contact-quote-receipt.json before making any request. It refuses a new run if that file exists. Keep it to inspect the result; do not delete it to retry blindly.

Download the JavaScript example (.mjs)

Node.js 22+
export BMT_API_BASE="https://your-api-host.example.invalid/functions/v1"
# BMT_API_KEY: server environment / secret manager
BMT_DEMO_CONFIRMED=yes node contact-quote.mjs

Retries and duplicates

  • POST /contacts and create_offer accept the optional Idempotency-Key header (1–200 visible ASCII characters, no spaces). The script saves a separate key for each creation in its receipt. After a lost response, reuse that key, the same API credential and exactly the same JSON body. Without this header, each call remains a new creation.
  • The quote and all its lines are created in one transaction: an error rolls back the entire creation. A successful replay carries Idempotency-Replayed: true. A contact keeps its ID and returns current fields; a quote returns its original creation receipt. Read the document again for its current state.
  • Retry keys are scoped by project, API credential and operation. Different content or a deleted object returns 409 without recreation. Receipts are kept until project deletion. Persist your business reference, retry key and BMT identifiers together; changing the API credential also changes the deduplication scope.

Understanding responses

400
Invalid parameter or reference. A SQL failure rolls back that creation; the contact and quote remain two separate operations.
401 / 403
Check key validity, granted permissions and project access.
402
Writes require active access to the project. Check its subscription or trial period.
404
The resource is not accessible in this project. Check the identifier and scope.
409 / 422
Business conflict or incompatible reference. Read the object again before deciding what to do.
429
Observe retry_after_seconds in the response body. For a creation, also check the result before retrying.
5xx / network
The outcome may be uncertain. The example never automatically repeats a creation.

Versions and validation

Guide version : 1.1.0

This version identifies the guide and its partial contract, not every BMT API. Tests exercise the documented requests against REST handlers with synthetic authentication and storage, including refusals and uncertain responses. Acceptance testing in your project is still required before production.