REST API reference
Sloggr Developer API v1 — authentication, scopes, endpoints, pagination, analytics, errors, and examples for developers and AI agents.
This is the public contract for Sloggr Developer API v1. It is written for human developers and for AI assistants that need accurate, citable endpoint details.
- Base URL:
https://app.saleslogger.app/api/v1/ - OpenAPI: https://saleslogger.app/openapi/api-v1.yaml
- Webhooks: Outbound webhooks
- Product: About Sloggr
Authentication
Create an API key in the app: Settings → API Keys.
Authorization: Bearer <api_key_secret>
Content-Type: application/json
Optional request signing (recommended for server-to-server writes). If present, the signature must be valid:
X-Sloggr-Signature: <hex_hmac_sha256(raw_body, api_key_secret)>
| Condition | Result |
|---|---|
| Missing / invalid / revoked key | 401 unauthorized |
| Signature present but wrong | 403 forbidden |
| Key missing required scope | 403 forbidden |
Rate limit: 60 requests/minute per API key (configurable). Exceeding the limit returns 429.
Tenancy model
| Concept | Meaning |
|---|---|
| Account org | Your Sloggr account. Owns API keys, webhook subscriptions, billing, and team users. |
| Target org | A customer organization belonging to the account. Deals, tickets, and contacts live here. |
| API key scope | Every key belongs to one account org. It can only see that account’s data. |
Cross-account access is rejected even if record IDs collide globally.
External app identity (recommended)
Integrators should send:
| Field | Description |
|---|---|
source_app | Stable app id (e.g. client-diary, n8n) |
external_org_id | Your tenant/practice id |
Sloggr stores (source_app, external_org_id) → org_id after the first successful resolve. You do not need to persist Sloggr org ids for normal flows.
First-time link hints: org_name, contact_email (and optional contact_name).
API key scopes
| Access | How to create | Can do |
|---|---|---|
Full (*) | Default “Full access” key, or legacy keys with scopes = null | Read + write |
| AI / agent read-only | “AI / agent read-only” in API Keys UI | Lists, activity, analytics, webhook read — no creates/updates |
Capabilities
| Capability | Typical routes |
|---|---|
orgs:read / orgs:write | List orgs; resolve / link external ids |
users:read | List team members |
contacts:read | List contacts; marketing audience GET |
deals:read / deals:write | List/get/search deals; list/create activities |
support:read / support:write | List/get tickets & logs; create tickets |
activity:read | Unified activity feed |
analytics:read | /analytics/* |
webhooks:read / webhooks:write | List endpoints/deliveries; create endpoints |
read | Bundle of all read capabilities |
* | Everything |
Marketing audience PUT/DELETE requires full access (*).
Conventions
Dates and times
- Prefer ISO-8601 (
2026-08-11T15:00:00or withZ) - Day bounds also accept
YYYY-MM-DD - Analytics also accept report presets via
range=(see Analytics)
Pagination
| Param | Default | Notes |
|---|---|---|
page | 1 | ≥ 1 |
per_page | 25 | Max 100 |
List responses include:
{
"pagination": {
"page": 1,
"per_page": 25,
"total": 120,
"pages": 5,
"has_next": true,
"has_prev": false
}
}
Sorting (where supported)
sort + direction (asc | desc). Deal/ticket sorts include created_at, updated_at, id, title, status.
Idempotency (writes)
Send either:
- Header:
Idempotency-Key: your-unique-key - Body:
"idempotency_key": "..."
Same key + account within the retention window returns the original response (no duplicate create).
Errors
Machine-readable JSON:
{
"error": "validation_error",
"message": "contact_email is required when contact_id is omitted.",
"fields": {
"contact_email": "required"
}
}
| HTTP | error examples | Meaning |
|---|---|---|
| 401 | unauthorized | Auth failure |
| 403 | forbidden | Scope, tenancy, or bad signature |
| 404 | *_not_found, org_not_found | Missing in account scope |
| 409 | org_ambiguous | Multiple org matches |
| 422 | validation_error, org_lookup_required | Bad input |
| 429 | rate limited | Slow down |
| 500 | internal_error | Unexpected server error |
Passwords, API secrets, and auth tokens are never returned in resource payloads (webhook endpoint create returns the endpoint signing secret once).
Endpoint index
Organizations
| Method | Path | Scope | Purpose |
|---|---|---|---|
GET | /orgs | orgs:read | List customer orgs (q) |
POST | /orgs/resolve | orgs:write | Map external tenant → org |
PUT | /orgs/{org_id}/external-ids | orgs:write | Manual external id link |
Users & contacts
| Method | Path | Scope | Purpose |
|---|---|---|---|
GET | /users | users:read | Account team members |
GET | /contacts | contacts:read | Contacts (org_id, email, q) |
GET | /contacts/{id}/marketing-audiences | contacts:read | Marketing memberships |
PUT/DELETE | /contacts/{id}/marketing-audiences | * | Update/remove memberships |
Deals
| Method | Path | Scope | Purpose |
|---|---|---|---|
GET | /deals | deals:read | List/filter/sort deals |
GET | /deals/search | deals:read | Lookup by Stripe id / email / org |
GET | /deals/{id} | deals:read | Get one deal |
GET | /deals/{id}/activities | deals:read | Timeline activities |
POST | /deals/{id}/activities | deals:write | Log note/call/email/meeting |
Support
| Method | Path | Scope | Purpose |
|---|---|---|---|
GET | /support/tickets | support:read | List tickets |
POST | /support/tickets | support:write | Create ticket + first log |
GET | /support/tickets/{id} | support:read | Get ticket |
GET | /support/tickets/{id}/logs | support:read | List support logs |
Activity & analytics
| Method | Path | Scope | Purpose |
|---|---|---|---|
GET | /activity | activity:read | Unified activity feed |
GET | /analytics/sales | analytics:read | Sales aggregates + compare |
GET | /analytics/support | analytics:read | Support aggregates + compare |
GET | /analytics/team | analytics:read | Per-user totals |
GET | /analytics/customers | analytics:read | Customer health |
GET | /analytics/activity | analytics:read | Activity volume mix |
GET | /analytics/trends | analytics:read | ISO-week trends |
Webhooks (management)
| Method | Path | Scope | Purpose |
|---|---|---|---|
GET | /webhooks/endpoints | webhooks:read | List subscriptions |
POST | /webhooks/endpoints | webhooks:write | Register endpoint |
GET | /webhooks/deliveries | webhooks:read | Delivery log |
Full event catalog and signing: Webhooks docs.
Organizations
Resolve external org
POST /api/v1/orgs/resolve
| Field | Required | Description |
|---|---|---|
source_app | Yes | App identifier |
external_org_id | Yes | Your tenant id |
org_name | When unmapped | Customer name hint |
contact_email | When unmapped | Primary contact email |
contact_name | No | Disambiguation |
200 statuses: mapped (already linked) or linked (newly linked).
curl -sS -X POST 'https://app.saleslogger.app/api/v1/orgs/resolve' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"source_app": "client-diary",
"external_org_id": "practice_8842",
"org_name": "Acme Physio",
"contact_email": "owner@acmephysio.com"
}'
List orgs
GET /api/v1/orgs?q=acme&page=1&per_page=25
Manual link
PUT /api/v1/orgs/{org_id}/external-ids
{ "source_app": "client-diary", "external_org_id": "practice_8842" }
Users & contacts
List users
GET /api/v1/users?active_only=1
Returns account team members (id, email, display_name, role, is_active, support_enabled). No passwords or secrets.
List contacts
GET /api/v1/contacts?org_id=14673&q=jane
Deals
List deals
GET /api/v1/deals?status=qualified&owner_user_id=12&created_from=2026-08-01&sort=updated_at&direction=desc
Useful filters: status, org_id, owner_user_id, q, created_from/created_to, updated_from/updated_to.
Search deals
GET /api/v1/deals/search?stripe_customer_id=cus_abc123
At least one of: stripe_customer_id, contact_email, org_id.
Get deal
GET /api/v1/deals/{deal_id}
List deal activities
GET /api/v1/deals/{deal_id}/activities
Create deal activity
POST /api/v1/deals/{deal_id}/activities
Idempotency-Key: n8n:welcome-email:cus_abc123
| Field | Required | Description |
|---|---|---|
source_app | Yes | Integrator id |
message | Yes | Timeline text |
activity_kind | No | note (default), email, call, meeting |
outcome | No | success, failed, skipped |
external_reference | No | Caller reference |
metadata_json | No | Opaque object |
Emits webhook deal.activity.created when delivery subscriptions exist.
curl -sS -X POST 'https://app.saleslogger.app/api/v1/deals/42/activities' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: n8n:welcome:42' \
-d '{
"source_app": "n8n",
"message": "Welcome email sent",
"activity_kind": "email",
"outcome": "success"
}'
Support tickets
Create ticket
POST /api/v1/support/tickets
| Field | Required | Description |
|---|---|---|
source_app | Yes | App id |
external_org_id | Yes | Your tenant id |
title | Yes | Ticket title |
details | Yes | Description |
contact_email | Yes* | Required unless contact_id |
org_name | When unmapped | Lookup hint |
note | No | First update body (defaults to details) |
channel | No | Default api |
external_reference | No | Caller case id |
metadata_json | No | Opaque object |
idempotency_key | No | Or use header |
curl -sS -X POST 'https://app.saleslogger.app/api/v1/support/tickets' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-H 'Idempotency-Key: client-diary:case-8842' \
-d '{
"source_app": "client-diary",
"external_org_id": "practice_8842",
"org_name": "Acme Physio",
"title": "Cannot export diary entries",
"details": "Export button greyed out on mobile Safari.",
"contact_email": "owner@acmephysio.com",
"channel": "api",
"external_reference": "case-8842"
}'
List tickets
GET /api/v1/support/tickets?open_only=1&org_id=14673
Filters: status, open_only, org_id, owner_user_id, q, created_from/created_to, sort.
Get ticket / list logs
GET /api/v1/support/tickets/{ticket_id}
GET /api/v1/support/tickets/{ticket_id}/logs
Unified activity
Normalized customer-facing activity across deal timeline events and support logs.
GET /api/v1/activity?org_id=14673&from=2026-04-25&to=2026-07-24&employee_user_id=12&source=all
| Param | Description |
|---|---|
org_id | Customer org |
employee_user_id / user_id | Actor filter |
deal_id / ticket_id | Related entity |
source | all, timeline, sales, support_log, support |
from / to | Date range |
Each activity includes stable composite ids such as timeline:123 or support_log:456, plus employee, customer, type, content, related deal/ticket ids, and timestamps.
Note: Results are capped at 500 rows per source before pagination — narrow with from/to for large accounts.
Analytics
Server-side aggregates so agents do not need to download thousands of records. Prefer a read-only API key.
Date selection
| Param | Description |
|---|---|
range | Preset: today, this_week, last_week, this_month, last_month, this_quarter, this_year, last_year (default this_month) |
from / to | Custom range (overrides preset) |
compare | 1 / true / previous — include prior period + change |
Change objects look like:
{
"absolute": 4,
"percent": 25.0,
"note": null
}
When the previous value is 0, percent is null and note is "zero_baseline" (unless both periods are zero).
Sales
GET /api/v1/analytics/sales?range=this_month&compare=1
Includes sales results (created/won/lost/win rate/by rep), funnel, lost reasons, and open-pipeline follow-up signals (overdue_followups, deals_without_activity_14d). Optional: owner_user_id, by=owner|closer.
Support
GET /api/v1/analytics/support?range=this_month&compare=1
Tickets created, currently open, resolved/closed in period, support updates, aged open (>7d), by employee and by customer.
Team / customers / activity / trends
GET /api/v1/analytics/team?range=this_month
GET /api/v1/analytics/customers?range=this_month
GET /api/v1/analytics/activity?range=this_month
GET /api/v1/analytics/trends?range=this_month
/analytics/customers includes customer health rankings and customers_with_open_support_and_open_deals.
Example questions → endpoints
| Question | Endpoint |
|---|---|
| How did sales do this month vs last? | GET /analytics/sales?range=this_month&compare=1 |
| Which tickets are still open? | GET /support/tickets?open_only=1 |
| Everything for customer X in 90 days | GET /activity?org_id=X&from=...&to=... |
| Who has the most support updates? | GET /analytics/support or /analytics/team |
| Customers with open support and open deals | GET /analytics/customers |
| Overdue follow-ups | GET /analytics/sales → open_pipeline.overdue_followups |
The API returns facts and calculations. Interpretation/commentary belongs in your AI layer, not in Sloggr.
Setup checklist (external SaaS)
- Create an API key (full for writes, or AI read-only for analytics).
- Store the secret in your backend only.
- Agree a stable
source_appstring with the account holder. - Call
POST /orgs/resolveon tenant onboarding. - Create tickets / log deal activities with idempotency keys.
- Optionally register webhook endpoints for push updates.