Spendify MCP server
Spendify lets people share and split expenses with friends using a link, with no account. This page explains how an AI agent can create groups, add people and record expenses through the Spendify MCP server.
This page is documentation. The MCP endpoint is
https://sobrecodigo-api.azurewebsites.net/mcp, not
https://spendify.link/mcp. Send JSON-RPC requests to the
endpoint.
Quick start
Add the server to Claude Code:
claude mcp add --transport http spendify https://sobrecodigo-api.azurewebsites.net/mcp
Or call it directly, without an MCP client:
curl -X POST https://sobrecodigo-api.azurewebsites.net/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
The web app at spendify.link needs JavaScript, so fetching its pages as text only returns the landing copy. Don't scrape it; use the MCP server.
Connection
| Endpoint | https://sobrecodigo-api.azurewebsites.net/mcp |
|---|---|
| Transport |
HTTP POST with JSON-RPC 2.0. Responses are plain
application/json, never a stream.
|
| Requests | One request per call. Batches are rejected. |
| Authentication | None. There's no session; each request stands alone. |
| Protocol version | 2024-11-05 |
| Methods |
initialize, ping,
tools/list, tools/call
|
GET on the endpoint |
Returns a one-line text description with the tool names. |
Links and the group hash
Each group is identified by its hash, a UUID. Spendify links carry it
in the hash query parameter, in any of these forms:
https://spendify.link/gastos?hash=<hash>https://spendify.link/expenses?hash=<hash>https://www.spendify.link/expenses?hash=<hash>
When a user pastes a Spendify link, take the hash value
and pass it to the tools. Anyone with the hash can read and edit the
group, so treat it as a secret and don't post it publicly.
Tools
Tool names and argument names are exact. Field names are in Spanish.
tools/list returns the same schemas as JSON.
create_expense_link
Creates a new group.
| Argument | Type | Required | Description |
|---|---|---|---|
nombre | string | No | Group name. |
tipoHash | integer | No | 1 = monthly household expenses, 2 = trip (default), 3 = event. |
Returns hash, nombre and link.
Give the link to the user.
rename_expense_link
Renames a group.
| Argument | Type | Required | Description |
|---|---|---|---|
hash | string | Yes | Group hash. |
nombre | string | Yes | New name. |
add_person
Adds a person to the group. Returns the updated list of people.
| Argument | Type | Required | Description |
|---|---|---|---|
hash | string | Yes | Group hash. |
nombre | string | Yes | Person's name. |
list_people
Lists the people in the group. Returns data, an array of
{ id, nombre, cvu }.
| Argument | Type | Required | Description |
|---|---|---|---|
hash | string | Yes | Group hash. |
list_expense_types
Lists the group's expense categories. Returns an array of
{ id, descripcion }. New groups have: Vivienda,
Transporte, Alimentación, Salud, Inversión, Educación, Deudas y
Finanzas, Entretenimiento, Vestimenta y Cuidado Personal, Familia y
Mascotas, Emergencias e Imprevistos, Donaciones y Regalos, Otros,
Ahorros.
| Argument | Type | Required | Description |
|---|---|---|---|
hash | string | Yes | Group hash. |
create_expense
Adds an expense, with who paid and who shares it.
| Argument | Type | Required | Description |
|---|---|---|---|
hash | string | Yes | Group hash. |
descripcion | string | Yes | What the expense was. |
gasto | number | Yes | Total amount. |
pagadores | array | Yes, at least 1 |
Who paid. Each item is {"id": <person id>, "monto": <amount>}
or {"nombre": "<person name>", "monto": <amount>}.
If monto is omitted, it defaults to the full
gasto.
|
participantes | array | Yes, at least 1 |
Who shares the expense: person IDs ([4084, 4085])
or names (["Ana", "Beto"]). Payers are added to the
split automatically if they aren't listed.
|
tipoPago | string | No |
Payment method: Efectivo (cash),
Tarjeta (card) or Mercado Pago.
|
tipoGastoDescripcion | string | No |
Category, exactly as returned by
list_expense_types, accents included.
|
fileBase64, fileName | string | No | Receipt image, base64-encoded, and its file name. |
-
People must already exist in the group. Get IDs and names from
list_people, and add anyone missing withadd_personfirst. -
If
pagadoresorparticipantesis missing, or a name or ID isn't in the group, the call fails with HTTP 400 and nothing is saved. -
Returns
ok,descripcion,gasto, andpagadoresandparticipantesresolved to person IDs.
list_expenses
Lists the group's expenses. Returns data, an array of
expenses with id, gasto,
descripcion, created,
tipoGasto, tipoPago and
usuariosQueParticipanYPagan. In that last list,
tipoParticipacion 1 is a payer with their
monto, and 2 is a person in the split.
| Argument | Type | Required | Description |
|---|---|---|---|
hash | string | Yes | Group hash. |
Results and errors
-
A successful
tools/callreturnsresult.content[0].text, a JSON string. Parse it to read the data. -
A missing required field, a person who isn't in the group or an
unknown tool returns HTTP 400 with a JSON-RPC
error(code-32602). Messages are in Spanish, for exampleFalta el campo hash("missing field: hash") orNo existe el pagador 'Zoe' en este grupo("payer 'Zoe' doesn't exist in this group"). - Other failures return HTTP 500 with a JSON-RPC
error.
Full example
Add a 15000 dinner paid by Ana and split between Ana and Beto:
POST https://sobrecodigo-api.azurewebsites.net/mcp
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "create_expense",
"arguments": {
"hash": "<hash>",
"descripcion": "Cena",
"gasto": 15000,
"tipoPago": "Efectivo",
"tipoGastoDescripcion": "Alimentación",
"pagadores": [{ "nombre": "Ana", "monto": 15000 }],
"participantes": ["Ana", "Beto"]
}
}
}
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{\"ok\": true, \"hash\": \"<hash>\", \"link\": \"https://www.spendify.link/expenses?hash=<hash>\", \"descripcion\": \"Cena\", \"gasto\": 15000.0, \"pagadores\": [{\"id\": 4089, \"monto\": 15000.0}], \"participantes\": [4089, 4090]}"
}
]
}
}
Typical flow for a pasted link
- Take
hashfrom the link. -
Call
list_people,list_expensesandlist_expense_typesto see the group as it is now. - Add missing people with
add_person. -
Add each expense with
create_expense, using people fromlist_peopleand a category fromlist_expense_types. If the user doesn't say who paid or who shares the expense, ask before creating it. -
Call
list_expensesto confirm, then send the user the link to review in the app.
To start from scratch, call create_expense_link first
and give the user the returned link.
Things to watch for
-
An unknown hash is not an error: list tools return an empty
dataarray. If a pasted link shows no people and no expenses, check the hash before assuming the group is empty. -
If
tipoGastoDescripcionis missing or doesn't match a category exactly, the expense is filed under "Vivienda" without warning. - There's no currency field. Amounts are stored as plain numbers.
- Lists return everything in one page.
Machine-readable files
- llms.txt: this guide as Markdown.
- /.well-known/mcp.json: endpoint, transport and tool names as JSON.
- /.well-known/ard.json and ai-catalog.json: resource catalog for the site, including the MCP server.