API reference
Everything the console does goes through the CoSell HTTP API, and your own tools can call it too.
#Base URL and authentication
- Base URL:
https://api.cosell.habilelabs.io/api/v1
- Authentication:
Authorization: Bearer <ID token> from a CoSell user (Amazon Cognito). Calls run with that user's
role in the workspace.
- Bodies are JSON. Errors come back as
{ "error": "…", "details": [...] } with a meaningful status code:
- 400: the request was malformed
- 403: not allowed, or AWS refused the action
- 404: not found
- 409: a business rule was broken
- 422: validation failed
- Lists are paged with
limit and cursor. The response carries the next cursor when there is more.
All workspace paths below start with /tenants/{tenantId}.
#Searching, filtering and sorting lists
The opportunity, invitation, error, notification, audit and bulk job lists can also be searched, filtered and sorted. Add any of q, sort, order or offset to a list request, and it answers with numbered pages instead of a cursor.
| Parameter |
Meaning |
q |
Words to find. Every word must appear somewhere in the item; case does not matter. |
sort, order |
A column from the table below, and asc or desc. Items without a value come last. |
offset, limit |
Where the page starts, and its size (25 unless set, at most 100). |
| A filter name |
One or more values, separated by commas, for example syncStatus=failed,needs_information. |
| List |
Filters |
Sort columns |
opportunities |
syncStatus, origin, reviewStatus (none when AWS has not reviewed it), aceStage, awsLinkId, inAws (yes or no) |
updated, title, company, stage, review, sync, lastSync |
invitations |
status, awsLinkId |
received, respondBy, expires, title |
errors |
resolution, category |
created, retries, category, deal |
notifications |
type, read (read or unread) |
created, type |
audit |
action, actor, entityType |
created, actor, action |
bulk |
status, kind |
created, finished, status |
The answer is { "items", "total", "offset", "limit", "sort", "order", "facets", "scanLimited" }:
facets counts the items each filter value would leave, given the search and the other filters.
scanLimited is true when the workspace holds more than 5,000 records of that kind. In that case only the newest 5,000 were searched.
GET /tenants/{tenantId}/opportunities?q=acme&syncStatus=failed&sort=updated&order=desc&offset=0&limit=50
#Workspace
| Method and path |
Purpose |
GET /me |
The caller and their workspaces |
GET /tenants/{tenantId} |
Workspace settings and plan |
PATCH /tenants/{tenantId}/settings |
Update preferences ({ "name", "settings": { … } }) |
GET /tenants/{tenantId}/dashboard |
Counts by status, invitations, errors, Zoho budget |
GET, POST /tenants/{tenantId}/members |
List members, each with account: invited, active, reset_required, disabled, missing or unknown; or invite one ({ "email", "roles" }) |
POST /tenants/{tenantId}/members/{userId}/password |
Send a new temporary password to an invited member, or a reset code to an active one (admins); answers { "sent": "invitation" | "reset", "email" } |
DELETE /tenants/{tenantId}/members/{userId} |
Remove a member |
#Connections
| Method and path |
Purpose |
GET /tenants/{tenantId}/connections/zoho |
Zoho connection state, redirect and webhook URLs |
POST /tenants/{tenantId}/connections/zoho/authorize |
Start the Zoho consent flow |
POST /tenants/{tenantId}/connections/zoho/activate |
Re-run activation (fields, channel, currency) |
GET /tenants/{tenantId}/connections/zoho/fields |
Deal fields usable in filters and routing rules |
GET /tenants/{tenantId}/onboarding-template |
The CloudFormation template for your AWS account |
GET, POST /tenants/{tenantId}/aws-links |
List or link AWS accounts |
POST /tenants/{tenantId}/aws-links/{linkId}/verify |
Check the link again |
POST /tenants/{tenantId}/aws-links/{linkId}/default |
Make the link the default |
#Mapping
| Method and path |
Purpose |
GET, PUT /tenants/{tenantId}/mapping |
Read or save the mapping (a new version per save) |
GET /tenants/{tenantId}/mapping/check |
Is a deal at the gate ready to submit, and why not |
POST /tenants/{tenantId}/mapping/deal-filter/preview |
Try a deal filter on recent deals |
#Opportunities and referrals
| Method and path |
Purpose |
GET /tenants/{tenantId}/opportunities |
Tracked deals and their ACE opportunities |
GET /tenants/{tenantId}/opportunities/{crmRecordId} |
One deal with its sync history |
POST /tenants/{tenantId}/opportunities/{crmRecordId}/actions |
{ "action": "sync" | "submit" | "refresh" | "retry" } |
GET, POST /tenants/{tenantId}/opportunities/{crmRecordId}/assistant |
Ask Partner Central ({ "question" }) and read the answers |
POST /tenants/{tenantId}/opportunities/{crmRecordId}/drafts |
Draft next steps and a summary ({ "meetingNotes" }, optional) |
GET /tenants/{tenantId}/aws-import/preview?scope=live |
Opportunities that can be imported into Zoho |
POST /tenants/{tenantId}/aws-import |
Import them ({ "opportunityIds", "awsLinkId" }) |
GET /tenants/{tenantId}/invitations?status=pending |
AWS referrals |
POST /tenants/{tenantId}/invitations/{invitationId}/decision |
{ "decision": "accept" | "reject", "reason", "awsLinkId" } |
POST /tenants/{tenantId}/invitations/{invitationId}/import |
Finish the import of an accepted referral now |
POST /tenants/{tenantId}/invitations/refresh |
Check AWS for invitations CoSell missed |
#Bulk operations, private offers and partners
| Method and path |
Purpose |
GET /tenants/{tenantId}/bulk/csv-template |
The CSV template for your mapping |
POST /tenants/{tenantId}/bulk/csv/check |
Check a CSV ({ "csv" }) without writing anything |
POST /tenants/{tenantId}/bulk/csv |
Import it as a bulk job |
POST /tenants/{tenantId}/bulk/update |
{ "crmRecordIds", "changes": [{ "field", "value" }], "runAt" }; fields include stage and lostReason |
POST /tenants/{tenantId}/bulk/assign |
{ "crmRecordIds", "assignee": { "name", "email" }, "runAt" } |
GET /tenants/{tenantId}/bulk, GET /tenants/{tenantId}/bulk/{jobId} |
Bulk jobs, and one job's rows |
POST /tenants/{tenantId}/bulk/cancel |
{ "jobId" } |
GET /tenants/{tenantId}/opportunities/{crmRecordId}/offers |
Linked private offers, their agreements and drafts |
POST /tenants/{tenantId}/opportunities/{crmRecordId}/offers/link |
{ "offer" } (ID or ARN) |
POST /tenants/{tenantId}/opportunities/{crmRecordId}/offers/draft |
{ "productId", "name", "buyerAccountId" } |
GET /tenants/{tenantId}/marketplace/offers, GET /tenants/{tenantId}/marketplace/products |
Your private offers and products |
GET /tenants/{tenantId}/partners |
Partners you are connected with |
GET /tenants/{tenantId}/opportunities/{crmRecordId}/engagement |
The opportunity's partners and invitations sent |
POST /tenants/{tenantId}/opportunities/{crmRecordId}/partner-invitations |
{ "receiverAccountId", "responsibilities", "message" } |
POST /tenants/{tenantId}/partners/snapshot-role |
Use CoSell's snapshot job role (admins) |
#AI: assistant, proposals and pipeline health
| Method and path |
Purpose |
GET, POST /tenants/{tenantId}/assistant/conversations |
Your conversations; start one with { "message" } |
GET /tenants/{tenantId}/assistant/conversations/{conversationId} |
A conversation, its messages and its proposals |
POST /tenants/{tenantId}/assistant/conversations/{conversationId}/messages |
Send { "message" }; the answer arrives asynchronously |
GET /tenants/{tenantId}/proposals?status=pending |
Proposals, filtered by status, crmRecordId or conversationId |
POST /tenants/{tenantId}/proposals/decision |
{ "proposalId", "decision": "approve" | "reject" | "override", "text", "note" } |
GET /tenants/{tenantId}/risks |
Pipeline health findings (?crmRecordId= for one deal) |
POST /tenants/{tenantId}/risks/dismiss |
{ "key", "snoozeDays" }; without snoozeDays, until the facts change |
POST /tenants/{tenantId}/risks/restore |
{ "key" } |
#Errors, notifications and audit
| Method and path |
Purpose |
GET /tenants/{tenantId}/errors?resolution=open |
Sync errors |
POST /tenants/{tenantId}/errors/actions |
{ "errorId", "action": "retry" | "resolve" } |
GET /tenants/{tenantId}/notifications |
Notifications. Each has a path: the console page it is about, relative to the workspace (for example opportunities/{crmRecordId}) |
POST /tenants/{tenantId}/notifications/read |
Mark one read ({ "notificationId" }) |
POST /tenants/{tenantId}/notifications/read-all |
Mark every unread notification read; answers { "marked" } |
DELETE /tenants/{tenantId}/notifications |
Delete them all (admins); answers { "deleted" } and is audited |
GET /tenants/{tenantId}/audit |
The audit log |
#Endpoints without a user
| Method and path |
Purpose |
POST https://api.cosell.habilelabs.io/webhooks/zoho/{tenantId} |
Zoho workflow webhook; send the webhook token in x-cosell-token |
POST https://api.cosell.habilelabs.io/marketplace/register |
AWS Marketplace fulfillment URL |
GET https://api.cosell.habilelabs.io/health |
Service health |