Pull feedback results, goal progress, meeting records, and team responsiveness into your own tools — authenticated with a single API key.
Your API Key
Paste your workspace API key to enable the Try-it panels below. Stored only in this browser tab — never sent to our servers from this page.
Don't have one? Get an API key →
The DeskChime REST API gives you read access to your organization's data — feedback, goals, meetings, one-on-ones, users, and activity reports — so you can push it into your own dashboards, BI tools, or HR platforms.
Base URL
https://deskchime.com
Format
JSON (UTF-8)
Timestamps
UTC ISO 8601
Every request must include your organization's API key in the x-api-key header. Generate your key in Settings → Workspace → API Key (Admin role required). Regenerating a key immediately invalidates the previous one.
curl "https://deskchime.com/api/v1/feedback" \ -H "x-api-key: YOUR_API_KEY"
Missing header
x-api-key header not present
Invalid format
Key format is not recognized
Key not found
Key doesn't match any organization
Cross-org access
User/resource belongs to a different org
Invalid filter
Unknown enum value or unparseable date in a query param
Not found
No record with that id in your organization
All /api/v1/* endpoints allow 60 requests per 60 seconds per organization (burst-friendly — not strictly 1/sec). When the limit is exceeded you receive a 429. Check Retry-After and back off.
| Response header | Meaning |
|---|---|
| X-RateLimit-Limit | Maximum requests allowed in the window (60) |
| X-RateLimit-Remaining | Requests remaining in the current window |
| X-RateLimit-Reset | ISO timestamp when the window resets |
| Retry-After | Seconds to wait — only present on 429 responses |
/api/workspace-statsHigh-level counts for your organization — goals, users, teams, meetings, feedback, and more. Cancelled meetings and archived goals are excluded; pendingReviews counts feedback cycles that have not closed yet.
curl
curl "https://deskchime.com/api/workspace-stats" \ -H "x-api-key: YOUR_API_KEY"
Example response
{
"success": true,
"organization": {
"id": 1,
"name": "Acme Inc.",
"slug": "acme"
},
"stats": {
"totalGoals": 12,
"totalUsers": 8,
"totalTeams": 3,
"totalReviews": 24,
"totalMeetings": 47
}
}/api/workspace-stats/userStats for a specific user — feedback given/received, goals, meetings, and applaudes. One-on-ones count meetings the member organized or took part in.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | string | required | User email address |
curl
curl -X POST "https://deskchime.com/api/workspace-stats/user" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'Example response
{
"success": true,
"user": {
"id": "u1",
"email": "[email protected]",
"name": "Jane"
},
"stats": {
"feedbacksGiven": 3,
"feedbacksReceived": 5,
"totalGoals": 4,
"completedGoals": 2,
"oneOnOnes": {
"total": 8,
"completed": 7
}
}
}/api/v1/usersAll users in your organization with their roles and status. Filter by role. state is "active", "invited" (pending invitation) or "deactivated"; deactivated members stay in the list with deactivatedAt set so integrations can see who left and when. The existing integer status field is retained for backwards compatibility, but state is preferred. managers[] is always an array, [] when the user has no managers — DeskChime has no single manager column, a manager is a TeamManager of any team the user is a TeamMember of, and both relations are many-to-many, so a user can have zero, one, or several managers. Only direct team membership counts; team hierarchy is not walked. Scoped to your organization's teams, and a user is never listed as their own manager.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| page | query | number | optional | Page number (default: 1) |
| limit | query | number | optional | Results per page, max 50 (default: 20) |
| role | query | string | optional | Filter by role: SuperAdmin | Admin | Manager | Member. Any other value returns 400. |
curl
curl "https://deskchime.com/api/v1/users?page=1&limit=20&role=Manager" \ -H "x-api-key: YOUR_API_KEY"
Example response
{
"data": [
{
"id": "u1",
"name": "Jane Smith",
"email": "[email protected]",
"role": "Admin",
"status": 1,
"state": "active",
"deactivatedAt": null,
"isOnboarded": true,
"joinedAt": "2024-09-01T10:00:00Z",
"managers": []
},
{
"id": "u2",
"name": "Bob Lee",
"email": "[email protected]",
"role": "Member",
"status": 0,
"state": "invited",
"deactivatedAt": null,
"isOnboarded": true,
"joinedAt": "2024-10-15T09:30:00Z",
"managers": [
{
"id": "u5",
"name": "Priya Nair",
"email": "[email protected]"
}
]
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 8,
"totalPages": 1,
"hasMore": false
}
}/api/v1/feedbackPaginated list of feedback forms in your organization. responseCount counts live responses only — withdrawn ones are not included. email, userId, and assignee filter to cycles where the named user is an assignee — assignee is an accepted alias for userId, kept for integrations already sending it. Supply only one of the three; supplying more than one returns 400. An unknown user returns 404, and a user outside your organization returns 403. This is unrelated to status, which keeps filtering the raw Review.status column exactly as before. Omitting email, userId, and assignee lists feedback across the whole organization.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| page | query | number | optional | Page number (default: 1) |
| limit | query | number | optional | Results per page, max 50 (default: 20) |
| status | query | string | optional | Filter by the raw lifecycle flag. Feedback is created as "pending" and stays there — use closeDate to tell whether a cycle has closed. |
| query | string | optional | Filter to cycles where this member is an assignee. Provide only one of email, userId, or assignee — supplying more than one returns 400. An unknown user returns 404, and a user outside your organization returns 403. | |
| userId | query | string | optional | Filter to cycles where this member is an assignee, by DeskChime user id. Stable across email changes. Same either/or rule as email. |
| assignee | query | string | optional | Accepted alias for userId, kept for existing integrations already sending assignee. Same either/or rule as email and userId — combining it with either returns 400. |
curl
curl "https://deskchime.com/api/v1/feedback?page=1&limit=20&status=pending&email=jane%40acme.com" \ -H "x-api-key: YOUR_API_KEY"
Example response
{
"data": [
{
"id": "abc",
"title": "Q1 Review",
"status": "pending",
"frequency": "Once",
"assigneeCount": 5,
"responseCount": 3,
"createdAt": "2025-01-15T10:00:00Z"
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 42,
"totalPages": 3,
"hasMore": true
}
}/api/v1/feedback/:idSingle feedback form with an anonymised per-question response summary (no individual names).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string | required | Feedback ID |
curl
curl "https://deskchime.com/api/v1/feedback/abc123" \ -H "x-api-key: YOUR_API_KEY"
Example response
{
"data": {
"id": "abc",
"title": "Q1 Review",
"status": "completed",
"assigneeCount": 8,
"responseCount": 6,
"questions": [
{
"id": 1,
"question": "Rate communication",
"type": "scale",
"responseCount": 6,
"averageScore": 4.2,
"scale": {
"min": "1",
"max": "5"
}
},
{
"id": 2,
"question": "What's working well?",
"type": "textarea",
"responseCount": 5
}
]
}
}/api/v1/feedback/requestsLists individual outstanding feedback requests, one row per assignee per cycle, with a derived status — status is never stored, it's computed as pending, answered, or expired, and the same predicate drives the query filter, so meta.total and paging stay correct for a filtered request rather than counting the unfiltered set. Omitting status returns all three. Anonymous feedback cycles are excluded from data[] entirely — that's a privacy boundary, not an oversight — and show up only as the aggregate meta.excludedAnonymous count, so meta.total + meta.excludedAnonymous reconciles against stats.feedback.received from the activity endpoint for the same user and month. Returns identity, titles, and timestamps only — never feedback content, answers, or ratings. cycleTitle maps to Review.review_name, an optional column, so it can be null. cycleDescription comes from the cycle's form record and is null when unset. subjectUserId, subjectName, and subjectEmail identify the respondent — the person the request is on, i.e. who is being asked — while requestedByUserId/requestedByName are the creator of the cycle. On a single-user query (email or userId) subjectUserId necessarily equals the user you queried for, so it only carries new information on org-wide calls. respondedAt is set only once the request has actually been answered, and stays null otherwise. Omitting both email and userId lists outstanding requests across the whole organization.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| query | string | optional | Filter to one member's requests. Either email or userId, not both — supplying both returns 400. An unknown user returns 404, and a user outside your organization returns 403. | |
| userId | query | string | optional | Filter to one member's requests by DeskChime user id. Stable across email changes. Same either/or rule as email. |
| status | query | string | optional | pending | answered | expired. Any other value returns 400. Omit to return all three. |
| month | query | string | optional | YYYY-MM. Filters on when the request was raised, not when it's due. Resolved in the member's own timezone when you filter by user, otherwise the platform default. Malformed values return 400. |
| page | query | number | optional | Page number (default: 1) |
| limit | query | number | optional | Results per page, max 50 (default: 20) |
curl
curl "https://deskchime.com/api/v1/feedback/requests?email=jane%40acme.com&status=pending&month=2025-04&page=1&limit=20" \ -H "x-api-key: YOUR_API_KEY"
Example response
{
"data": [
{
"id": "ra1",
"cycleTitle": "Q1 Peer Review",
"cycleDescription": "Quarterly peer feedback for engineering",
"subjectUserId": "u2",
"subjectName": "Bob Lee",
"subjectEmail": "[email protected]",
"requestedByUserId": "u1",
"requestedByName": "Jane Smith",
"requestedAt": "2025-01-10T09:00:00Z",
"dueAt": "2025-01-24T23:59:59Z",
"status": "pending",
"respondedAt": null,
"url": "https://app.deskchime.com/acme/feedback/id/ra1"
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 14,
"totalPages": 1,
"hasMore": false,
"excludedAnonymous": 3
}
}/api/v1/goalsPaginated list of goals with progress and assignees. Filter by status or type. Archived goals are excluded. email and userId filter to goals where the named user is an assignee — either one, not both; supplying both returns 400, an unknown user returns 404, and a user outside your organization returns 403. month filters on the goal's end date (Goals.end_date), not on when it was assigned, and end_date is nullable, so a goal with no end date never matches a month filter. Omitting email, userId, and month lists goals across the whole organization.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| page | query | number | optional | Page number |
| limit | query | number | optional | Max 50 |
| status | query | string | optional | OnTrack | Completed | Delayed | AtRisk | Abandoned. Any other value returns 400. |
| type | query | string | optional | Organization | Individual | Team | Self. Any other value returns 400. |
| query | string | optional | Filter to goals where this member is an assignee. Either email or userId, not both — supplying both returns 400. An unknown user returns 404, and a user outside your organization returns 403. | |
| userId | query | string | optional | Filter to goals where this member is an assignee, by DeskChime user id. Stable across email changes. Same either/or rule as email. |
| month | query | string | optional | YYYY-MM. Filters on the goal's end date, not on when it was assigned — end_date is nullable, so a goal with no end date never matches. Resolved in the filtered member's own timezone when you filter by email or userId, otherwise the platform default. Malformed values return 400. |
curl
curl "https://deskchime.com/api/v1/goals?page=1&limit=20&status=OnTrack&type=Individual&email=jane%40acme.com&month=2025-04" \ -H "x-api-key: YOUR_API_KEY"
Example response
{
"data": [
{
"id": "g1",
"title": "Grow ARR by 30%",
"type": "Organization",
"status": "OnTrack",
"progress": 45,
"assignees": [
{
"name": "Jane",
"email": "[email protected]"
}
]
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 8,
"totalPages": 1,
"hasMore": false
}
}/api/v1/goals/:idSingle goal with full timeline of progress updates and actionable items.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string | required | Goal ID |
curl
curl "https://deskchime.com/api/v1/goals/g1" \ -H "x-api-key: YOUR_API_KEY"
Example response
{
"data": {
"id": "g1",
"title": "Grow ARR by 30%",
"status": "OnTrack",
"progress": 45,
"timeline": [
{
"status": "OnTrack",
"comment": "Closed 3 new accounts",
"date": "2025-03-10T09:00:00Z"
}
],
"actionItems": [
{
"id": "a1",
"title": "Close enterprise deal",
"status": "OnTrack"
}
]
}
}/api/v1/meetingsPaginated list of meetings. Filter by type or date range. Cancelled meetings are excluded.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| page | query | number | optional | Page number |
| limit | query | number | optional | Max 50 |
| type | query | string | optional | Goal | Review | Casual | ONE_ON_ONE | Booking. Any other value returns 400. |
| from | query | string | optional | Accepts YYYY-MM-DD (resolved in the platform default timezone — this endpoint has no per-user filter), YYYY-MM-DDTHH:mm[:ss[.sss]] (same, read as wall-clock), or either with a trailing Z or ±HH:MM/±HHMM offset (honoured exactly as given). Loosely-formatted values like 2026-8-1 or 2026/08/01 return 400 rather than being guessed at. |
| to | query | string | optional | Same accepted forms as from. A bare date is the upper bound — it covers the whole day through 23:59:59.999 rather than stopping at midnight. Loosely-formatted values like 2026-8-1 or 2026/08/01 return 400. |
curl
curl "https://deskchime.com/api/v1/meetings?page=1&limit=20&type=Review&from=2025-01-01&to=2025-03-31" \ -H "x-api-key: YOUR_API_KEY"
Example response
{
"data": [
{
"id": "m1",
"title": "Sprint Retro",
"type": "Casual",
"scheduledAt": "2025-03-15T14:00:00Z",
"isCompleted": true,
"attendeeCount": 6
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 47
}
}/api/v1/one-on-onesPaginated list of one-on-one meetings with organizer, participant, and full participants[] details. Cancelled sessions are excluded by default — set includeCancelled=true to include them, returned with status: "cancelled". participants[] always contains exactly two entries, since a DeskChime 1-on-1 is always two people; role is "owner" (whoever booked the session) or "attendee". isCurrentMember is false when that person has since left or been removed from the workspace — their past sessions are still returned deliberately, because the meeting genuinely happened, so you can tell "this person left" apart from "I could not match this person". status is exactly "completed" | "scheduled" | "cancelled" — there is no no-show state. completedAt was only introduced in May 2026 and is null for most sessions completed before then; use status to tell held from booked, and scheduledAt to attribute a session to a month — do not rely on completedAt for historical data. title has the participant's name substituted into the stored template ($name), relative to whichever member you filtered by via email or userId — with no user filter it falls back to the organizer's own perspective. titleTemplate carries the raw stored string with the $name placeholder intact.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| page | query | number | optional | Page number |
| limit | query | number | optional | Max 50 |
| from | query | string | optional | Accepts YYYY-MM-DD (resolved in the member's own timezone, or the platform default when no user filter is supplied), YYYY-MM-DDTHH:mm[:ss[.sss]] (same, read as wall-clock), or either with a trailing Z or ±HH:MM/±HHMM offset (honoured exactly as given). Loosely-formatted values like 2026-8-1 or 2026/08/01 return 400 rather than being guessed at. |
| to | query | string | optional | Same accepted forms as from. A bare date is the upper bound — it covers the whole day through 23:59:59.999 rather than stopping at midnight, not just its first instant. Loosely-formatted values like 2026-8-1 or 2026/08/01 return 400. |
| heldFrom | query | string | optional | Filters on when the session was completed, not booked — combinable with month/from/to, and a session that was never completed can never match. Accepts YYYY-MM-DD (resolved in the member's own timezone, or the platform default with no user filter), YYYY-MM-DDTHH:mm[:ss[.sss]], or either with a trailing Z or ±HH:MM/±HHMM offset. Loosely-formatted values like 2026-8-1 or 2026/08/01 return 400. |
| heldTo | query | string | optional | Same accepted forms as heldFrom, as the upper bound — a bare date covers the whole day through 23:59:59.999 rather than stopping at midnight. Combinable with month/from/to; a session that was never completed can never match. |
| status | query | string | optional | scheduled | completed | cancelled. Any other value returns 400. status=cancelled returns cancelled sessions directly — you don't additionally need includeCancelled=true. |
| query | string | optional | Filter to one member's sessions. Either email or userId, not both — supplying both returns 400. An unknown user returns 404. | |
| userId | query | string | optional | Filter to one member's sessions by DeskChime user id. Stable across email changes. |
| month | query | string | optional | YYYY-MM. Resolved in the member's own timezone. Takes precedence over from/to when both are supplied. Malformed values return 400. |
| includeCancelled | query | string | optional | Set to true to include cancelled sessions, which are otherwise omitted. |
curl
curl "https://deskchime.com/api/v1/one-on-ones?page=1&limit=20&from=2025-01-01&to=2025-03-31&heldFrom=2025-01-01&heldTo=2025-03-31&status=completed&month=2025-04&includeCancelled=true" \ -H "x-api-key: YOUR_API_KEY"
Example response
{
"data": [
{
"id": "613d3206-a5c4-4bcd-bb1f-a05e94968212",
"title": "1-on-1 with Aaditya verma",
"titleTemplate": "1-on-1 with $name",
"frequency": "Monthly",
"scheduledAt": "2024-11-05T10:30:00Z",
"endsAt": "2024-11-05T11:00:00Z",
"completedAt": null,
"status": "completed",
"isCompleted": true,
"createdAt": "2024-07-03T04:03:07Z",
"organizer": {
"id": "u1",
"name": "Anil sharma",
"email": "[email protected]"
},
"participant": {
"id": "u2",
"name": "Aaditya verma",
"email": "[email protected]"
},
"participants": [
{
"id": "u1",
"name": "Anil sharma",
"email": "[email protected]",
"role": "owner",
"isCurrentMember": true
},
{
"id": "u2",
"name": "Aaditya verma",
"email": "[email protected]",
"role": "attendee",
"isCurrentMember": false
}
]
}
],
"meta": {
"page": 1,
"limit": 20,
"total": 18
}
}/api/v1/users/activityActivity counts and responsiveness rates for a team member. Rates are whole percentages, or null when there is nothing to measure. feedback.received counts individual feedback requests, so each cycle of a recurring form counts once. applaudes.systemGenerated counts applauds received that were generated automatically by the system rather than sent by a colleague — it is a subset of applaudes.received, not a separate bucket; applaudes.received minus applaudes.systemGenerated is the colleague-sent count. meetings.assigned counts meetings that actually took place; a member counts as attending unless they explicitly declined. oneOnOnes.total/completed and meetings.assigned/attended are evaluated as of asOf (a top-level ISO instant in the response), not over the whole month — they grow if you call again later in the same month, because a 1-on-1 scheduled for later this month is not yet a missed one. scheduledInMonth, on both stats.oneOnOnes and stats.meetings, is the same count without that as-of clamp, and it's the figure that reconciles with GET /api/v1/one-on-ones for a whole month. The relationship isn't the same on both: for oneOnOnes, scheduledInMonth differs from total only by the asOf clamp; for meetings, assigned/attended additionally require the meeting to have concluded, so scheduledInMonth differs from them by the clamp and that completion requirement together — don't assume one relationship explains the other. An unrecognised user returns 404, and a user outside your organization returns 403 — so a zero-filled 200 always means a genuine month of no activity. Month boundaries resolve in the member's own timezone.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| body | string | optional | User email address. Either email or userId, not both — supplying both, or neither, returns 400. | |
| userId | body | string | optional | DeskChime user id. Either email or userId, not both — supplying both, or neither, returns 400. Stable across email changes. |
| month | body | string | optional | Restrict to one calendar month, YYYY-MM. Month boundaries follow the member's own timezone. Omit for all-time. |
curl
curl -X POST "https://deskchime.com/api/v1/users/activity" \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","userId":"","month":"2025-03"}'Example response
{
"user": {
"id": "u1",
"name": "Jane",
"email": "[email protected]"
},
"organization": {
"id": 1
},
"period": "2025-03",
"asOf": "2025-03-14T09:12:44Z",
"stats": {
"feedback": {
"given": 3,
"received": 10,
"answered": 8
},
"goals": {
"total": 5,
"completed": 3
},
"meetings": {
"created": 4,
"assigned": 12,
"attended": 11,
"scheduledInMonth": 15
},
"applaudes": {
"given": 6,
"received": 4,
"systemGenerated": 2
},
"oneOnOnes": {
"total": 8,
"completed": 7,
"scheduledInMonth": 9
}
},
"responsiveness": {
"feedbackResponseRate": 80,
"goalCompletionRate": 60,
"meetingAttendanceRate": 92,
"oneOnOneCompletionRate": 88
}
}/api/v1/organizations/:id/activityReturns the same per-user activity payload as POST /api/v1/users/activity, but for every member of the organization in one paginated call — a nightly sync can make one or two requests instead of one per employee. Each element of data[] is identical in shape to the single-user response, so existing parsing code can be reused in a loop, except asOf is carried per element rather than once at the top level: users on a page are computed one at a time, so each one's asOf is captured at a slightly different instant, and a single top-level asOf would overstate that precision. applaudes.systemGenerated counts applauds received that were generated automatically by the system rather than sent by a colleague — it is a subset of applaudes.received, not a separate bucket; applaudes.received minus applaudes.systemGenerated is the colleague-sent count. oneOnOnes.total/completed and meetings.assigned/attended are evaluated as of that element's own asOf, not over the whole month — they grow on a later call in the same month, because a 1-on-1 scheduled for later this month is not yet a missed one. scheduledInMonth, on both stats.oneOnOnes and stats.meetings, is the same count without that as-of clamp, and it's the figure that reconciles with GET /api/v1/one-on-ones for a whole month. The relationship isn't the same on both: for oneOnOnes, scheduledInMonth differs from total only by the asOf clamp; for meetings, assigned/attended additionally require the meeting to have concluded, so scheduledInMonth differs from them by the clamp and that completion requirement together — don't assume one relationship explains the other. :id must match the organization your API key belongs to — any other id returns 403.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | string | required | Your organization id. Must match the organization your API key belongs to, or the request returns 403. |
| month | query | string | optional | YYYY-MM. Omit for all-time figures. Each member's month is resolved in their own timezone. |
| page | query | number | optional | Page number (default: 1) |
| limit | query | number | optional | Results per page, max 25 (default: 25) |
curl
curl "https://deskchime.com/api/v1/organizations/3/activity?month=2025-04&page=1&limit=25" \ -H "x-api-key: YOUR_API_KEY"
Example response
{
"data": [
{
"user": {
"id": "u1",
"name": "Jane",
"email": "[email protected]"
},
"asOf": "2025-04-10T06:45:00Z",
"stats": {
"feedback": {
"given": 4,
"received": 12,
"answered": 9
},
"goals": {
"total": 6,
"completed": 4
},
"meetings": {
"created": 5,
"assigned": 0,
"attended": 0,
"scheduledInMonth": 3
},
"applaudes": {
"given": 7,
"received": 5,
"systemGenerated": 2
},
"oneOnOnes": {
"total": 9,
"completed": 8,
"scheduledInMonth": 11
}
},
"responsiveness": {
"feedbackResponseRate": 75,
"goalCompletionRate": 67,
"meetingAttendanceRate": null,
"oneOnOneCompletionRate": 89
}
}
],
"meta": {
"total": 30,
"period": "2025-04",
"page": 1,
"limit": 25,
"totalPages": 2,
"hasMore": true
}
}