holded-skill
Use holdedcli to read and modify Holded data with a safe, repeatable workflow.
Operational Flow
- Confirm technical prerequisites.
- Discover available actions with
holded actions list. - Inspect the selected action with
holded actions describe <action> --json. - Classify the action as read or write.
- If it is a write operation, ask for explicit confirmation before execution.
- Run with
--jsonand summarize IDs, HTTP status, and applied changes.
Prerequisites
- Verify that the binary exists:
holded help - Verify credentials:
holded auth statusorHOLDED_API_KEY - Prefer structured output whenever possible:
--json
Safety Rules
- ALWAYS check deductibility rules BEFORE creating any document. See "Accounting Rules for Spain" section below.
- Treat any
POST,PUT,PATCH, orDELETEaction as write. - Treat any
GETaction (orHEADwhen present) as read. - Before any operation, always run
holded actions describe <action> --json(afterholded actions list) to validate accepted parameters. - For purchase receipts, always enforce
docType=purchaseand include"isReceipt": truein the JSON body. Since holdedcli validates against Holded's schema (which doesn't includeisReceipt), you must use--skip-validationflag. - Ask for explicit user confirmation every time before any write action.
- Do not execute writes on ambiguous replies (
ok,go ahead,continue) without clarification. - Repeat the exact command before confirmation to avoid unintended changes.
- If the user does not confirm, stop and offer payload adjustments.
Mandatory Confirmation Protocol
Before any write action, show:
- Holded action (
action_idoroperation_id). - Method and endpoint.
--path,--query, and body parameters (--bodyor--body-file).- The exact command to run.
Use this format:
This operation will modify data in Holded.
Action: <action_id> (<METHOD> <endpoint>)
Changes: <short summary>
Command: holded actions run ... --json
Do you confirm that I should run exactly this command? (reply with "yes" or "confirm")
Execute only after an explicit affirmative response.
Execution Pattern
Read Operations
- Locate the action with
holded actions list --json(use--filter). - Verify accepted path/query/body parameters with
holded actions describe <action> --json. - Run
holded actions run <action> ... --json. - Return a clear summary and relevant IDs for follow-up steps.
Write Operations
- Locate and validate the action.
- Run
holded actions describe <action> --jsonto verify required/optional parameters. - Prepare the final payload.
- If creating a purchase receipt/ticket, verify
docType=purchaseand"isReceipt": true, and use--skip-validationflag. - Request mandatory confirmation.
- Run the command after confirmation.
- Report result (
status_code, affected ID, API response).
Base Commands
holded auth set --api-key "$HOLDED_API_KEY"
holded auth status
holded ping --json
holded actions list --json
holded actions list --filter contacts --json
holded actions describe invoice.get-contact --json
holded actions run invoice.get-contact --path contactId=<id> --json
For long payloads, prefer --body-file:
holded actions run invoice.update-contact \
--path contactId=<id> \
--body-file payload.json \
--json
Purchase receipt rule (mandatory for purchase tickets):
holded actions describe invoice.create-document --json
holded actions run invoice.create-document \
--path docType=purchase \
--body '{"isReceipt": true, "date": 1770764400, "contactId": "<contactId>", "items": [{"name": "Description", "units": 1, "subtotal": 29.4, "tax": 0}]}' \
--skip-validation \
--json
Important notes:
- Use
--skip-validationflag because holdedcli validates against Holded's schema which doesn't includeisReceipt. - Use
subtotalin items (notprice) - this is the field name Holded's API expects. - Timestamps must be in seconds (Unix epoch) and in Europe/Madrid timezone.
Timestamp calculation (Python):
from datetime import datetime, timezone, timedelta
# For 11/02/2026 00:00 in Madrid:
dt = datetime(2026, 2, 11, 0, 0, 0, tzinfo=timezone(timedelta(hours=1)))
print(int(dt.timestamp())) # 1770764400
Accounting Rules for Spain
⚠️ ALWAYS check these rules BEFORE creating any expense document:
| Expense Type | IVA Deductible | Expense Deductible | Account |
|---|---|---|---|
| Restaurants/Meals | ❌ No | ✅ Yes (with justification) | 629 |
| Displacement | ❌ No | ✅ Yes | 629 |
| Fuel | ⚠️ Mixed | ✅ Yes | 625/622 |
| Office supplies | ✅ Yes | ✅ Yes | 600/602 |
| Insurance | ⚠️ Mixed | ✅ Yes | 625 |
Before creating any document, ALWAYS verify:
- Is the expense tax deductible?
- Is the IVA deductible? (usually NO for restaurants, displacement)
- If in doubt, ASK before creating the document.
Common mistake to avoid: Never set tax: 10 or tax: 21 for restaurant expenses - IVA is NOT deductible for meals unless it's a business event with proper justification.
Error Handling
- If
MISSING_API_KEYappears, configure API key through--api-key,HOLDED_API_KEY, orholded auth set. - If
ACTION_NOT_FOUNDappears, list the catalog and search with--filter. - If
INVALID_BODYappears, validate JSON before execution. - If
API_ERRORappears, reportstatus_codeand the API snippet.
References
- Read
{baseDir}/references/holdedcli-reference.mdfor quick commands and criteria. - Use dynamic action discovery and parameter inspection via:
holded actions list --jsonholded actions describe <action> --json