# puertafria > Work a list of companies by cold call: which company is up today, the research > beside the call, and what happened after. This file is for agents. A person wants https://puertafria.es/agentes . Everything below is one account: the one whose key is presented. There are no scopes beyond read and write, and another account's row answers 404 rather than 403, so this door is never an oracle for what other accounts hold. ## Connecting 1. The account owner mints a key at https://puertafria.es/account , under the subscription panel. Pro plan or above: a free account is refused with 403 PLAN_API on every request, reads included. The key is shown once and stored as a hash, so it cannot be read back. 2. A key reads only, unless the box marked "may write" was ticked when it was minted. This cannot be changed later. Mint another. 3. Send it as a header, on every request: Authorization: Bearer pf_... Never as a query parameter, which the proxy's access log would keep. Never as the session cookie: a signed-in browser must not reach this by accident. 4. Ask what you are holding before you use it: curl -sS https://puertafria.es/api/v1/me -H "Authorization: Bearer $PUERTAFRIA_TOKEN" The answer names the plan and whether this key may write. Read it rather than discovering the limit by being refused. ## The envelope Every answer is JSON, and every answer is cache-control: no-store, because what comes back is research on named people at named companies. { "ok": true, "data": { } } { "ok": false, "reason": "COMPANY_GONE" } `reason` is the domain's own word. Never a sentence, never translated: you are a machine and those words are the vocabulary. The status follows the shape of the word. *_GONE is 404, PLAN_* is 403, a row whose state refuses (SUPPRESSED, NAME_TAKEN) is 409, anything else is 400. ## The reads GET /api/v1/me The account this key opens, its plan, and whether this key may change anything. tool: whoami GET /api/v1/funnels Every funnel this account holds. Start here: nothing else takes a funnel by name. tool: list_funnels GET /api/v1/funnels/:id One funnel: counts by stage, how many are due, its campaigns and provinces, and its tracking fields with their ids. tool: funnel GET /api/v1/funnels/:id/queue Who to call today. Takes ?stage= &campaign= &province= &q= &page=. A company that asked to stop is never in it. tool: queue GET /api/v1/companies/:id One card: the row, its branches, its people, its history, its tracking values and its reminders. tool: company GET /api/v1/funnels/:id/metrics One funnel's numbers over ?days=7, 30 or 90. Pro and above; the free plan answers 403 PLAN_METRICS. tool: metrics GET /api/v1/funnels/:id/export/:file prospects.csv, contacts.csv or activities.csv. For curl and a pipe, never offered as a tool. no tool, on purpose There is no last-looked-at state here. Ask /api/v1/funnels for the ids. ## The writes Each of these needs a key minted with writes, and each goes through the same core function the screen goes through, so it inherits the same refusals. POST /api/v1/companies/:id/activities What happened on a call. An outcome that leaves the company open needs nextActionAt; a losing one needs a note. tool: record_outcome PATCH /api/v1/companies/:id/tracking The funnel's own fields on one company, keyed by field id. A blank clears a value; a field left out is left alone. tool: save_tracking POST /api/v1/companies/:id/reminders A promise to come back to this company on a day. Pro and above. tool: add_reminder PATCH /api/v1/reminders/:id Tick a reminder off, put it back, or move it. Exactly one of those per call. tool: update_reminder PATCH /api/v1/companies/:id/branches/:locationId One researched fact about one branch. A blank value clears it. tool: edit_branch_fact POST /api/v1/funnels/:id/activate Move named companies into a campaign. Ids only, never a filter: read the queue first and send what you looked at. tool: activate_cohort POST /api/v1/funnels/:id/companies One company typed in, for when there is no file. Bulk loading is the import screen, not this. tool: add_company ## Rules you will meet - **Nothing deletes.** No route exports DELETE. You can append and correct. Removing a company, a funnel, a field or a reminder stays something a person does on a screen. A loop you run can make a mess somebody can read. It cannot make one that is gone. - **A no is forever.** A company recorded as DO_NOT_CONTACT leaves every queue and the server refuses another contact against it with SUPPRESSED. It is not a label you can clear. Do not try. - **An open outcome must say when it is picked up again.** Anything that does not end the deal is refused with NEXT_ACTION_REQUIRED without nextActionAt, and a losing outcome is refused without a note. - **Dates in are civil days, YYYY-MM-DD.** Never a timestamp. A reminder is about a day somebody works. - **The company comes off the URL and wins over the body.** A body naming another company cannot redirect a write authorised against this one. - **A cohort names its ids, never a filter.** Read the queue first and send what you actually looked at, up to 500. Each company is judged on its own and the answer says which were skipped and why. - **Adding companies one at a time is not bulk loading.** For a file, the import screen has a dry run. An agent inserting a thousand companies one request at a time would spend a day's budget doing badly what a file does well. - **500 write attempts per key per day.** Attempts, not successes: a loop being refused is the loop worth stopping. Over it, 429 WRITE_LIMIT. Reads never spend. ## Refusals before any handler runs 401 NO_TOKEN No Authorization header, or not a Bearer. 401 BAD_TOKEN Unknown, revoked or expired key. 403 PLAN_API The account is on the free plan. Connecting an agent is a Pro feature. 403 READ_ONLY The key was minted without writes, and this is not a GET. 429 WRITE_LIMIT More than 500 write attempts today on this key. 404 DEMO The demo instance answers 404 to all of it, before the header is even read. ## MCP There is an MCP server for this API. stdio, one process the agent's host spawns, offering the same 13 tools named above: whoami, list_funnels, funnel, queue, company, metrics, record_outcome, save_tracking, add_reminder, update_reminder, edit_branch_fact, activate_cohort, add_company. It holds no logic. Every tool is one request to the routes on this page, so the remoteness is the API and not the shim, and a read-only key is offered read-only tools rather than left to find a 403 by calling something. It is not published to a registry yet. Until it is, ask for it at https://puertafria.es/#contacto . Nothing is lost by waiting: the HTTP above is the whole product, and an agent that can make a request can already work the funnel. ## What this is not - Not a CRM. No deals, no quotes, no pipeline of your own shape. - Not a bulk loader. That is a CSV and a screen with a dry run. - Not a place to read the export from. That route exists and is deliberately not a tool: a thousand rows of research on named people does not belong in a context window nobody asked to put it in.