Skip to content
Get API key (opens in a new tab)

Cevoid API

Read and write profiles, loyalty data, products, posts, orders and more with the versioned Cevoid REST API.

Use the Cevoid API to work with profiles, loyalty data, labels, products, posts, reviews, markets and orders from your own servers. It is a REST API over HTTPS that accepts and returns JSON.

If you are embedding widgets, tracking storefront analytics or connecting an AI client, see Widget, the Analytics SDK and MCP. If you use Cevoid in the platform, see the Help Center.

At a glance

TopicDetails
Base URLhttps://api.cevoid.com/v2
AuthenticationSecret key as a bearer token, see Authentication
FormatJSON request and response bodies
PaginationCursor-based, see Pagination
Rate limits25 reads and 10 writes per second per workspace, see Rate limits

Make your first request

Create a secret key in Settings → Integrations → Cevoid API⁠, store it in an environment variable, then call GET /v2/me to check that it works:

Verify your key
export CEVOID_API_KEY="cev_sk_..."

curl https://api.cevoid.com/v2/me \
  -H "Authorization: Bearer ${CEVOID_API_KEY}"

The response describes the key, its workspace and its scopes:

200 OK
{
  "data": {
    "id": "6f3ab66f14ebd9b9c67d1a31",
    "name": "Production integration",
    "type": "secret",
    "scopes": ["profiles:read", "orders:read"],
    "workspace": {
      "id": "6648c0f7bb9fd2d956fb0a42",
      "name": "Cevoid Demo"
    },
    "rate_limits": {
      "reads": 25,
      "writes": 10
    }
  }
}

List resources

List endpoints return one page at a time. Pass limit (1 to 100) and send the next_cursor from each response back as cursor until has_more is false:

List posts
curl "https://api.cevoid.com/v2/posts?limit=25" \
  -H "Authorization: Bearer ${CEVOID_API_KEY}"
200 OK
{
  "data": [],
  "has_more": true,
  "next_cursor": "eyJpZCI6InBvc3RfMDEifQ"
}

The same loop in TypeScript, with error handling:

list-posts.ts
const API_URL = "https://api.cevoid.com/v2"

type Page<T> = { data: T[]; has_more: boolean; next_cursor: string | null }

type ApiError = {
  status: number
  code: string
  message: string
  request_id: string
}

export async function listAllPosts(): Promise<unknown[]> {
  const posts: unknown[] = []
  let cursor: string | null = null

  do {
    const url = new URL(`${API_URL}/posts`)
    url.searchParams.set("limit", "100")
    if (cursor) url.searchParams.set("cursor", cursor)

    const response = await fetch(url, {
      headers: { Authorization: `Bearer ${process.env.CEVOID_API_KEY}` },
    })

    if (!response.ok) {
      const error = (await response.json()) as ApiError
      throw new Error(`${error.code}: ${error.message} (${error.request_id})`)
    }

    const page = (await response.json()) as Page<unknown>
    posts.push(...page.data)
    cursor = page.has_more ? page.next_cursor : null
  } while (cursor)

  return posts
}
Show all 36 linesShow fewer lines

Keep every filter except cursor unchanged between page requests.

Handle errors

Errors share one shape. Use the HTTP status for broad handling and code for specific recovery, and log request_id for every failed request:

422 Unprocessable Entity
{
  "status": 422,
  "code": "validation_error",
  "message": "Request validation failed",
  "request_id": "req_abc123",
  "additional_data": {
    "errors": [
      {
        "field": "query.limit",
        "message": "Too big: expected number to be <=100"
      }
    ]
  }
}
Note:

Do not retry 401, 403, 404 or 422 responses until you change the request. Retry a 429 only after the Retry-After delay.

Guides

Reviews

See the product review and company review references for filters, includes and localized response fields, and review requests for review invitations and their completion state. Import reviews from another platform with POST /v2/product-reviews and POST /v2/company-reviews; both take an Idempotency-Key.

OpenAPI specification

The reference is generated from the OpenAPI specification. Download it to generate a client or import the API into your HTTP tool.