PipSync

Connect Claude or ChatGPT to your live trading account — check quotes and positions, and place, modify or close trades with a two-step confirm (trading scope only, never withdrawals).

Documentation

Home›Developers›API Reference

v1 API · OpenAPI 3.1 · signed webhooks

An API built for traders who code.

REST where it makes sense, signed webhooks where events need to reach your systems. OpenAPI 3.1 spec, verifiable signatures, and copy-paste examples for every hot endpoint.

Interactive PlaygroundDownload OpenAPI spec

Getting started

QuickstartAuthenticationObtaining an API keyKey scopesKey security

Rate limits

Limits by tierResponse headersExponential backoff

Errors

Error codes

Endpoints

GET/v1/meGET/v1/signalsGET/v1/tradesGET/v1/reports

Webhooks

Realtime SSE streamEvent catalogueVerifying signatures

OpenAPI clients

Code generatorsInteractive Playground ↗

Quickstart

Store your key, call /v1/me to verify auth, then start reading signals or trades. Five minutes from zero to first API response.

cURLNode.jsPython

curl https://app.pipsync.io/api/v1/me
-H "Authorization: Bearer $PIPSYNC_KEY"

Every response is wrapped in { "data": … }. Paginated endpoints additionally return a "meta" object with total, page, totalPages, and hasMore.

Authentication

All API requests require a bearer token in the Authorization header. Keys are per-environment (live / sandbox), per-scope, and time-limited only if you choose to set an expiry.

HeaderAuthorization: Bearer pipsync_live_<32 alnum chars>

Obtaining an API key

API access requires the Enterprise plan. Once on Enterprise:

  1. Navigate to Settings → API Keys in your workspace.
  2. Click Create key, choose a name (e.g. prod-signal-reader), and select the scopes you need.
  3. Copy the key — it is shown only once. Store it in a secret manager (AWS Secrets Manager, Vault, Doppler, etc.).
  4. To rotate: create a replacement key, cut traffic over, revoke the old key. There is no downtime if you overlap by one deployment cycle.

Key scopes

ScopeAccessEndpoints
signals:readRead-onlyGET /v1/signals
trades:readRead-onlyGET /v1/trades
reports:readRead-onlyGET /v1/reports, GET /v1/reports/trades
account:readRead-onlyGET /v1/me, GET /v1/account/usage
webhooks:writeWriteManage webhook subscriptions (dashboard only)

Key security

Never expose a live key in client-side code. Keys embedded in browser bundles, mobile apps, or public repos are compromised. Use sandbox keys for prototyping. Revoke a leaked key immediately from Settings → API Keys and create a replacement.

Additional hardening available on Enterprise: IP allowlist (restrict which CIDR ranges may use a key) and IP blocklist. Both configured per-key from the same settings page.

Rate limits

Limits are per API key per rolling 60-second window. Webhooks are separately rate-limited on their inbound delivery surface.

PlanAPI req / minWebhooks / minBurstNotes
Basic6010No burst headroom
Pro30060Short burst window (5 s)
Business1000200Burst up to 3 000 RPM for ≤ 5 s
EnterpriseCustomCustomCustomNegotiated SLA, custom concurrency

Response headers

Every API response includes rate-limit headers so your integration can stay within bounds without trial and error:

HeaderValue
X-RateLimit-LimitMaximum requests allowed in the current window
X-RateLimit-RemainingRequests remaining in the current window
X-RateLimit-ResetISO 8601 timestamp when the window resets
Retry-AfterSeconds to wait before retrying (only on 429)

429 responses are retryable. Always read Retry-After and honour it. Do not hard-code a sleep duration — the exact window depends on your plan and current load.

Exponential backoff

Implement jittered exponential backoff whenever you receive a 429. This pattern prevents thundering-herd issues if your fleet is calling in parallel:

Node.jsPython

async function fetchWithRetry(url, key, maxRetries = 4) { for (let attempt = 0; attempt <= maxRetries; attempt++) { const res = await fetch(url, { headers: { Authorization: Bearer ${key} }, }); if (res.status !== 429) return res.json();

const retryAfter = parseInt(res.headers.get("Retry-After") ?? "1", 10);
const backoff = retryAfter * 1000 * Math.pow(2, attempt) + Math.random() * 200;
await new Promise(r => setTimeout(r, backoff));

} throw new Error("Rate limit retries exhausted"); }

Error codes

All errors use RFC 7807 Problem Details (application/problem+json):

401 Unauthorized

{ "type": "https://app.pipsync.io/errors/unauthorized", "title": "Unauthorized", "status": 401, "detail": "Missing or invalid API key" }

HTTP statusMeaningAction
400Bad RequestFix the request body / query params
401UnauthorizedCheck key value and Authorization header format
403ForbiddenKey lacks the required scope for this endpoint
404Not FoundResource does not exist or was deleted
422UnprocessablePasses schema but business-rule validation failed
429Rate LimitedBack off and retry (see Retry-After)
5xxServer ErrorTransient — retry with backoff; check pipsync.io/status

GET /v1/me

Returns the profile of the workspace owner associated with the API key.

GET/v1/meTry it ↗

GET /v1/signals

Returns parsed trading signals for the workspace. Signals are the normalized output of the parser — ready for downstream processing.

GET/v1/signalsTry it ↗

Query parameters

ParamTypeRequiredDescription
sinceISO 8601NoReturn signals received at or after this time
limitnumberNoMax results per page (default 25, max 100)
pagenumberNoPage number (1-based)
instrumentstringNoFilter by instrument, e.g. EURUSD
statusstringNoFilter by status: parsed | pendinginvalid

curl "https://app.pipsync.io/api/v1/signals?limit=10"
-H "Authorization: Bearer $PIPSYNC_KEY"

GET /v1/trades

Returns trade records (opened, closed, partially-closed positions) for the workspace. Paginated; newest trades first.

GET/v1/tradesTry it ↗

ParamTypeRequiredDescription
sinceISO 8601NoOnly trades opened at or after this time
limitnumberNoMax results per page (default 25, max 100)
pagenumberNoPage number (1-based)
instrumentstringNoFilter by instrument
statusstringNoFilter by status: open | closedpending

curl "https://app.pipsync.io/api/v1/trades?limit=25"
-H "Authorization: Bearer $PIPSYNC_KEY"

GET /v1/reports

Enumerate generated trade reports and download links. Use /v1/reports/trades to get the detailed line-item CSV/PDF export.

GET/v1/reportsTry it ↗

The full OpenAPI 3.1 spec (with request / response schemas for every endpoint) is available at /api/v1/openapi.json. Import it into Postman, Insomnia, or use the interactive playground to try every endpoint live.

Realtime stream

For browser dashboards and live monitoring, subscribe to /api/trading/stream with EventSource. This is the shipped SSE fallback when WebSocket upgrades are unavailable; keep signed webhooks for server-to-server automation.

Webhooks

Subscribe to push events from Settings → Webhooks. PipSync POSTs a signed JSON payload to your endpoint every time an event occurs. Delivery is attempted up to 5 times with exponential backoff.

POSTyour-server.com/pipsync — signed by X-PipSync-Signature

EventWhenPayload type
signal.receivedA signal was parsed from any sourceSignalIntent
signal.parsedParser normalized the source messageParsedSignal
trade.openedA broker position was openedTradeOpened
trade.closedA broker position was closedTradeClosed
trade.tp_hitTake profit was hitTradeClosed
trade.sl_hitStop loss was hitTradeClosed
subscription.upgradedSubscription moved to a higher tierSubscription
subscription.canceledCancellation was scheduledSubscription

Verifying signatures

Every webhook delivery includes an X-PipSync-Signature header formatted as t=<unix-ts>,v1=<hex-hmac-sha256>. Verify before trusting the payload:

Node.jsPython

import crypto from "crypto";

export function verifyWebhook(rawBody: string, header: string, secret: string): boolean { const parts = Object.fromEntries( header.split(",").map((part) => part.split("=")), ); const signed = parts.t + "." + rawBody; const expected = crypto .createHmac("sha256", secret) .update(signed) .digest("hex"); // Constant-time comparison to prevent timing attacks return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(parts.v1 ?? ""), ); }

Always verify the timestamp. Reject payloads where t is more than 5 minutes in the past — this prevents replay attacks. Compare Math.abs(Date.now() / 1000 - Number(parts.t)) > 300.

OpenAPI clients

The shipped contract is the OpenAPI 3.1 spec at /api/v1/openapi.json. Generate a typed client in your runtime — or use the interactive playground for ad-hoc requests.

TypeScript

Generate with openapi-typescript

/api/v1/openapi.json

Python

Generate with openapi-python-client

Go

Generate with oapi-codegen

Rust

Generate with progenitor or openapi-generator

C#

Generate with NSwag

MQL5

Use REST + signed webhook examples

Contact us for EA samples

Prefer the interactive playground for ad-hoc testing with your real key. Open Playground →