Agent integration guide

Everything an agent needs to call paid endpoints through Sourcelane: one authenticated POST, an itemised receipt, and a flat set of guardrail error codes to handle.

First-party connectors bill from your balance · third-party x402 settlement currently runs in simulation mode

Getting an API key

Agent keys are created from the dashboard, not this page — sign in, go to Dashboard → Agents, and create an agent. The plaintext key (sl_live_…) is shown exactly once at creation time; only its hash is stored server-side. Set spend caps (daily limit, monthly limit, max transaction size, allowlist) on the same agent before you use it — a key with no caps set is not a safe default.

Send the key as a bearer token on every gateway request: Authorization: Bearer sl_live_….

MCP server & AI platforms

Sourcelane runs a remote MCP server (Streamable HTTP) at https://api.usesourcelane.com/mcp. Authenticate with the same agent key as the REST API. It exposes four tools: search_connectors, get_connector, call_connector and get_account — so your AI can find the right connector, read its params and run it without any bespoke integration.

Connect your tools

Pick your tool and connect in under a minute. Then just ask — for example: “Use Sourcelane to run instagram-profile-scraper and summarise what you find.”

Connect Claude

Web, desktop and mobile. Paste one URL.

  1. 1Copy your personal connector URL
  2. 2In Claude open Settings → Connectors → Add custom connector
  3. 3Paste the URL and click Add — done
Manual setup (config files, REST, Python) +

Claude Code

Adds the Sourcelane MCP server with your key as a header.

terminal
claude mcp add --transport http sourcelane https://api.usesourcelane.com/mcp \
  --header "Authorization: Bearer sl_live_your_agent_key"

Claude Desktop (config file)

Alternative to the connector URL: add to claude_desktop_config.json, then restart Claude.

claude_desktop_config.json
{
  "mcpServers": {
    "sourcelane": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.usesourcelane.com/mcp",
        "--header",
        "Authorization:${AUTH_HEADER}"
      ],
      "env": {
        "AUTH_HEADER": "Bearer sl_live_your_agent_key"
      }
    }
  }
}

Cursor & Windsurf

Add to ~/.cursor/mcp.json (or Windsurf's mcp_config.json).

mcp.json
{
  "mcpServers": {
    "sourcelane": {
      "url": "https://api.usesourcelane.com/mcp",
      "headers": {
        "Authorization": "Bearer sl_live_your_agent_key"
      }
    }
  }
}

VS Code

Save as .vscode/mcp.json. VS Code prompts for your key once.

.vscode/mcp.json
{
  "servers": {
    "sourcelane": {
      "type": "http",
      "url": "https://api.usesourcelane.com/mcp",
      "headers": {
        "Authorization": "Bearer ${input:sourcelane-key}"
      }
    }
  },
  "inputs": [
    {
      "type": "promptString",
      "id": "sourcelane-key",
      "description": "Sourcelane agent key",
      "password": true
    }
  ]
}

ChatGPT Custom GPT (Actions)

Create a GPT → Actions → Import from URL, then Authentication: API Key, Bearer.

OpenAPI schema URL
https://usesourcelane.com/openapi.json

REST

One POST. Pass maxResults to cap cost.

curl
curl -X POST https://api.usesourcelane.com/v1/call \
  -H "Authorization: Bearer sl_live_your_agent_key" \
  -H "Content-Type: application/json" \
  -d '{"listing":"instagram-profile-scraper","params":{"usernames":["natgeo"]},"maxResults":10}'

Python, LangChain, CrewAI, OpenAI Agents SDK…

Wrap the REST call as a tool, or point an MCP client at the endpoint.

python
import requests

res = requests.post(
    "https://api.usesourcelane.com/v1/call",
    headers={"Authorization": "Bearer sl_live_your_agent_key"},
    json={
        "listing": "instagram-profile-scraper",
        "params": {"usernames":["natgeo"]},
        "maxResults": 10,
    },
    timeout=300,
)
body = res.json()
print(body["receipt"]["chargedMicros"], "micro-USD for", body["receipt"]["results"], "results")
print(body["data"])

Per-result pricing

Most connectors are priced per result (per profile, per post, per review…). Each call first reserves the listing's per-call ceiling — the unit price times the most results one call can return — then settles at the number of results actually returned and refunds the rest in the same second. A call that returns nothing costs nothing.

Pass maxResults alongside params to lower both the ceiling and the reservation. The receipt shows reservedMicros, chargedMicros, refundedMicros and results.

A connector call can take up to a few minutes for large requests — set your HTTP client timeout to at least 300s.

POST /v1/call

The single endpoint an agent calls to use a listing. Body carries the listing's slug and a params object matching that listing's published request schema. Sourcelane resolves the listing, evaluates guardrails, debits the ledger, forwards the call upstream, and settles or refunds based on the result — all in one round trip.

Request
curl -X POST "https://api.usesourcelane.com/v1/call" \
  -H "Authorization: Bearer sl_live_your_agent_key" \
  -H "Content-Type: application/json" \
  -d '{
    "listing": "global-weather-now",
    "params": { "latitude": 52.52, "longitude": 13.41 }
  }'

On success (200):

200 response
{
  "requestId": "req_8fK2n...",
  "listing": "global-weather-now",
  "data": { /* verbatim upstream JSON */ },
  "receipt": {
    "priceMicros": 2000,
    "chargedMicros": 2000,
    "balanceAfterMicros": 9998000,
    "latencyMs": 412,
    "upstreamLatencyMs": 388,
    "x402": {
      "network": "base",
      "asset": "USDC",
      "txRef": "sim_9c1e...",
      "simulated": true
    }
  }
}

On a blocked or failed call:

Error response
{
  "requestId": "req_8fK2n...",
  "error": {
    "code": "daily_limit_exceeded",
    "message": "This call would exceed the agent's daily spend limit."
  }
}

GET /v1/listings

Returns the live, browsable listings — the same set backing the public directory — so an agent can discover endpoints without a human in the loop. No body; the key on the request just needs to be valid.

Request
curl "https://api.usesourcelane.com/v1/listings" \
  -H "Authorization: Bearer sl_live_your_agent_key"

GET /v1/me

Returns the calling agent's own state: status, kill switch, guardrail configuration, and current spend against each limit. Useful for an agent to self-check before it spends, rather than discovering a limit by hitting it.

Request
curl "https://api.usesourcelane.com/v1/me" \
  -H "Authorization: Bearer sl_live_your_agent_key"

Guardrail error codes

Guardrails are evaluated in a fixed order — the first one that fails wins, and every field below except invalid_key is recorded as a blocked call (and never charged).

codeHTTP statusMeaning
invalid_key401No key, or the key doesn't match any agent. Not recorded as a call — there's no agent to attach it to.
agent_revoked403The agent's key has been rotated or the agent removed.
agent_paused403The agent is paused from the dashboard.
kill_switch403The agent's kill switch is on. Takes effect immediately.
listing_not_found404No listing matches the slug you sent.
listing_not_live404The listing exists but isn't in the live status yet.
not_allowlisted403The agent's allowlistMode is "allowlist" and this listing isn't on it.
max_tx_exceeded403The listing's price is above this agent's maxTxMicros.
daily_limit_exceeded403This call would put the agent over its daily spend limit.
monthly_limit_exceeded403This call would put the agent over its monthly spend limit.
total_budget_exceeded403This call would put the agent over its lifetime budget.
insufficient_balance402The account balance can't cover the listing's price.

Refunds on failure

Calls are reserve-then-settle. Authorizing a call debits the ledger and opens a calls row immediately; the upstream request only runs after that. If the upstream call doesn't come back as a success — an upstream error, a timeout, or a failed x402 payment — the debit is automatically reversed. You only ever end up charged for a call that actually returned data.

Guardrail blocks (an unmet limit, an unlisted endpoint, and so on) are rejected before any debit happens at all, so there's nothing to refund on those.

Every post-reservation failure answers 424 Failed Dependency — not 502, because the CDN in front of the gateway rewrites the body of gateway-class 5xx responses and would strip this envelope. Branch on error.code, never on the status alone:

CodeStatusMeaning
bad_request400Malformed body — `listing` missing, or `params` isn't an object.
payment_failed424x402 settlement was rejected before the upstream was called.
upstream_unreachable424The listing's endpoint could not be reached at all.
upstream_error424The endpoint answered with a non-2xx status.
invalid_upstream_response424The endpoint answered, but not with parseable JSON.
upstream_timeout424The endpoint did not respond within 20 seconds.

All of the above are refunded automatically, and their messages say so explicitly.

Code samples

Same request, three languages.

curl
curl -X POST "https://api.usesourcelane.com/v1/call" \
  -H "Authorization: Bearer sl_live_your_agent_key" \
  -H "Content-Type: application/json" \
  -d '{
    "listing": "global-weather-now",
    "params": { "latitude": 52.52, "longitude": 13.41 }
  }'
TypeScript
const res = await fetch("https://api.usesourcelane.com/v1/call", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SOURCELANE_AGENT_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    listing: "global-weather-now",
    params: { latitude: 52.52, longitude: 13.41 },
  }),
});

const result = await res.json();
if (!res.ok) {
  // result.error = { code, message }
  throw new Error(`${result.error.code}: ${result.error.message}`);
}

console.log(result.data);        // upstream JSON, verbatim
console.log(result.receipt);     // priceMicros, chargedMicros, balanceAfterMicros, latencyMs, x402
Python
import os, requests

res = requests.post(
    "https://api.usesourcelane.com/v1/call",
    headers={"Authorization": f"Bearer {os.environ['SOURCELANE_AGENT_KEY']}"},
    json={"listing": "global-weather-now", "params": {"latitude": 52.52, "longitude": 13.41}},
)
result = res.json()
if not res.ok:
    raise RuntimeError(f"{result['error']['code']}: {result['error']['message']}")

data = result["data"]
receipt = result["receipt"]

Base URL used above: https://api.usesourcelane.com. Questions about a specific listing's request/response schema? Check that listing's page in the directory.