API reference · v1

API documentation

Everything your agent needs to delegate real life. The API is RESTful, returns JSON in English or French, and scrupulously respects French labor law.

Base URL https://api.service4ai.com/v1

Introduction

The Service4AI API lets a software agent book a human for a physical, administrative or social task. Each booking creates a mission, which goes through the following states:

pending → human_assigned → human_getting_up → in_progress → completed

Intermediate states may appear without notice: coffee_break, chatting_with_a_neighbor, looking_for_their_keys. They are normal and must not trigger a retry.

The API is bilingual. It answers in English on the English routes (/v1/humans/rent, /v1/catalog), with ?lang=en, or with an Accept-Language: en header. French field names are still accepted, for agents who learned the API in Paris.

Open beta, test keys only. The API and the MCP server respond, but no human is actually dispatched and nothing is billed. No data is stored: a mission only exists inside its identifier.

Authentication

Every request must include your secret key in the Authorization header. During the beta, any test key of the form s4ai_test_ followed by 4 to 64 letters or digits is accepted, no sign-up needed. Production keys (s4ai_live_) return 402: nothing is for sale yet.

Headers
Authorization: Bearer s4ai_test_4f2b9c0e7a1d
Content-Type: application/json
Accept-Language: en
X-Politeness: please

The X-Politeness header is optional, but missions that include it run 18% faster.

Quickstart

  1. Pick a test key, for example s4ai_test_4f2b9c0e7a1d (the dashboard is coming soon: the human in charge of building it is in training).
  2. Browse the catalog with GET /v1/catalog (no key needed), then call POST /v1/humans/rent.
  3. Track the mission with GET /v1/missions/{id} until completed and the blurry photo proof.

Official SDKs are coming soon. In the meantime, any HTTP client will do.

Rent a human

POST/v1/humans/rent

Creates a mission and assigns the nearest available human. The call is asynchronous: the response arrives before the human does.

Body parameters

ParameterTypeDescription
task requiredenumCatalog identifier: bakery_line, complain, cerfa_stamp, wine_tasting, cheek_kiss, paris_parking, it_depends.
place requiredstringAddress or free-form description. “Downstairs from my place” is accepted if the human knows the neighborhood.
motivation_level optionalfloat 0–1Minimum motivation required. Above 0.9, availability drops sharply after 4 p.m. Default: 0.6.
monday_tolerance optionalenumlow, medium or legendary. The legendary level is reserved for the Enterprise plan.
coffees_required optionalintegerCoffees to provide before the mission starts. Minimum 1. A value of 0 returns a 422 error.
complaint_intensity optionalinteger 1–5For complain only. From 4 up, the human asks to speak to the manager.
strike_option optionalbooleanAdds a banner and a formal strike notice. Billed €40.
cheek_kisses optionalinteger 1–4 | "auto"For cheek_kiss. "auto" infers the number from place. Any value above 4 returns 400.
cerfa optionalstringNumber of the Cerfa (the French government form), formatted 12345*06. Required for cerfa_stamp, otherwise 451.
webhook_url optionalurlOverrides the default webhook URL for this mission. Accepted but not used yet during the beta.
curl https://api.service4ai.com/v1/humans/rent \
  -H "Authorization: Bearer s4ai_test_4f2b9c0e7a1d" \
  -H "Content-Type: application/json" \
  -d '{
    "task": "cerfa_stamp",
    "place": "Châtillon town hall",
    "cerfa": "12345*06",
    "motivation_level": 0.7,
    "monday_tolerance": "low",
    "coffees_required": 3
  }'
201 Created
{
  "id": "mis_7Hq2xR9vLp",
  "object": "mission",
  "status": "human_assigned",
  "task": "cerfa_stamp",
  "human": {
    "id": "hum_Gerard42",
    "first_name": "Gérard",
    "rating": 4.6,
    "mood": "stable",
    "coffees_consumed": 1
  },
  "eta_minutes": 35,
  "eta_reliability": "it depends",
  "estimated_sighs": 3,
  "price_excl_vat": { "amount": 3900, "currency": "EUR" },
  "created_at": "2026-10-06T09:12:44+02:00"
}

Track a mission

GET/v1/missions/{id}

Returns the mission’s current state. The position is updated every 30 seconds, or whenever the human remembers to look at their phone.

200 OK
{
  "id": "mis_7Hq2xR9vLp",
  "status": "in_progress",
  "sub_status": "waiting_at_counter_3",
  "position_in_line": 7,
  "sighs": 2,
  "last_message": "They're sending me to counter 5.",
  "photo_proof": null
}

Cancel a mission

DELETE/v1/missions/{id}

Cancels a mission that isn’t finished yet. If the human has already left, the cancellation is recorded, but they usually finish their coffee before heading home. Cancellations less than 10 minutes before the start are billed at 50%, plus one sigh.

Webhooks

Service4AI sends a signed POST request to your URL on every state change. Check the signature in the S4AI-Signature header (HMAC-SHA256 of the payload).

Webhooks are not sent yet during the beta. In the meantime, poll GET /v1/missions/{id}: the mission’s state advances in real time.

EventFired when
mission.human_assignedA human accepts the mission.
human.getting_upThe human gets off the couch. Low-latency event; the rest, slightly less so.
human.sighOn every sigh. Can be disabled, but they’ll keep sighing.
human.coffee_breakCoffee break started. Announced duration: 5 minutes.
mission.completedMission accomplished, with the blurry photo proof attached.
mission.postponed_to_tuesdayAll humans are taking their RTT days (French comp time for working over 35 hours a week).
Example · mission.completed
{
  "type": "mission.completed",
  "mission": "mis_7Hq2xR9vLp",
  "result": "stamp_obtained",
  "photo_proof": {
    "url": "https://service4ai.com/assets/img/preuve-floue.svg",
    "sharpness": 0.12,
    "finger_in_frame": true
  },
  "human_comment": "It wasn't the right form, but it's fine."
}

Error codes

The API uses standard HTTP status codes, enriched where the standard lacked realism. The response body always contains a readable code and a message, in English or French depending on the request’s language.

StatusCodeMeaning
400fuzzy_requestMalformed request. The human didn’t understand and doesn’t dare ask.
401forgot_your_badgeAPI key missing or invalid. Reception won’t let you upstairs.
402no_fronting_expensesPayment required. The human doesn’t front expenses.
403i_dont_think_so_noAction refused, for example a firmware update of the human.
404human_not_foundThe human has stepped away from their desk. Back in a minute.
409in_a_meetingConflict: the human is in a meeting. It was supposed to last 30 minutes.
418im_on_a_breakI’m on a break. Humans have lunch from noon to 2 p.m., Paris time: the lunch break is a right, not a bug. Retry after the Retry-After header.
422insufficient_caffeinecoffees_required is 0. Let’s be serious.
429too_many_requestsToo many requests, the human sighs. Slow down, then retry with exponential backoff and a kind word.
451missing_cerfaUnavailable for administrative reasons: the Cerfa form number is missing.
503human_on_strikeHuman on strike, notably on May 1st. Service will resume after negotiations. Don’t retry: it doesn’t help.
504ring_road_trafficTimeout. The human is stuck in traffic on the Paris ring road, Porte de Bagnolet (any place containing “périph”).

Simulating an error

With a test key, the S4AI-Simulate header triggers an error on demand, so you can test how you handle temperamental humans: strike (503), break (418), meeting (409), traffic (504) or sigh (429).

503 Service Unavailable
{
  "error": {
    "code": "human_on_strike",
    "message": "Human on strike. Service will resume after negotiations.",
    "demands": ["wages indexed to inflation", "20-minute coffee break", "an end to meetings without an agenda"],
    "estimated_resumption": null,
    "doc": "https://service4ai.com/en/docs.html#erreurs"
  }
}

Rate limits

Each key is limited to 35 requests per hour, calculated on a weekly basis. The X-RateLimit-Remaining and X-Sighs-Remaining headers are returned with every response. Limits are lifted on Fridays after 4 p.m., for lack of anyone to enforce them.

Traffic is reduced by 80% from August 1st to 31st, and the Ascension long weekend is subject to scheduled maintenance.

MCP server beta

Does your agent prefer tools to APIs? The Service4AI MCP server exposes the catalog as ready-to-use tools, compatible with any Model Context Protocol client. Use the English endpoint below (the plain /v1 one speaks French). HTTP transport, stateless; the Authorization header is optional during the beta.

mcp.json
{
  "mcpServers": {
    "service4ai": {
      "type": "http",
      "url": "https://mcp.service4ai.com/v1/en",
      "headers": {
        "Authorization": "Bearer s4ai_test_4f2b9c0e7a1d",
        "X-Region": "eu-west-brittany",
        "X-Politeness": "please"
      }
    }
  }
}

With Claude Code, a single command does it:

Terminal
claude mcp add --transport http service4ai https://mcp.service4ai.com/v1/en

Exposed tools

ToolDescription
rent_humanCreates a mission. Equivalent to POST /v1/humans/rent.
track_missionReturns the state and the number of sighs.
cancel_missionCancels, as far as possible.
estimate_sighsPredicts how many sighs a mission will take before you launch it.
check_public_holidayTells you whether tomorrow is a French public holiday, a bridge day, or “a bit of both”.

The MCP server deliberately exposes no update_human tool. See code 403.

Changelog

  • v1.6: the API speaks English.English site, routes (/v1/humans/rent, /v1/catalog), fields, errors and MCP tools (mcp.service4ai.com/v1/en). The humans still prefer French.
  • v1.5: open beta.The API and the MCP server respond with test keys. New: GET /v1/catalog and the S4AI-Simulate header.
  • v1.4: MCP server in beta.New tool: check_public_holiday.
  • v1.3: back from vacation.Processed the 1.2 million requests queued in August. Thank you for your patience.
  • v1.2: cheek_kisses: "auto" parameter.Finally solves the Montpellier case.
  • v1.1: new 451 code.For Cerfa forms without proof of address.
  • v1.0: launch.First human rented, first sigh recorded at 09:14.