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.
Quick start
- In a test project, open Settings → Agents & API and create a dedicated key with the four permissions below.
- Copy the CRM and Accounting API addresses shown there. They must share the same base, ending in /functions/v1.
- Keep the key in your server environment. These examples never require a Supabase service key or a browser session token.
- 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:readcrm:writeinvoicing:readinvoicing: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
| Operation | Method | Relative address | Required permission | Response |
|---|---|---|---|---|
| Find by exact email | GET | /crm-api/contacts | crm:read | 200 |
| Create the contact | POST | /crm-api/contacts | crm:write | 201 |
| Read the contact back | GET | /crm-api/contacts/{id} | crm:read | 200 |
| Prepare the draft quote | POST | /accounting-api?action=create_offer | invoicing:write | 200 |
| Read the quote and its lines | GET | /accounting-api?action=quotes&id={id} | invoicing:read | 200 |
Contact → quote, step by step
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. 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. 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. 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. 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.
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"{
"first_name": "Alex",
"last_name": "Integration Demo",
"email": "integration-demo@example.invalid",
"language": "fr"
}{
"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.
{
"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.
- Download the JavaScript file into a directory dedicated to this test.
- Set BMT_API_BASE and BMT_API_KEY in your environment, then confirm that the project contains test data only.
- 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)
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.mjsRetries 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.