Skip to content

Overview

The Pinlyx Public API provides programmatic access to your contacts, Telegram messaging, the social inbox and post scheduler, sales pipeline (deals), tasks, finance (read-only) and the email inbox. All requests must include an Authorization: Bearer <token> header where the token is a Pinlyx API key in the format csk_<env>_<keyId><secret>. Access is scope-based - each key is issued with a specific set of scopes (e.g. contacts:read, telegram:send), and operations that require a scope not granted to the key return 403 Forbidden. All responses are JSON. Rate limits are per-key and communicated via X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset response headers. An MCP server for AI agent integration is available at the same host (POST /mcp).

Workspaces (X-Workspace-Id)

CRM data is shared inside a workspace. Send X-Workspace-Id: <id> on any CRM request to act on that team’s shared pool; omit it and the key resolves your default workspace, falling back to your personal data when you belong to none. Membership is verified server-side on every request, so an id you are not a member of silently falls back to personal scope instead of widening access. GET /v1/me lists the workspaces a key may address and the role it holds in each; a viewer role can read but every write returns 403.

Idempotent writes (Idempotency-Key)

Send Idempotency-Key: <your-unique-string> on POST /v1/contacts, POST /v1/contacts/batch or PATCH /v1/contacts/{id} to make a retry safe. The first call runs and its status code and body are stored for 24 hours; a repeat of the same key returns that stored response verbatim with Idempotency-Replayed: true, without touching your data. Reusing a key with a different request body returns 409 - that is a client bug, not a retry.

Property casing

Property names inside a response object are PascalCase (Id, ExternalId, CustomFields); only the pagination envelope keys (items, nextCursor, hasMore) and the tag dictionary are camelCase. The schemas below spell properties in camelCase for readability, so match them case-insensitively when you generate a client. Request bodies are parsed case-insensitively, so either casing is accepted on the way in.

Pagination

Every collection endpoint returns the same envelope: { "items": [...], "nextCursor": <cursor|null>, "hasMore": <bool> }. Pass the returned nextCursor back as after (or before on message threads and the conversation list) to fetch the next page. Endpoints whose result set is naturally complete - connected accounts, pipeline boards, a contact’s tags - still return the envelope with nextCursor: null and hasMore: false, so one client loop works everywhere.

Plan-gated modules

A scope says what a key is allowed to do; the workspace’s plan says what the workspace has. Modules that are not on every plan (the social inbox and the post scheduler today) answer 402 with error: payment_required and the missing feature key in details.FeatureKey when the plan lacks them. That is a permanent answer for that workspace until it upgrades, so treat it as a configuration problem rather than a transient failure and do not retry it.

  • OpenAPI version: 3.0.3

Pinlyx API key. Format: csk_<env>_<12-char-keyId><32-char-secret>. Obtain keys from the Pinlyx dashboard. Keep secret - the full token is never stored server-side (only a bcrypt hash of the secret portion).

Security scheme type: http

Bearer format: csk_<env>_<key>