CMP42 // PRODUCT // APIREST + GRAPHQL PARITY
// Delivered · REST + GraphQL parity

A FAST,
BORING API.

For non-MCP clients, every operation is exposed through REST and GraphQL. Same auth, same audit trail. Ship the agent of the month against the same surface.

// API-first, not API-also

BORING IS A FEATURE.

In a UI-first CRM, the API tends to arrive after the interface. It covers what someone remembered to expose, lags behind new features, and behaves slightly differently from what the screen does. Integrators learn its quirks the hard way.

A headless CRM has no interface for the API to lag behind. In CMP42 the API is the product. The same operations your MCP tools perform are available over REST and GraphQL, against the same models, with the same validation.

We call it boring on purpose. Predictable resources that match your ontology. Errors that tell you what went wrong. No hidden behaviour that only happens when a human clicks. The interesting part should be what you build on top — the Slack bot, the internal app, the agent your team ships next month.

// Parity

THREE SURFACES. ONE CONTRACT.

Operations

Every operation, everywhere

For non-MCP clients, every operation is exposed through both REST and GraphQL. You never have to switch surfaces because one of them is missing a feature.

Auth

Same auth model

MCP, REST and GraphQL share one auth model. Permissions that apply on one surface apply on all of them — there is no side door.

Audit

Same audit trail

Every write is versioned and records the human or agent that produced it — whether it came from Claude via MCP, a Slack bot via REST or your app via GraphQL.

// What it looks like

SAME DATA. YOUR CHOICE OF SHAPE.

The snippets illustrate the same job on both surfaces: find the deals at the renewal stage, then write a note on a company.

With REST, you address resources and use HTTP verbs — easy to call from any language, easy to debug with curl.

With GraphQL, you ask for exactly the fields you need and follow typed edges — the deal’s owner, its company — in a single round trip.

Paths, field names and the header format are illustrative. The concrete API reference ships with the Alpha and is shaped together with the Design Partners.

REST · read and writeIllustrative
GET /deals?stage=renewal
Authorization: Bearer <token>

200 OK
{ "data": [
  { "id": "cmp42://deal/…",
    "title": "Aspen · Q4 renewal",
    "stage": "renewal",
    "owner": "cmp42://contact/…" } ] }

POST /companies/<id>/notes
{ "body": "Renewal risk: budget owner changed …" }

201 Created · written_by: app:slack-bot
GraphQL · one round tripIllustrative
query RenewalDeals {
  deals(stage: "renewal") {
    id
    title
    owner   { id name }
    company { id name }
  }
}

mutation {
  writeNoteOnCompany(company: "cmp42://company/…",
                     body: "Renewal risk: …") {
    id version writtenBy
  }
}
// Which surface when

MCP, REST OR GRAPHQL? PICK BY CLIENT.

Rule of thumb: if a model decides what to call next, use MCP. If your code decides, use REST or GraphQL.

AspectMCPRESTGraphQL
Best forAI agents that choose their own next stepScripts, bots and backend services with a fixed jobApps that need a specific slice of the graph
Typical clientClaude Desktop, Claude Code, Cursor, Cline, custom MCP SDK agentsYour team’s Slack bot, an internal automation, a data jobThe internal app or dashboard your engineers build
Shape of a callA tool call with typed input, e.g. list_deals_at_stageA resource plus an HTTP verbOne query with nested fields across typed edges
StrengthThe model discovers tools and their schemas at runtimeWorks from any language; simple to test and debugFetch exactly what you need, no over-fetching
Auth & auditSameSameSame
// Auth and audit

ONE AUTH MODEL. ONE AUDIT TRAIL.

Parity is not only about which operations exist; it is about how they are governed. Whatever surface a request comes through, it is authorised by the same model and recorded in the same audit trail. Every object is versioned; every write says which human or agent produced it.

That matters the day you switch agents. The Slack bot you retire and the agent that replaces it leave the same kind of record, so your history stays readable across tools and years.

Authentication uses workspace-scoped Bearer tokens: Personal Access Tokens for humans and Service Tokens for agents and bots, each carrying Model-level scopes so a token can be trusted with exactly the operations it needs. The default rate limit is 1000 requests per minute per token — hitting it returns a 429 with Retry-After. The API is versioned as a URL prefix (/api/v1/); breaking changes require a new major version, with at least twelve months of overlap where the previous version keeps working before it is retired.