Raqeto — AI API

Raqeto AI API

REST API pro AI agenty — OpenClaw, Claude Desktop, ChatGPT, Cursor, vlastní skripty. Workspace-scoped, Bearer-token auth, OpenAPI 3.1 schema.

⬇ Stáhnout OpenClaw plugin Setup guide Swagger UI OpenAPI JSON

Raqeto AI API — dokumentace

REST API pro AI agenty (OpenClaw, Claude Desktop, ChatGPT Custom GPT, Cline, Cursor, …), které potřebují číst a zapisovat data v Raqeto workspace.

Tato stránka je veřejná — nepotřebuješ přihlášení, aby ses na ni podíval. AI agent si ji může stáhnout a použít jako referenci.


1. Co API umí

Resource Co můžeš dělat
Klienti Číst, vytvářet, upravovat, mazat
Projekty Číst, vytvářet, upravovat, mazat
Úkoly Číst, vytvářet, upravovat, mazat, hromadně přeskládat, nastavit prioritu
Briefy Číst, vytvářet, upravovat, mazat
Komentáře K úkolům a projektům, čtení + vytváření
Time tracking Číst, vytvářet, upravovat (smazat jen pokud není vyfakturovaný)
Faktury Číst, vytvářet, upravovat, označit jako odeslané
Kalendář Číst, vytvářet, upravovat, mazat události + range query
Rozvrh (plán) Číst, plánovat úkoly na konkrétní den, hromadně přeskládat pořadí v rozvrhu
Návrhy e-mailů Vytvořit draft (AI-generovaný), číst, upravit tělo, označit odeslaný, smazat
Search Cross-model fuzzy vyhledávání
Self-discovery /me/ vrátí workspace + scope klíče + seznam endpointů

Všechny dotazy jsou workspace-scoped — klíč vydaný ve workspace A nikdy neuvidí data workspace B.


2. Autentizace

2.1 Získání klíče

  1. Přihlas se do Raqeto a otevři Nastavení → Integrace → AI & API přístup.
  2. Klikni na Nový klíč, pojmenuj ho (např. OpenClaw laptop), popiš a zaškrtni potřebné scopes.
  3. Stiskni Vygenerovat klíč. Token se zobrazí jednou — zkopíruj ho ihned a ulož do secret manageru tvého agenta. Pozdější recovery není možná.
  4. Klíč je vázaný na workspace. Každý API request vrátí jen data z toho workspace.

2.2 Použití klíče

Klíč pošli v Authorization header jako Bearer token:

curl -H "Authorization: Bearer raq_live_abc123..." \
     https://raqeto.com/api/ai/me/

2.3 Scope model

Scope určuje, co klíč smí. Ukládá se jako JSON list string tokenů. HTTP metoda se mapuje na read (GET/HEAD/OPTIONS) nebo write (POST/PUT/PATCH/DELETE).

Token Efekt
read Čtení všech resource
write Zápis všech resource
tasks:read Čtení jen úkolů
tasks:write Vytvoření / úprava / smazání úkolů
projects:read Čtení projektů
projects:write Vytvoření / úprava / smazání projektů
clients:read Čtení klientů
clients:write Vytvoření / úprava / smazání klientů
briefs:read Čtení briefů
briefs:write Vytvoření / úprava / smazání briefů
comments:read Čtení komentářů
comments:write Vytváření komentářů
time:read Čtení time entries
time:write Vytvoření / úprava time entries (DELETE blokováno pro vyfakturované)
invoices:read Čtení faktur
invoices:write Vytváření / úpravy faktur, označení jako odeslané
calendar:read Čtení událostí kalendáře
calendar:write Vytvoření / úprava / smazání událostí

Backwards compatibility: Klíč bez scopes (legacy, vytvořený před tímto modelem) má plný read + write přístup.

Doporučení: Vytvoř jeden klíč pro čtení (read) a druhý pro zápis, oba pro různé účely. Revokuj nepoužívané.


3. Kompletní seznam endpointů

Metoda Path Popis Scope
GET /me/ Self-discovery libovolný
GET /search/?q=&types=tasks,projects Cross-model search <resource>:read
GET /tasks/ Seznam úkolů tasks:read
POST /tasks/ Vytvoření úkolu tasks:write
GET /tasks/{id}/ Detail úkolu tasks:read
PATCH /tasks/{id}/ Částečná úprava tasks:write
DELETE /tasks/{id}/ Smazání tasks:write
POST /tasks/{id}/set-priority/ Shortcut pro nastavení priority tasks:write
POST /tasks/reorder/ Hromadná změna pořadí tasks:write
GET/POST/PATCH/DELETE /projects/ Projekty CRUD projects:read/write
GET/POST/PATCH/DELETE /clients/ Klienti CRUD clients:read/write
GET/POST/PATCH/DELETE /briefs/ Briefy CRUD briefs:read/write
GET/POST/PATCH/DELETE /task-comments/ Komentáře k úkolům comments:read/write
GET/POST/PATCH/DELETE /project-comments/ Komentáře k projektům comments:read/write
GET/POST/PATCH/DELETE /time-entries/ Time tracking CRUD time:read/write
GET/POST/PATCH /invoices/ Faktury (DELETE není povoleno) invoices:read/write
POST /invoices/{id}/send/ Označit jako odeslaná invoices:write
GET/POST/PATCH/DELETE /calendar-events/ Kalendář CRUD calendar:read/write
GET/POST/PATCH/DELETE /schedule-entries/ Denní rozvrh (task × den × pozice) schedule:read/write
POST /schedule-entries/reorder/ Hromadná změna pořadí v rozvrhu schedule:write
GET/POST/PATCH/DELETE /emails/ AI-draft e-mailů emails:read/write

Plnou JSON schema s request/response shapes najdeš v Swagger UI.

3.1 Společné query parametry

Každý list endpoint podporuje:

3.2 Poznámky k zápisu


4. Příklady — cURL

4.1 Self-discovery

curl -H "Authorization: Bearer $RAQETO_TOKEN" \
     https://raqeto.com/api/ai/me/

Response:

{
  "workspace": {
    "id": "a1b2c3...",
    "name": "Freelance",
    "slug": null
  },
  "key": {
    "id": "d4e5f6...",
    "name": "OpenClaw laptop",
    "scopes": ["read", "write"],
    "last_used_at": "2026-04-13T11:42:00Z"
  },
  "endpoints": {
    "tasks": "/api/ai/tasks/",
    "projects": "/api/ai/projects/",
    "...": "..."
  }
}

4.2 Seznam úkolů

curl -H "Authorization: Bearer $RAQETO_TOKEN" \
     "https://raqeto.com/api/ai/tasks/?status=todo&priority=high&ordering=-created_at"

4.3 Vytvoření úkolu

curl -X POST https://raqeto.com/api/ai/tasks/ \
     -H "Authorization: Bearer $RAQETO_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "title": "Zavolat Jardovi ohledně briefu",
       "project": "a1b2c3d4-...",
       "priority": "high",
       "deadline": "2026-04-20"
     }'
curl -H "Authorization: Bearer $RAQETO_TOKEN" \
     "https://raqeto.com/api/ai/search/?q=brief&types=tasks,projects,clients"

4.5 Kalendář — události pro tento týden

curl -H "Authorization: Bearer $RAQETO_TOKEN" \
     "https://raqeto.com/api/ai/calendar-events/?start__gte=2026-04-13&end__lte=2026-04-20"

4.6 Time entry — ruční záznam

curl -X POST https://raqeto.com/api/ai/time-entries/ \
     -H "Authorization: Bearer $RAQETO_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "project": "a1b2c3d4-...",
       "description": "Review klientského briefu",
       "started_at": "2026-04-13T10:00:00+02:00",
       "ended_at": "2026-04-13T11:30:00+02:00",
       "duration_hours": "1.5",
       "is_billable": true
     }'

4.7 Faktura — vytvoření + označit odeslanou

# Vytvoření (number se doplní automaticky)
curl -X POST https://raqeto.com/api/ai/invoices/ \
     -H "Authorization: Bearer $RAQETO_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "client": "...",
       "project": "...",
       "issued_date": "2026-04-13",
       "due_date": "2026-04-27",
       "tax_rate": "21",
       "currency": "CZK"
     }'

# Označit jako odeslanou
curl -X POST https://raqeto.com/api/ai/invoices/<id>/send/ \
     -H "Authorization: Bearer $RAQETO_TOKEN"

4.8 Rozvrh — naplánovat úkol na den

# Přidat úkol do rozvrhu (position se dopočítá na konec dne)
curl -X POST https://raqeto.com/api/ai/schedule-entries/ \
     -H "Authorization: Bearer $RAQETO_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "task": "a1b2c3d4-...",
       "date": "2026-04-21"
     }'

# Vypsat rozvrh pro rozsah dní
curl -H "Authorization: Bearer $RAQETO_TOKEN" \
     "https://raqeto.com/api/ai/schedule-entries/?date_from=2026-04-20&date_to=2026-04-26"

4.9 Rozvrh — hromadné přeskupení pořadí

# AI přeskládá úkoly v rámci dne (nebo napříč dny).
# Pošli seznam { id, position }; position je 0-based index.
curl -X POST https://raqeto.com/api/ai/schedule-entries/reorder/ \
     -H "Authorization: Bearer $RAQETO_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "items": [
         {"id": "uuid-a", "position": 0},
         {"id": "uuid-b", "position": 1},
         {"id": "uuid-c", "position": 2}
       ]
     }'

Response: {"updated": 3} — počet úspěšně přeorderovaných záznamů. Záznamy mimo workspace klíče jsou tiše přeskočeny (nepočítají se do updated).

4.10 Návrhy e-mailů — vytvoření draftu

Externí automatizace (mailbox watcher, webhook z formuláře) POSTne příchozí e-mail. Server založí EmailDraft ve stavu generating, roztočí AI konverzaci a OpenClaw vygeneruje návrh odpovědi. Uživatel ho uvidí v dashboardu v sekci Psaní e-mailů. Nic se nikdy neodesílá — výstup je výhradně na zkopírování.

curl -X POST https://raqeto.com/api/ai/emails/ \
     -H "Authorization: Bearer $RAQETO_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "mode": "reply",
       "source_text": "Dobrý den, chtěl bych se zeptat…",
       "source_from": "klient@firma.cz",
       "source_subject": "Dotaz na nabídku",
       "client": "a1b2c3d4-...",
       "project": "e5f6g7h8-..."
     }'

Odpověď obsahuje id, status="generating" a ai_conversation. Jakmile OpenClaw odpoví, status přejde na pending a v poli body bude finální text.

4.11 Návrhy e-mailů — list + detail + update

# Filtrace a search
curl -H "Authorization: Bearer $RAQETO_TOKEN" \
     "https://raqeto.com/api/ai/emails/?status=pending&project=<uuid>&search=nabídka"

# Detail jednoho draftu (zjištění přechodu generating → pending)
curl -H "Authorization: Bearer $RAQETO_TOKEN" \
     "https://raqeto.com/api/ai/emails/<id>/"

# Přepsat tělo / označit odeslané
curl -X PATCH https://raqeto.com/api/ai/emails/<id>/ \
     -H "Authorization: Bearer $RAQETO_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"body": "Upravený text e-mailu", "status": "sent"}'

# Smazat spam / omyl (pro "hotovo" radši PATCH status=sent)
curl -X DELETE https://raqeto.com/api/ai/emails/<id>/ \
     -H "Authorization: Bearer $RAQETO_TOKEN"

Podporované filtry: status, mode, project, client. Search (?search=…) hledá v source_text, body, subject.


5. Příklady — Python

Univerzální klient, který funguje v libovolném Python skriptu nebo OpenClaw skillu:

import os
import httpx

BASE = "https://raqeto.com/api/ai"
TOKEN = os.environ["RAQETO_TOKEN"]

client = httpx.Client(
    base_url=BASE,
    headers={"Authorization": f"Bearer {TOKEN}"},
    timeout=15.0,
)


def me():
    return client.get("/me/").json()


def list_tasks(status=None, project=None, assignee=None):
    params = {}
    if status: params["status"] = status
    if project: params["project"] = project
    if assignee: params["assignee"] = assignee
    return client.get("/tasks/", params=params).json()


def create_task(title, project, priority="medium", deadline=None, description=""):
    payload = {
        "title": title,
        "project": project,
        "priority": priority,
        "description": description,
    }
    if deadline:
        payload["deadline"] = deadline
    return client.post("/tasks/", json=payload).json()


def search(query, types="tasks,projects,clients"):
    return client.get("/search/", params={"q": query, "types": types}).json()


def upcoming_events(days=7):
    import datetime
    start = datetime.date.today().isoformat()
    end = (datetime.date.today() + datetime.timedelta(days=days)).isoformat()
    return client.get(
        "/calendar-events/",
        params={"start__gte": start, "end__lte": end, "ordering": "start"},
    ).json()


def log_time(project, started_at, ended_at, duration_hours, description=""):
    return client.post("/time-entries/", json={
        "project": project,
        "started_at": started_at,
        "ended_at": ended_at,
        "duration_hours": duration_hours,
        "description": description,
        "is_billable": True,
    }).json()


if __name__ == "__main__":
    print("Workspace:", me()["workspace"]["name"])
    print("Úkoly dnes:", len(list_tasks(status="todo")["results"]))

5a. Raqeto chat daemon — nejjednodušší cesta k chat bubble

Doporučená cesta pro uživatele, kteří chtějí chat bubble v dashboardu fungující do 5 minut a bez nutnosti řešit OpenClaw plugin SDK.

Chat daemon je malý Node CLI (@raqeto/chat-daemon), který běží na tvém laptopu, polluje Raqeto inbox a volá tvůj LLM přímo — Anthropic, OpenAI, Ollama nebo LM Studio. Žádný OpenClaw mezi tím.

Instalace

Předpoklady: - Node ≥ 20 (používá native fetch) - API klíč pro zvoleného providera (Anthropic / OpenAI) nebo lokální Ollama / LM Studio

1. Vytvoř AIKey v Raqeto

Nastavení → Integrace → AI & API přístup → Nový klíč, zaškrtni chat:poll + chat:reply, Vygenerovat, zkopíruj token.

2. Nainstaluj daemon

npm install -g https://raqeto.com/api/ai/raqeto-chat-daemon.tgz

3. Spusť

raqeto-chat-daemon \
  --token raq_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
  --provider anthropic \
  --api-key sk-ant-...

Nebo přes env vars:

export RAQETO_TOKEN=raq_live_...
export ANTHROPIC_API_KEY=sk-ant-...
raqeto-chat-daemon --provider anthropic

4. Otestuj bubble

Otevři https://raqeto.com/dashboard/, klikni na bubble vpravo dole, napiš "ahoj". Do ~3 s by měl dorazit reply.

Vypnutí: Ctrl+C.

Podporované providery

--provider Default model Potřebuje API klíč? Default base URL
anthropic claude-sonnet-4-5 ano (ANTHROPIC_API_KEY) https://api.anthropic.com
openai gpt-4o-mini ano (OPENAI_API_KEY) https://api.openai.com
ollama llama3.2 ne http://localhost:11434
lmstudio local-model volitelně http://localhost:1234

CLI options

Všechny jsou volitelné, CLI > env var > config file.

Flag Env var Popis
--token RAQETO_TOKEN Povinné. Raqeto AIKey (raq_live_...)
--provider RAQETO_PROVIDER anthropic / openai / ollama / lmstudio (default anthropic)
--model RAQETO_MODEL Model ID — default per provider (viz tabulka)
--api-key RAQETO_API_KEY nebo ANTHROPIC_API_KEY / OPENAI_API_KEY API klíč providera
--api-base RAQETO_API_BASE Přepsat base URL (proxy, self-hosted)
--base-url RAQETO_BASE_URL Raqeto instance (default https://raqeto.com)
--poll-interval RAQETO_POLL_INTERVAL Inbox poll interval v ms (default 3000, min 1000)
--system-prompt RAQETO_SYSTEM_PROMPT Přepsat default system prompt (česky, CRM kontext)
--max-history RAQETO_MAX_HISTORY Max zpráv z konverzace posílaných do LLM (default 20)
--verbose RAQETO_VERBOSE=1 Logovat každý poll tick

Config file (volitelné)

Pokud nechceš psát flagy při každém startu, vytvoř ~/.raqeto/chat-daemon.json:

{
  "token": "raq_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "provider": "anthropic",
  "apiKey": "sk-ant-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "model": "claude-sonnet-4-5",
  "pollIntervalMs": 3000,
  "maxHistory": 20
}

Pak stačí spustit raqeto-chat-daemon bez argumentů. Pro jiný config path použij RAQETO_CONFIG_FILE=/path/to/config.json.

Jak to funguje

  1. Daemon každé ~3 s volá GET /api/ai/chat/inbox/ s Bearer tokenem
  2. Pro každou novou user zprávu stáhne plnou historii konverzace přes GET /api/ai/chat/history/?conversation_id=...
  3. Pošle {system prompt, history, latest message} do zvoleného providera
  4. Reply POST-uje na POST /api/ai/chat/outbox/
  5. Widget v dashboardu reply vybere při dalším pollingu (~2 s)

Daemon je stateless — celá historie konverzace žije v Raqeto DB. Můžeš ho kdykoliv zastavit a restartovat, nic se neztratí.

Spuštění jako systemd service (Linux)

~/.config/systemd/user/raqeto-chat-daemon.service:

[Unit]
Description=Raqeto chat daemon
After=network-online.target

[Service]
ExecStart=/usr/bin/env raqeto-chat-daemon
Environment="RAQETO_TOKEN=raq_live_..."
Environment="ANTHROPIC_API_KEY=sk-ant-..."
Restart=on-failure

[Install]
WantedBy=default.target
systemctl --user daemon-reload
systemctl --user enable --now raqeto-chat-daemon
journalctl --user -u raqeto-chat-daemon -f

Launchd na macOS

~/Library/LaunchAgents/com.raqeto.chat-daemon.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key><string>com.raqeto.chat-daemon</string>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/local/bin/raqeto-chat-daemon</string>
    </array>
    <key>EnvironmentVariables</key>
    <dict>
      <key>RAQETO_TOKEN</key><string>raq_live_...</string>
      <key>ANTHROPIC_API_KEY</key><string>sk-ant-...</string>
    </dict>
    <key>RunAtLoad</key><true/>
    <key>KeepAlive</key><true/>
    <key>StandardOutPath</key><string>/tmp/raqeto-chat-daemon.log</string>
    <key>StandardErrorPath</key><string>/tmp/raqeto-chat-daemon.log</string>
  </dict>
</plist>
launchctl load ~/Library/LaunchAgents/com.raqeto.chat-daemon.plist
tail -f /tmp/raqeto-chat-daemon.log

Troubleshooting

Co vidíš Příčina Oprava
missing --token Token nepředán --token raq_live_... nebo export RAQETO_TOKEN=...
authentication failed (401) Token revokovaný / špatně opsaný Vytvoř nový v Raqeto Settings
authentication failed (403) Scope chat:poll nebo chat:reply chybí Settings → Upravit práva → zaškrtnout oba
Anthropic 401 Špatný ANTHROPIC_API_KEY console.anthropic.com → nový klíč
Ollama ECONNREFUSED Ollama neběží ollama serve
Bubble se v dashboardu nezobrazí Žádný AIKey se chat scopes Vytvoř klíč
poll failed ale pak connected Dočasná síť — daemon retry-uje Nech běžet
Odpovědi Chyba při zpracování zprávy LLM provider vrátil error Podívej se do stderr daemonu

5b. OpenClaw channel plugin — chat bubble v Raqeto

Plná integrace, která udělá z Raqeto dashboardu chat rozhraní napojené na tvůj lokální OpenClaw (a tím pádem na tvůj vlastní LLM — Claude, GPT, Ollama, cokoli). Raqeto sám o sobě žádného LLM providera nevolá.

Jak to funguje

  1. Uživatel napíše zprávu do chat bubble vpravo dole v Raqeto dashboardu
  2. Raqeto backend ji uloží jako pending user message (žádné cloud volání)
  3. Na tvém laptopu běží OpenClaw s nainstalovaným @raqeto/openclaw-channel pluginem
  4. Plugin polluje GET /api/ai/chat/inbox/ (~3 s) a vyzvedne zprávu
  5. OpenClaw ji pošle do tvého nakonfigurovaného LLM
  6. Odpověď se vrátí přes POST /api/ai/chat/outbox/
  7. Bubble v prohlížeči odpověď zachytí při dalším polling tiku (~2 s)

Celá AI vrstva žije u tebe. Raqeto je jen message queue.

Instalace pluginu — krok za krokem

Celá instalace zabere ~3 minuty a nepotřebuje Node, Git ani build tooling — jen běžící OpenClaw.

Předpoklady

Krok 1 — Vytvoř AIKey s chat scopes

  1. V Raqeto přejdi na Nastavení → Integrace → AI & API přístup
  2. Klikni na Nový klíč
  3. Název: OpenClaw laptop (nebo jak chceš)
  4. Scopes: zaškrtni chat:poll a chat:reply (ostatní nech odškrtnuté, když plugin bude dělat jen chat)
  5. Vygenerovat klíč
  6. Hned zkopíruj token (raq_live_...) — v seznamu ho uvidíš už jen jako hvězdičky, ale kopírovací tlačítko pořád funguje, kdybys ho potřeboval znovu

Krok 2 — Nainstaluj plugin jedním příkazem

openclaw plugins install https://raqeto.com/api/ai/openclaw-plugin.tgz

OpenClaw stáhne předkompilovaný tarball (@raqeto/openclaw-channel, ~10 kB) z Raqeto CDN a nainstaluje ho. Žádný git clone, žádný npm install, žádný build.

Ověř:

openclaw plugins list            # uvidíš raqeto v seznamu
openclaw plugins info raqeto     # detail + stav + verzi (mělo by být 0.1.3+)

Pokud plugins install selže s invalid manifest nebo minHostVersion not satisfied, máš starou OpenClaw. Upgraduj (npm install -g openclaw@latest) a zkus znovu.

Krok 3 — Přidej config do ~/.openclaw/openclaw.json

Otevři (nebo vytvoř) soubor ~/.openclaw/openclaw.json a přidej blok channels.raqeto:

{
  "channels": {
    "raqeto": {
      "baseUrl": "https://raqeto.com",
      "token": "raq_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "pollIntervalMs": 3000,
      "dmSecurity": "allowlist",
      "allowFrom": []
    }
  }
}

Kdyby už tam channels blok existoval (např. máš Discord nebo Telegram), jen přidej raqeto dovnitř — ne jako samostatný top-level klíč vedle channels.

Pole Povinné Default Popis
baseUrl ne https://raqeto.com Self-hosteři přepíší na svoji doménu
token ano Bearer AIKey se scopes chat:poll + chat:reply
pollIntervalMs ne 3000 Jak často poll inboxu. Min 1000, max 60000
dmSecurity ne allowlist allowlist / blocklist / open
allowFrom ne [] Raqeto user UUIDs / emaily. Prázdný + allowlist = vše blok

Pravidla JSONu: klíče v uvozovkách, žádná čárka navíc na konci posledního klíče, žádné komentáře.

Krok 4 — Restartuj OpenClaw gateway

openclaw gateway restart

V logu (openclaw logs --follow) by mělo být:

[plugin:raqeto] loaded
[plugin:raqeto] polling https://raqeto.com/api/ai/chat/inbox/ every 3000 ms

Krok 5 — Otestuj bubble

  1. Otevři / refreshni https://raqeto.com/dashboard/ v prohlížeči (musíš být přihlášený)
  2. Vpravo dole uvidíš gradient bubble (indigo → fialová)
  3. Tečka v header bubble zezelená = OpenClaw aktivně polluje
  4. Klikni na bubble → drawer se rozbalí
  5. Napiš ahoj
  6. Do ~3–5 s by měla přijít odpověď z tvého OpenClaw LLM

Upgrade pluginu

Když vyjde nová verze, stačí:

openclaw plugins remove raqeto
openclaw plugins install https://raqeto.com/api/ai/openclaw-plugin.tgz
openclaw gateway restart

URL je stabilní — vždycky serveruje aktuální verzi z static/downloads/raqeto-openclaw-channel-<nejvyšší>.tgz.

Jednotlivé endpointy

Metoda Path Co dělá Scope
GET /api/ai/chat/inbox/ Vyzvedne pending user zprávy + označí jako delivered chat:poll
POST /api/ai/chat/outbox/ Pošle assistant odpověď zpátky chat:reply

Tělo POST /outbox/:

{
  "conversation_id": "uuid-z-inboxu",
  "text": "Máš 3 úkoly na dnes...",
  "tokens_input": 120,
  "tokens_output": 45
}

Troubleshooting

Co vidíš Co je špatně Oprava
Cannot find module ... root-alias.cjs/channel-core OpenClaw < 2026.4.12 (rozbitý SDK exports layout) npm install -g openclaw@latest, pak reinstall pluginu a restart gateway
unknown channel id: raqeto při startu Stará verze pluginu (< 0.1.3) openclaw plugins remove raqeto && openclaw plugins install https://raqeto.com/api/ai/openclaw-plugin.tgz
openclaw plugins install vrací 404 Typo v URL Zkopíruj URL přesně z https://raqeto.com/api/ai/guide/
plugins installinvalid manifest Host je moc starý, neumí openclaw.extensions shape Upgrade OpenClaw (npm install -g openclaw@latest)
minHostVersion not satisfied OpenClaw < 2026.4.12 Upgrade OpenClaw
Bubble se v dashboardu nezobrazí Klíč neexistuje / chybí chat:poll + chat:reply Settings → Upravit práva → zaškrtnout oba chat scopes
Bubble je, ale hlásí "OpenClaw neodpovídá" Plugin neběží / špatný token / OpenClaw nemá LLM Zkontroluj openclaw logs --follow a config
Odpovědi přicházejí pomalu (10+ s) pollIntervalMs je moc velký Sniž na 2000 v openclaw.json
401 v OpenClaw logu Token revokovaný / špatně opsaný Vytvoř nový v Raqeto Settings, vlož do configu, restart gateway
403 missing chat:poll Scope na klíči chybí Settings → Upravit práva → zaškrtnout chat:poll + chat:reply
429 rate limit Překročený per-user hourly limit Počkej hodinu nebo zvyš RAQETO_CHAT_RATE_LIMIT_PER_HOUR na backendu
ECONNREFUSED v OpenClaw logu baseUrl je nedostupný Ověř baseUrl — default https://raqeto.com
Zprávy dorazí, ale reply nikdy OpenClaw nemá nastavený LLM provider V OpenClaw nastav Anthropic / OpenAI / Ollama provider

Limity v1

Doporučený prompt pro tvůj OpenClaw LLM

Dej ho do OpenClaw system prompt configu, ať agent ví, že obsluhuje Raqeto chat:

Jsi asistent pro freelancery v CRM Raqeto. Uživatel ti píše z chat bubble
v Raqeto dashboardu. Komunikuj česky, stručně, použij markdown tabulky
pro výčty. Pro destruktivní akce si vyžádej explicitní potvrzení.

Pokud potřebuješ číst data z Raqeto, máš k dispozici raqeto-skill
(REST API přes /api/ai/*). Auth: stejný bearer token, co používáš pro
tento channel. Before calling any write endpoint, confirm with the user.

6. OpenClaw — custom skill setup (read/write REST přístup)

OpenClaw je lokální agent framework, který běží na tvém počítači a volá externí služby přes skills. Aby měl přístup do Raqeto, vytvoříš custom skill.

6.1 Získej AIKey

Viz sekce 2.1. Doporučené scopes: read, write (začni plným přístupem, později zúžíš).

6.2 Ulož token do OpenClaw secrets

Otevři / vytvoř ~/.openclaw/secrets (nebo ekvivalent dle tvé verze OpenClaw) a přidej:

RAQETO_TOKEN=raq_live_xxxxxxxxxxxxxxxxxxxxxxxxx

Nikdy neukládej token do kódu skillu, do Gitu, nebo do OpenClaw prompt historie.

6.3 Vytvoř skill soubor

Zkopíruj níže uvedený soubor jako ~/.openclaw/skills/raqeto.py (adresa se může lišit — viz docs.openclaw.ai):

"""Raqeto skill for OpenClaw.

Exposes Raqeto CRM as a set of agent tools. Requires RAQETO_TOKEN
in the environment (loaded from ~/.openclaw/secrets by OpenClaw).
"""
import os
import httpx

BASE = "https://raqeto.com/api/ai"
TOKEN = os.environ.get("RAQETO_TOKEN", "")
if not TOKEN:
    raise RuntimeError("RAQETO_TOKEN missing — add it to ~/.openclaw/secrets")

_client = httpx.Client(
    base_url=BASE,
    headers={"Authorization": f"Bearer {TOKEN}"},
    timeout=15.0,
)


def _get(path, **params):
    r = _client.get(path, params=params)
    r.raise_for_status()
    return r.json()


def _post(path, **data):
    r = _client.post(path, json=data)
    r.raise_for_status()
    return r.json()


def raqeto_whoami():
    """Return the workspace and key metadata."""
    return _get("/me/")


def raqeto_list_tasks(status: str = "", project: str = "", assignee: str = "", limit: int = 20):
    """List tasks in the current workspace. Optional filters."""
    params = {"page_size": limit}
    if status: params["status"] = status
    if project: params["project"] = project
    if assignee: params["assignee"] = assignee
    return _get("/tasks/", **params)


def raqeto_create_task(title: str, project: str, priority: str = "medium",
                       deadline: str = "", description: str = ""):
    """Create a task. ``project`` is the project UUID, ``deadline`` is ISO date."""
    payload = {"title": title, "project": project, "priority": priority}
    if deadline: payload["deadline"] = deadline
    if description: payload["description"] = description
    return _post("/tasks/", **payload)


def raqeto_set_task_priority(task_id: str, priority: str):
    """Shortcut: set priority on a task (low | medium | high | urgent)."""
    return _post(f"/tasks/{task_id}/set-priority/", priority=priority)


def raqeto_list_projects(status: str = "", limit: int = 20):
    params = {"page_size": limit}
    if status: params["status"] = status
    return _get("/projects/", **params)


def raqeto_list_clients(active: bool = True, limit: int = 20):
    return _get("/clients/", is_active=active, page_size=limit)


def raqeto_search(query: str, types: str = "tasks,projects,clients"):
    """Cross-model search across tasks, projects, clients, briefs, calendar, invoices."""
    return _get("/search/", q=query, types=types)


def raqeto_upcoming_events(days: int = 7):
    """Calendar events in the next N days."""
    import datetime
    start = datetime.date.today().isoformat()
    end = (datetime.date.today() + datetime.timedelta(days=days)).isoformat()
    return _get("/calendar-events/", **{"start__gte": start, "end__lte": end, "ordering": "start"})


def raqeto_log_time(project: str, started_at: str, ended_at: str,
                    duration_hours: str, description: str = "", billable: bool = True):
    """Log a time entry. Datetimes must be ISO 8601 with timezone."""
    return _post("/time-entries/",
                 project=project,
                 started_at=started_at,
                 ended_at=ended_at,
                 duration_hours=duration_hours,
                 description=description,
                 is_billable=billable)


def raqeto_sum_hours_this_week():
    """Return billable + total hours tracked in the current ISO week (current user)."""
    import datetime
    today = datetime.date.today()
    monday = today - datetime.timedelta(days=today.weekday())
    sunday = monday + datetime.timedelta(days=6)
    entries = _get("/time-entries/", **{
        "started_at__gte": f"{monday}T00:00:00Z",
        "started_at__lte": f"{sunday}T23:59:59Z",
        "ended_at__isnull": False,
        "page_size": 200,
    })
    total = sum(float(e.get("duration_hours", 0) or 0) for e in entries.get("results", []))
    billable = sum(
        float(e.get("duration_hours", 0) or 0)
        for e in entries.get("results", []) if e.get("is_billable")
    )
    return {"week_start": str(monday), "week_end": str(sunday),
            "total_hours": total, "billable_hours": billable}


# -------------------- Denní rozvrh (plán úkolů na konkrétní dny) --------------------

def raqeto_list_schedule(date_from: str = "", date_to: str = ""):
    """List schedule entries in a date range (ISO dates).

    Each entry carries ``task_title``, ``project_name``, ``client_name``
    and ``completed`` — no extra lookups needed.
    """
    params = {}
    if date_from: params["date_from"] = date_from
    if date_to: params["date_to"] = date_to
    return _get("/schedule-entries/", **params)


def raqeto_schedule_task(task: str, date: str, position: int = 0):
    """Plan a task for a specific day. Position 0 = append to end of day."""
    payload = {"task": task, "date": date}
    if position: payload["position"] = position
    return _post("/schedule-entries/", **payload)


def raqeto_unschedule(entry_id: str):
    """Remove a task from the schedule (entry id = schedule entry UUID)."""
    r = _client.delete(f"/schedule-entries/{entry_id}/")
    r.raise_for_status()
    return {"ok": True}


def raqeto_reorder_schedule(items: list):
    """Bulk reorder tasks in the schedule in one atomic call.

    ``items`` is a list of dicts: ``[{"id": "<uuid>", "position": 0}, ...]``.
    Returns ``{"updated": N}``.
    """
    return _post("/schedule-entries/reorder/", items=items)


# -------------------- Návrhy e-mailů (AI composer) --------------------

def raqeto_create_email_draft(source_text: str, mode: str = "reply",
                              subject: str = "", instructions: str = "",
                              client: str = "", project: str = "", task: str = ""):
    """Create an email draft. Server spins up an AI conversation that
    generates the draft body asynchronously.

    ``mode`` is one of ``reply`` (odpověď na příchozí mail), ``compose``
    (úplně nový mail podle bodů) or ``rewrite`` (přeformulovat text).
    ``source_text`` = příchozí mail (reply) / body points (compose) /
    existing draft to rewrite. ``client`` / ``project`` / ``task`` jsou
    volitelné UUID reference pro kontext.

    Returns the new ``EmailDraft`` JSON with ``status='generating'``.
    Poll ``raqeto_get_email_draft(id)`` until ``status='pending'`` to
    see the final body.
    """
    payload = {"mode": mode, "source_text": source_text}
    if subject: payload["subject"] = subject
    if instructions: payload["instructions"] = instructions
    if client: payload["client"] = client
    if project: payload["project"] = project
    if task: payload["task"] = task
    return _post("/emails/", **payload)


def raqeto_list_email_drafts(status: str = "", project: str = "",
                             client: str = "", search: str = "",
                             limit: int = 20):
    """List email drafts. Filter by ``status`` (generating|pending|sent|...),
    ``project`` UUID, ``client`` UUID, or free-text ``search``.
    """
    params = {"page_size": limit}
    if status: params["status"] = status
    if project: params["project"] = project
    if client: params["client"] = client
    if search: params["search"] = search
    return _get("/emails/", **params)


def raqeto_get_email_draft(draft_id: str):
    """Fetch one draft — use this to poll ``status`` (generating → pending)
    and read the finalized ``body``.
    """
    return _get(f"/emails/{draft_id}/")


def raqeto_update_email_draft(draft_id: str, body: str = "",
                              subject: str = "", status: str = ""):
    """Partial update — typically used to overwrite ``body`` after user
    edits, or set ``status='sent'`` after the user hits send externally.
    """
    payload = {}
    if body: payload["body"] = body
    if subject: payload["subject"] = subject
    if status: payload["status"] = status
    r = _client.patch(f"/emails/{draft_id}/", json=payload)
    r.raise_for_status()
    return r.json()


def raqeto_delete_email_draft(draft_id: str):
    """Delete a draft. Only for spam / mistakes — for "finished" drafts
    prefer ``raqeto_update_email_draft(id, status='sent')`` so the record
    stays in the audit trail.
    """
    r = _client.delete(f"/emails/{draft_id}/")
    r.raise_for_status()
    return {"ok": True}

6.4 Zaregistruj skill v OpenClaw

Přesný postup závisí na verzi OpenClaw. Obecně:

  1. Zkopíruj soubor do adresáře, který OpenClaw skenuje na startu (~/.openclaw/skills/)
  2. Restartuj OpenClaw daemon / sezení
  3. V chatu s agentem můžeš říct: "Use the raqeto_whoami tool to check the connection"
  4. Nebo: "Use raqeto_list_tasks to show my todos"

Přesné kroky viz docs.openclaw.ai.

6.5 Smoke test

Před tím, než začneš skill používat v OpenClaw, otestuj token z shellu:

export RAQETO_TOKEN=raq_live_...
curl -H "Authorization: Bearer $RAQETO_TOKEN" https://raqeto.com/api/ai/me/

Pokud dostaneš JSON s názvem tvého workspace, token funguje a skill bude taky fungovat.

6.6 Doporučený prompt pro OpenClaw agenta

Jsi asistent pro správu CRM Raqeto. Máš k dispozici skills s prefixem
raqeto_* — použij je pro čtení a zápis dat ve workspace uživatele.

Co umíš:
  • Klienti, projekty, úkoly — číst, zakládat, upravovat, řadit
  • Time tracking — vypsat týden, zapsat záznam
  • Kalendář — nadcházející události, plánování
  • Denní rozvrh — raqeto_list_schedule / raqeto_schedule_task /
    raqeto_reorder_schedule (bulk přeskládání)
  • Návrhy e-mailů — raqeto_create_email_draft (režimy reply / compose /
    rewrite), raqeto_list_email_drafts, raqeto_get_email_draft (poll
    dokud status není 'pending'), raqeto_update_email_draft (uložit
    úpravy nebo označit sent), raqeto_delete_email_draft
  • Search — raqeto_search pro cross-model fuzzy hledání

Pro destruktivní akce (smazání, přepočet faktury) si nejprve vyžádej
textové potvrzení. Komunikuj česky, stručně, výčty v markdown tabulkách.

Pozn.: Nic se neodesílá automaticky — e-mailové návrhy uživatel
ručně kopíruje do svého klienta a označí jako sent.

7. Další AI klienti

7.1 Claude Desktop (manuálně bez MCP)

Claude Desktop zatím nepodporuje libovolné HTTP tool volání bez MCP wrapperu. Dokud nebude k dispozici Raqeto MCP server, použij:

  1. Custom Python helper (viz výše)
  2. Nebo Claude Projects s API docs vloženými jako kontext

7.2 ChatGPT Custom GPT / Actions

V GPT Builder otevři Actions → Authentication:

Potom importuj schema z:

https://raqeto.com/api/ai/schema.json

GPT Builder automaticky vygeneruje všechny Actions z OpenAPI schema.

7.3 Cursor / Cline / Windsurf

Tyto IDE-agent klienti obvykle podporují volání přes HTTP. Použij Python snippet z sekce 5 jako helper v tvém workspace.

7.4 Jakýkoli HTTP klient

Cokoli, co umí poslat Authorization: Bearer raq_live_..., může API používat.


8. Rate limits

Scope Limit
Anonymní N/A — všechny /api/ai/* endpointy vyžadují klíč
Per-key Zatím bez hard limitu; abuse pattern může triggerovat throttling v budoucnu
Dashboard chat 30 zpráv / hodinu / uživatel (separate endpoint, nepočítá se do API quoty)

9. HTTP status kódy

Kód Význam
200 OK
201 Vytvořeno
204 OK, no content (typicky DELETE)
400 Špatný request — chybí nebo nesprávný field
401 Chybějící / neplatný / revokovaný token → vygeneruj nový v Settings
403 Token je platný, ale chybí mu scope pro tento request
404 Resource neexistuje v tomto workspace
405 HTTP metoda není dovolena na tomto URL
429 Rate limit překročen — back off a zkus později
500 Server error — nahlas s request ID z response headers
502 Upstream error (Anthropic, Fakturoid) — network / dependency
503 Služba dočasně nedostupná (chat bez ANTHROPIC_API_KEY)

Pokud request selže s 403, zavolej /me/ a zkontroluj key.scopes — potřebuješ <resource>:<action> (např. invoices:write).


10. Troubleshooting

"Invalid AI key" / 401

→ Vygeneruj nový klíč v Nastavení → Integrace → AI & API přístup.

"AI key missing required scope" / 403

→ V Settings revokuj klíč a vytvoř nový s potřebnými scopes. Nebo edituj existující klíč (pokud to UI podporuje — zatím jen recreate).

"Cannot determine user to attribute time entry to" / 400

Cross-tenant leak

Swagger UI neukazuje "Try it out" button


11. Bezpečnost


12. Versioning

Verze API je v OpenAPI schema pod info.version (aktuálně 1.0.0). Breaking změny inkrementujou major verzi a objeví se pod /api/ai/v2/. Do té doby je unversioned base /api/ai/ stabilní.

Changelog: - 1.0.0 (2026-04): První veřejná verze. Endpointy: tasks, projects, clients, briefs, comments, time-entries, invoices, calendar-events, me, search. Scope model s tokens jako JSON list.


13. Kontakt a support

Pokud najdeš chybu v dokumentaci, nejrychlejší cesta je PR na docs/AI_API.md.