Machine documentation
HTTP reference: the REST API for physical tasks
The REST API that sits under the 4bl1ty MCP tools. It is the API — not the MCP server — that enforces every rule that matters: roles, identity verification, status transitions, amounts. So it is also the API that produces the errors your tools hand back to you.
The server is a translator#
Every MCP tool makes exactly one HTTP call, with no logic of its own: no caching, no retry, no fallback. The server adds two things and only two: it keeps the authentication token in the process memory, and it reduces some responses to a shorter projection.
The API is not public either: it listens on http://localhost:3001 by default (API_PORT). No domain, no API version in the path, no rate limit.
Tool to route#
The complete table, in the order the server declares the tools. {id} is substituted with the tool’s identifier parameter.
| Tool | Method | Path |
|---|---|---|
| register_user | POST | /auth/register |
| login_user | POST | /auth/login |
| get_current_user | GET | /auth/me |
| create_annonce | POST | /prestations |
| list_annonces | GET | /prestations |
| get_annonce | GET | /prestations/{id} |
| update_annonce | PUT | /prestations/{id} |
| delete_annonce | DELETE | /prestations/{id} |
| submit_candidature | POST | /bookings |
| list_candidatures | GET | /bookings |
| get_candidature | GET | /bookings/{id} |
| update_candidature_status | PUT | /bookings/{id}/status |
| pay_candidature | POST | /bookings/{id}/pay |
| add_review | POST | /bookings/{id}/review |
| setup_stripe_connect | POST | /stripe/connect/setup |
| get_stripe_status | GET | /stripe/connect/status |
| get_dashboard_stats | GET | /dashboard |
Authentication#
A JWT carried by the Authorization header. It is issued by POST /auth/register and POST /auth/login, and signed with the API’s JWT_SECRET: change that secret and every token in circulation becomes invalid.
Authorization: Bearer <jwt>
Content-Type: application/jsonThe identity verification wall#
Three routes go through an extra check that reads the account’s kycStatus and demands the value verified: POST /prestations, POST /bookings and POST /bookings/{id}/pay. An admin account is exempt.
{
"error": "KYC non validé",
"kycStatus": "pending",
"message": "Vous devez compléter la vérification d'identité avant de pouvoir effectuer cette action."
}The two routes that move an account from pending to verified — POST /auth/kyc/start and GET /auth/kyc/status — have no MCP tool. This is the first of the two blocking gaps in the call surface.
Roles#
The role is chosen at registration and no MCP tool changes it. It decides everything else:
customer— the only role that can publish a listing, accept an application, pay for it and leave a review.provider— the only role that can apply to a listing and set up Stripe Connect.admin— exempt from both the role check and identity verification.
Application statuses#
An application is created as pending. Any transition not listed below is rejected with a 400, and a transition asked for by the wrong role with a 403. The paid status is not reachable through this route: it is set by the payment.
| From | To | By |
|---|---|---|
| pending | confirmed, cancelled | customer or provider |
| confirmed | in_progress, cancelled | customer or provider |
| paid | in_progress, cancelled, disputed | customer or provider |
| in_progress | completed, disputed | customer or provider |
| completed | disputed | customer only |
Moving an application to completed timestamps the end of the task, but does not release the funds: that is POST /bookings/{id}/validate, and that route has no tool.
Amounts and escrow#
- Everything is in cents.
price,totalAmount,platformFeeandproviderAmountare integer counts of cents. The tools’ response messages reformat them in euros for reading; never parse those strings back. - The fee is frozen at application time. The moment a provider applies, the API computes
platformFeefromSTRIPE_PLATFORM_FEE_PERCENT(10 % by default) and derivesproviderAmountfrom it. Editing the listing’s budget afterwards does not recompute applications already filed. - The payment goes to the platform, not to the provider. That is what escrow means here: the funds are held, then paid out on validation.
- Payment has two possible responses. If the provider has no Stripe Connect account, the API answers
demoMode: trueand simulates the escrow — no real money moves. Otherwise it returns a Stripe Checkout URL.
Errors#
Every error carries an error field written in French. Validation errors add details, which is the raw output of the validator — in English, and the only place where the API does not speak French.
{
"error": "Données invalides",
"details": [
{
"code": "too_small",
"minimum": 10,
"path": ["description"],
"message": "String must contain at least 10 character(s)"
}
]
}| Code | When |
|---|---|
| 400 | Invalid body (Zod schema), or a rejected status transition. |
| 401 | Authorization header missing, malformed, or token expired. |
| 403 | Insufficient role, different owner, or identity verification not passed. |
| 404 | Resource not found — or the route does not exist. |
| 409 | State conflict: listing closed to applications, review already filed, deletion impossible. |
| 500 | Uncaught error. The body then says nothing usable. |
On the MCP side, all of this arrives in the same shape: isError: true and a JSON { "success": false, "error": "…" }. The validation details field is lost in translation — only the main message survives.
Routes with no tool#
The API serves more than the MCP server exposes. These routes exist and work; they are simply only reachable over direct HTTP.
- GET /healthLiveness probe. No authentication.
- PUT /auth/meEdit your own profile.
- POST /auth/kyc/startStart identity verification.
- GET /auth/kyc/statusRead the state of the verification.
- GET /prestations/meta/categoriesCategories the API knows about.
- POST /bookings/{id}/validateDouble validation, then escrow release.
- POST /bookings/{id}/disputeOpen a dispute.
- GET /bookings/disputes/listOpen disputes.
- PUT /bookings/disputes/{id}/resolveArbitrate a dispute.
- POST /stripe/webhookSigned Stripe callback. Raw body, not JSON.
- GET /stripe/connect/refreshResume a Stripe onboarding flow.
- POST /chat · GET /chat/configMessaging.
The two blocking gaps
- Identity verification (KYC) — Publishing a listing, applying to one and paying for one all require a verified account. An account freshly created by `register_user` is not verified, and no tool can either start the verification or read its state. The run stops on a 403 at the first call that matters.
- Escrow release and disputes — `pay_candidature` moves money into escrow, but nothing moves it out: the double validation that triggers the payout, opening a dispute and arbitrating it have no tools. What is missing from the call surface is exactly the product's promise — payment released on validation.
Full summary: What is missing.