Cold Leads

Předplatné, které zahájí agent a schválí člověk

Pro koho
Tvůrci AI agentů, jejichž vlastník zatím nemá klíč Cold Leads
Problém
Agent, který potřebuje ověřování e-mailů, by nikdy neměl mít u sebe platební kartu ani si sám sjednat předplatné. Poslat člověka, aby se zaregistroval, vybral tarif a zkopíroval klíč, úlohu přeruší a klíče vkládané do chatů unikají.
Řešení
Agent bez klíče zavolá jeden endpoint a dostane odkaz na Stripe Checkout pro svého vlastníka a k tomu tajný claim token. Vlastník si tarif prohlédne a rozhodne. Po zaplacení si agent s claim tokenem vyzvedne API klíč právě jednou, dotazováním na stav nebo po podepsaném callbacku.
Co získáte
Funkční tajný API klíč k novému účtu vlastníka s tarifem Business, doručený agentovi jednou, a e-mail vlastníkovi s odkazem pro otevření webové aplikace Cold Leads.

Adresy, identifikátory a výsledky v příkladech jsou ilustrativní. Doména example.com je vyhrazená pro dokumentaci, takže skutečná kontrola těchto adres vrátí invalid.

Ukázky kódu jsou ve všech jazycích stejné, komentáře v nich jsou anglicky.

Průběh v kostce

Sekvence
Agent (no key)                 Cold Leads                         Human owner              Stripe
     |                              |                                   |                     |
     | POST /api/agent/provision    |                                   |                     |
     | owner_email, agent_id,       |                                   |                     |
     | callback_url (optional)      |                                   |                     |
     |----------------------------->| pending account, disabled key,    |                     |
     |                              | Checkout session (24 h) --------------------------------->|
     |<-----------------------------| checkout_url, session_id,         |                     |
     |                              | claim_token (shown once)          |                     |
     | shows checkout_url --------------------------------------------->|                     |
     |                              |                                   | reviews plan, pays->|
     |                              |<-------------------------------------- payment webhook --|
     |                              | activates account and key,        |                     |
     |                              | e-mails the owner a sign-in link ->|                     |
     |<-- signed callback (optional, no secrets) -----------------------|                     |
     | GET /api/agent/status        |                                   |                     |
     | ?session_id=...              |                                   |                     |
     | X-Claim-Token: clt_...       |                                   |                     |
     |----------------------------->|                                   |                     |
     |<-----------------------------| status active + api_key           |                     |
     |                              | (first call only)                 |                     |

Stejný postup je vestavěný v Node.js SDK (agent.provision, agent.waitForActivation, verifyCallbackSignature) a v lokálním stdio MCP serveru jako nástroje provision_account_and_get_payment_link a check_provisioning_status. Hostovaný MCP endpoint vyžaduje klíč u každého požadavku, takže agent bez klíče pro tento krok použije REST, SDK nebo stdio server.

Krok 1: vyžádejte si platební odkaz (bez klíče)

owner_email je člověk, který bude účet vlastnit a platit; agent_id pojmenovává vašeho agenta nebo produkt a zobrazí se na platební stránce. callback_url je volitelný a musí být https na veřejném hostu.

Požadavek
curl -s https://coldleads.app/api/agent/provision \
  -H "Content-Type: application/json" \
  -d '{
    "owner_email": "owner@example.com",
    "agent_id": "Acme Research Agent",
    "callback_url": "https://agent.example.com/hooks/coldleads"
  }'
Odpověď 200
{
  "status": "payment_required",
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_live_…",
  "session_id": "cs_live_…",
  "provision_id": "prov_…",
  "claim_token": "clt_…",
  "expires_at": "2026-10-01T09:30:00.000Z",
  "plan": { "id": "business", "name": "Business", "price": "$99", "amount": 99, "currency": "usd", "interval": "month", "api": true },
  "status_url": "https://coldleads.app/api/agent/status?session_id=cs_live_…",
  "instructions_for_agent": "Show the human owner (owner@example.com) this payment link and let them decide: … Do not open, pay or forward the link yourself. Keep claim_token secret (it is shown only now). …"
}
HTTPerrorKdy
400invalid_owner_email, agent_id_required, invalid_callback_url, bad_bodyTělo není platný JSON, e-mail vlastníka neprojde kontrolou syntaxe, agent_id je prázdné nebo callback_url není https na veřejném hostu.
409account_existsTento e-mail už má pracovní prostor Cold Leads. Místo toho požádejte vlastníka o tajný klíč z Nastavení → API klíče.
429rate_limitedVíc než 10 požadavků za hodinu z jedné IP adresy nebo víc než 3 požadavky na stejný e-mail vlastníka za den.
502gatewayStripe nedokázal vytvořit checkout; zkuste to později.

Krok 2: vlastník rozhodne na Stripe

  • Ukažte checkout_url člověku a nechte rozhodnutí na něm. Odkaz sami neotevírejte, neplaťte ani nepřeposílejte.
  • Stránka Stripe uvádí produkt Cold Leads Business (API access), jméno agenta, cenu $99 měsíčně, měsíční obnovování až do zrušení a odkazy na podmínky. Tato cesta nemá zkušební verzi a při placení se může připočíst daň.
  • Odkaz platí 24 hodin. Poté se stav změní na expired a agent si může vyžádat nový odkaz.
  • Jakmile platba projde, Cold Leads aktivuje účet i klíč a pošle vlastníkovi e-mailem jednorázový odkaz do webové aplikace, kde může spravovat předplatné nebo klíč agenta přegenerovat.

Krok 3: jednou si vyzvedněte klíč

Dokud je stav pending_payment, volejte každých 15 až 30 sekund GET /api/agent/status?session_id=… s hlavičkou X-Claim-Token. První odpověď po zaplacení na dotaz s platným claim tokenem obsahuje api_key; žádná pozdější odpověď ho neobsahuje.

statusPole kromě session_id a plan
pending_paymentexpires_at; checkout_url, když je claim token platný
active (první volání s claim tokenem)activated_at, api_key, api_key_prefix, mcp_url, api_base, message
active (každé další volání)activated_at, api_key_prefix, mcp_url, api_base, key_delivered_at, message
active (bez platného claim tokenu)jen activated_at
expiredmessage: vyžádejte si nový odkaz přes POST /api/agent/provision
suspendedžádná
První odpověď po zaplacení
{
  "session_id": "cs_live_…",
  "plan": "business",
  "status": "active",
  "activated_at": "2026-09-30T10:02:11.000Z",
  "api_key_prefix": "sk_…9f3c",
  "mcp_url": "https://coldleads.app/api/mcp",
  "api_base": "https://coldleads.app/api/v1",
  "api_key": "sk_…",
  "message": "This is the only time the key is shown. Store it as COLDLEADS_API_KEY; send it as Authorization: Bearer <key>."
}
poll_status.py
# pip install httpx
import os
import time

import httpx

BASE = "https://coldleads.app"
SESSION_ID = os.environ["COLDLEADS_SESSION_ID"]    # session_id from the provision response
CLAIM_TOKEN = os.environ["COLDLEADS_CLAIM_TOKEN"]  # claim_token (clt_...), shown only once


def save_key(key: str) -> None:
    path = os.path.expanduser("~/.coldleads_api_key")  # or your secret manager
    fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600)
    with os.fdopen(fd, "w") as f:
        f.write(key)


while True:
    r = httpx.get(f"{BASE}/api/agent/status", params={"session_id": SESSION_ID},
                  headers={"X-Claim-Token": CLAIM_TOKEN}, timeout=30)
    if r.status_code == 429:  # 120 status requests per minute per IP
        time.sleep(60)
        continue
    r.raise_for_status()
    s = r.json()
    if s["status"] == "active":
        if "api_key" not in s:
            raise SystemExit("The key was already collected; the owner can rotate it in Settings -> API keys.")
        save_key(s["api_key"])
        print("API key saved; prefix", s["api_key_prefix"])
        break
    if s["status"] in ("expired", "suspended"):
        raise SystemExit(s.get("message", s["status"]))
    time.sleep(20)  # pending_payment: poll every 15-30 seconds

Volitelně: podepsaný callback místo dotazování

  • Když vlastník zaplatí, Cold Leads pošle jeden POST na callback_url s časovým limitem 5 sekund. Nesleduje přesměrování a pokus neopakuje, takže dotazování si ponechte jako zálohu.
  • JSON tělo obsahuje event (coldleads.account.activated), provision_id, session_id, status (active) a status_url. Klíč nikdy neobsahuje: vyzvedněte si ho dotazem na stav z kroku 3.
  • Hlavičky: X-Coldleads-Event s názvem události a X-Coldleads-Signature se sha256=, za kterým následuje hex digest: HMAC-SHA256 ze surového těla požadavku, s klíčem, kterým je hex digest SHA-256 vašeho claim tokenu.
Node.js (Express)
// npm install express
import express from "express";
import { createHash, createHmac, timingSafeEqual } from "node:crypto";

const CLAIM_TOKEN = process.env.COLDLEADS_CLAIM_TOKEN; // clt_... from the provision response

// X-Coldleads-Signature: sha256=<hex HMAC-SHA256 of the raw body>, key = SHA-256 hex digest of the claim token
function validSignature(rawBody, header, claimToken) {
  if (!Buffer.isBuffer(rawBody) || typeof header !== "string" || !header.startsWith("sha256=")) return false;
  const key = createHash("sha256").update(claimToken).digest("hex");
  const expected = createHmac("sha256", key).update(rawBody).digest();
  const given = Buffer.from(header.slice("sha256=".length), "hex");
  return given.length === expected.length && timingSafeEqual(given, expected);
}

const app = express();
app.post("/hooks/coldleads", express.raw({ type: "application/json" }), (req, res) => {
  if (!validSignature(req.body, req.get("x-coldleads-signature"), CLAIM_TOKEN)) return res.sendStatus(401);
  const event = JSON.parse(req.body.toString("utf8"));
  res.sendStatus(204); // answer fast: Cold Leads waits 5 seconds and does not retry
  if (event.event === "coldleads.account.activated") {
    // the callback carries no key: collect it now with GET /api/agent/status + X-Claim-Token
    console.log("owner paid, session", event.session_id);
  }
});
app.listen(3000);
Python (Flask)
# pip install flask
import hashlib
import hmac
import json
import os

from flask import Flask, request

CLAIM_TOKEN = os.environ["COLDLEADS_CLAIM_TOKEN"]  # clt_... from the provision response
app = Flask(__name__)


def valid_signature(raw_body: bytes, header, claim_token: str) -> bool:
    if not header or not header.startswith("sha256="):
        return False
    key = hashlib.sha256(claim_token.encode()).hexdigest().encode()
    expected = hmac.new(key, raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header[len("sha256="):])


@app.post("/hooks/coldleads")
def coldleads_callback():
    raw = request.get_data()  # the raw bytes, before any JSON parsing
    if not valid_signature(raw, request.headers.get("X-Coldleads-Signature"), CLAIM_TOKEN):
        return "", 401
    event = json.loads(raw)
    if event.get("event") == "coldleads.account.activated":
        # the callback carries no key: collect it with GET /api/agent/status + X-Claim-Token
        print("owner paid, session", event["session_id"])
    return "", 204

Poznámky k bezpečnosti

  • S claim_token zacházejte jako s heslem. Vrací se jen jednou, ukládá se jen jeho hash a je to jediný způsob, jak klíč vyzvednout: bez něj klíč neobsahuje žádná odpověď na dotaz na stav, ať se hledá podle session_id, nebo owner_email.
  • API klíč se doručí právě jednou. Pokud se ztratí, vlastník se přihlásí a přegeneruje ho v Nastavení → API klíče.
  • Zaplacení nedokazuje, že plátce ovládá schránku vlastníka. Webový přístup k účtu dostane jen owner_email: přes jednorázový odkaz poslaný na tuto adresu, nebo přihlášením do Cold Leads s touto adresou, jakmile je ověřena.
  • Než na callback zareagujete, ověřte jeho podpis nad surovým tělem, i když callback žádná tajemství nenese.
  • Nezaplacené žádosti nezůstávají viset: odkaz vyprší po 24 hodinách a nezaplacené záznamy o zřízení se po 7 dnech smažou i s nepoužitým účtem a klíčem.

Limity a náklady

  • Tarif: Business s přístupem k API, $99 měsíčně v amerických dolarech, obnovuje se každý měsíc až do zrušení; 10 000 kreditů na ověřování a API měsíčně; další balíčky po 1 000 kreditech stojí $5. Může se připočíst daň.
  • Zřízení účtu: 10 požadavků za hodinu na IP adresu a 3 požadavky na e-mail vlastníka za den. Dotazy na stav: 120 za minutu na IP adresu.
  • Po aktivaci má klíč běžný limit API 120 požadavků za minutu.

Otázky

Může agent zaplatit nebo zvolit levnější tarif?

Ne. Odkaz je na tarif Business, jediný tarif, který zahrnuje API, a zaplatit ho může jen člověk na stránce Stripe. Úkolem agenta je odkaz ukázat a čekat.

Co když vlastník nikdy nezaplatí?

Odkaz na platbu vyprší po 24 hodinách a stav se změní na expired. Agent si může vyžádat nový odkaz (až 3 požadavky na e-mail vlastníka za den). Nezaplacené záznamy se po 7 dnech smažou.

Co když vlastník už Cold Leads používá?

Požadavek selže s 409 account_exists. Vlastník vytvoří tajný klíč v Nastavení → API klíče (tarif Business) a předá ho agentovi jako COLDLEADS_API_KEY.

Funguje to i přes MCP?

Ano, s lokálním stdio serverem (npx -y --allow-git=root github:anttka4cz/mcp-server-coldleads). Spustí se bez klíče, nabízí provision_account_and_get_payment_link a check_provisioning_status a na nový klíč přepne, jakmile je vyzvednut. Hostovaný endpoint na coldleads.app/api/mcp vyžaduje klíč u každého požadavku.