Quick start
Authenticate with a project API key and make your first REST request.
The REST API covers the resources in each Saasco app — analytics, CRM, email, workflows, knowledge, support, short links, social proof, feedback, roadmap, changelog, disputes, and benchmarks — from a server you control. It is the right tool for backfills, syncs from your own backend, and anything that runs without a browser.
Every endpoint lives under one base URL:
https://www.saasco.com/api/v2/Setup
Generate an API key
In your project dashboard, go to Settings → API Keys and click Create key.
- Enter a descriptive name for your key (e.g.
my-app-production) - Click Create key
- Copy the key immediately, because you won't be able to see it again
Your API key is only shown once at creation time. Store it somewhere safe like a password manager or environment variable. If you lose it, you'll need to generate a new one.
Store the key and your project id in your environment:
SAASCO_API_KEY=sk_live_your_api_key_here
SAASCO_PROJECT_ID=your_project_idYour project id is on Settings → Project.
Make your first call
Requests take the key in the Authorization header. Almost every path is project-scoped, so the project id goes in the URL:
curl "https://www.saasco.com/api/v2/projects/$SAASCO_PROJECT_ID/crm/attributes" \
-H "Authorization: Bearer $SAASCO_API_KEY"Or from JavaScript:
const response = await fetch(
`https://www.saasco.com/api/v2/projects/${process.env.SAASCO_PROJECT_ID}/crm/attributes`,
{
headers: {
Authorization: `Bearer ${process.env.SAASCO_API_KEY}`,
"Content-Type": "application/json",
},
}
);
const attributes = await response.json();
console.log(attributes);Responses are the resource itself, with no envelope:
[
{
"id": "plan",
"projectId": "your_project_id",
"type": "string",
"totalCount": 1284,
"uniqueCount": 3
}
]Browse the endpoints
Every page under this section is generated from the live OpenAPI document, with each endpoint's parameters, response schema and a runnable example. Good places to start: List Contacts, Query Events, List Email Campaigns.
The document itself is served at /api/v2/openapi.json if you'd rather generate a client.
Authentication
A key is bound to one project, and every project-scoped path re-checks that the key belongs to the projectId in the URL, so there is no cross-project read. Keys are rejected by the MCP server, which uses OAuth instead, and an MCP token is rejected here.
Errors come back with a code and the HTTP status:
{
"message": "You must be logged in or use a valid API key to access this resource",
"code": "UNAUTHORIZED",
"data": { "httpStatus": 401, "path": "crm.listAttributes" }
}Invalid API key in the same shape means the header arrived but the key didn't match.
Pagination
List endpoints page with skip and take. Collection responses carry a count alongside the rows, so you can stop once you've read them all:
const take = 100;
let skip = 0;
let count = Infinity;
while (skip < count) {
const response = await fetch(
`https://www.saasco.com/api/v2/projects/${projectId}/crm/contacts/query`,
{
method: "POST",
headers: {
Authorization: `Bearer ${process.env.SAASCO_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ skip, take }),
}
);
const page = await response.json();
handle(page.data);
count = page.count;
skip += take;
}Analytics endpoints that read event streams (User Events, Query Events) take limit and a cursor instead. Pass back the cursor from the previous page.
Reads and writes here bill the same as the equivalent call from the SDK or MCP. A backfill that walks every contact costs what walking every contact costs.
Tool reference
Every tool the Saasco MCP server exposes, what it does, and whether it reads or writes.
List Users
Lists identified users for the project, most recently seen first, each with their full property bag. Only users who have been through an `identify()` call appear here. Anonymous visitors are counted by Current Users and Query Sessions but have no record to list.