
Overview
The API is the pull-based half of Disco’s developer toolkit. Use it to sync Members from a CRM, provision access from a sign-up flow, automate Admin and Manager assignments, or pull basic engagement data without working inside the Admin Area by hand. The API is available on the Enterprise plan only, and only Academy Owners and Admins can create or manage keys. Full endpoint reference and request and response schemas are published as OpenAPI documentation at https://api.production.services.disco.co/v1/docs.Create an API Key
API keys are created and managed in the Admin Area.- Go to Admin Area → Settings → API.
- Click + API Key.
- Enter a Name. Names must be unique within your Academy.
- Optionally set an Expiration Date. Leave it blank if the key should not expire.
- Click Save.
Authenticate API Requests
All requests are made against the base URL: https://api.production.services.disco.co/v1 Authenticate every request by passing the key in the X-Disco-API-Key header. Disco does not accept Authorization or Bearer tokens.Use the API
The API supports the Member and content operations most teams need to automate:- Add or remove Members in your Academy or Programs
- Create magic login links for Members
- Add or remove Admins or Managers in your Academy or Programs
- Invite Members to your Academy or Programs
- List Programs and the Members in those Programs
- List Member Groups and the Members in those Groups
- Create and remove Member Groups and subgroups
- Manage Member Group membership
- Pull basic engagement data for Members
- Add Program, curriculum module, and curriculum item completions for existing Members, including a backfill mode for historical records
- Review assignment submissions as passed or failed, with an optional review comment
filter object in the request body. Programs and Pathways can be filtered by name and slug, Member Groups by name, and Members by fullName. Each filter value must be at least one character and is matched as a case-insensitive substring against the field.
For request and response schemas, see the OpenAPI docs at https://api.production.services.disco.co/v1/docs.
Endpoints that list the Members of a Program (for example,
product.listUsers) return only Members whose Program membership is currently enrolled. Members who were previously added to the Program but have since been unenrolled are excluded from the response, even if their underlying Academy membership still exists.Create and Remove Member Groups
Use the Group endpoints to manage Member Groups and subgroups without working in the Admin Area:group.createcreates a Member Group or subgroup.group.removepermanently removes a custom Member Group or subgroup.
group.create accepts:
name— optional. Must be 25 characters or less.product_id— optional. Creates the Group inside a Program. Omit it to create an Academy-level Group. Groups can only be created for course Programs.parent_group_id— optional. Creates a subgroup under the given parent Group. The parent must be a custom or default Group. When the parent Group belongs to a Program, you must also pass theproduct_idof that same Program. When creating a Program Group, omit this field to place the Group under the Program’s default Group.color— optional. Hex color for the Group, 3 or 6 digits. Use 4 or 8 digits to include an alpha channel, for example#FFF5D680. Defaults to#FFF5D6.description— optional. Must be 280 characters or less.visibility— optional.everyoneoradmin_only. Defaults toeveryone. Cannot be set on subgroups.
group with its id, name, product_id, parent_group_id, is_default_group, and visibility. Requests that fail validation return HTTP 400 with the code invalid_input and per-field field_errors. A product_id or parent_group_id that does not exist in your Academy returns HTTP 404.
group.remove accepts a single group_id. Removing a parent Group also permanently removes all of its subgroups and their memberships. Only custom Groups can be removed:
- Removing a default or platform-maintained Group (such as Program member or role Groups) returns HTTP 400 with the code
not_custom_group. - Removing a Group that is still used by Events, Channels, or other Academy features returns HTTP 400 with the code
group_in_use.
Complete Programs and Curriculum Modules
Use the completion endpoints to mark a Program, curriculum module, or curriculum item as complete for an existing member:product.completecompletes a Program. Optionally setcomplete_all_childrentotrueto complete every curriculum item and module first.product.completeCurriculumModulecompletes a curriculum module identified by the module’sinstance_idfromproduct.getCurriculum. Optionally setcomplete_all_childrentotrueto complete its items first. Completing the final required module also completes the Program.product.completeCurriculumItemcompletes one curriculum item identified by the item’sinstance_idfromproduct.getCurriculum. Completing the final required item also completes the module.
standard— completions run through the normal Disco workflows, so Members receive notifications, certificates are issued, automations fire, and webhook and Zapier events are emitted.backfill— completions are persisted without notifications, certificates, automations, webhooks, or Zapier events. Program backfills still update pathway progression. Use this mode when importing historical completion data.
user_id (the Member’s Academy membership ID) and a product_id (the Program ID); module and item entries also require instance_id.
Responses return one result per input, in request order:
- Success:
success: true, pluscreated(trueif the request created the completion,falseif the Member was already complete) andcompleted_at(the original completion time — existing completions are not overwritten). - Failure:
success: false, plus afailure_codeandfailure_reason.not_foundcovers missing, inaccessible, or ineligible records.internal_erroris returned for unexpected failures on that single record while the rest of the batch continues to process.
created: false the second time and does not duplicate the record. Retrying an existing Program completion with complete_all_children: true still fills any missing child completions.
Review Assignment Submissions
Thecontent.reviewAssignment endpoint marks an assignment submission as passed or failed. Use it when work is evaluated outside Disco — in a grading tool, a rubric app, or a human review queue — and the decision needs to flow back into the Program.
The assignment must have Require Pass to Progress enabled before its submissions can be reviewed. Submissions on any other assignment are rejected with the code grading_not_enabled.
Each request accepts:
assignment_submission_id— the submission being reviewed.status—passorfail.reviewer_user_id— the Academy membership ID of the Admin the review comes from. They must be an active Member of your Academy with permission to mark assignments in the Program, so every review is attributed to a real person rather than to the API key.review_comment_markdown— optional. Posts a comment to the submission’s comment thread as the reviewer. Standard Markdown constructs — headings, lists, emphasis, links, quotes, and code — are converted to Disco’s editor format. Posting a comment also requires the reviewer to be a member of the Program, so an Academy Admin who is not in the Program can review a submission but cannot comment on it. The maximum comment length is documented in the OpenAPI spec.
status, plus review_comment_id when a comment was posted.
Reviews made through the API behave the same as reviews made in the app: the Member is notified of the outcome, and passing the submission records the completion that unblocks their progress. When several Members submitted the assignment together, passing it completes the assignment for all of them.
Reviewing the same submission again replaces the previous review. Marking a previously passed submission as failed updates the status but does not revoke the completion that was already recorded, matching what happens in the app.
Delete an API Key
Deleting a key is immediate and cannot be undone.- Go to Admin Area → Settings → API.
- Locate the key in the API Keys table.
- Open the Action menu and click Delete.
Rate Limits
Rate limits are applied per endpoint and per Academy. A request that exceeds the limit returns HTTP 429 with the message Rate Limited. Per-endpoint limits and the maximum number of IDs accepted by bulk endpoints are documented in the OpenAPI spec at https://api.production.services.disco.co/v1/docs. Request bodies are also capped in size. A request whose body exceeds the cap returns HTTP 413 with the codepayload_too_large, before any field-level validation runs. The cap and any per-field length limits are documented in the same OpenAPI spec.
Input Validation
Fields that accept Disco entity IDs (for examplegroup_id, pathway_id, invite_id, webhook_endpoint_id, the ids and pathway_ids arrays, the group_membership_ids and webhook_request_ids arrays, and profile_fields[].id) must be passed as positive integer strings. Values that are not numeric, or that are larger than a Postgres bigint, are rejected before the request reaches the handler.
A request that fails ID validation returns HTTP 400 with a structured error body:
field is the dotted path to the entry — for example ids.0 or profile_fields.0. Previously these requests could return HTTP 500; they now consistently return HTTP 400 so clients can surface the error to the caller.
FAQ
Do I need to ask Disco to enable the API?
Do I need to ask Disco to enable the API?
No. If your Academy is on the Enterprise plan, the API settings page is already available in the Admin Area. Non-Enterprise plans do not see the page.
Can I use the API on a non-Enterprise plan?
Can I use the API on a non-Enterprise plan?
No. The API is an Enterprise-only feature. If you need API access, talk to your Disco contact about upgrading.
I keep getting an authentication error. What am I doing wrong?
I keep getting an authentication error. What am I doing wrong?
The most common cause is sending the key in the wrong header. Disco expects X-Disco-API-Key. Clients that default to Authorization: Bearer <token> are rejected. Double-check the header name and confirm you copied the full key value.
Why do list and read endpoints use POST instead of GET?
Why do list and read endpoints use POST instead of GET?
Most endpoints use POST so they can support pagination. Community.get is the only GET endpoint. Treat POST as the default when reading data.
Where do I find the Program ID I need for an API call?
Where do I find the Program ID I need for an API call?
Open the Program in the Admin Area and go to Settings. The ID is shown there, and you can also grab it from the Admin URL when editing the Program. Use this value in any request that accepts a product_id field.
Where do I find the assignment submission ID for a review?
Where do I find the assignment submission ID for a review?
The
content.user_submitted_assignment webhook event carries it as assignment_submission.id, which makes subscribing to that event the usual way to drive reviews: receive the submission, evaluate it in your own system, then send the result back with content.reviewAssignment. The same ID also appears in the submission’s URL when you open it in the app.Can I pull user activity like logins through the API?
Can I pull user activity like logins through the API?
The engagement.list endpoint returns engagement metrics per Member per day, filterable by user IDs and date range up to 120 days. It is the closest thing to a general activity feed. Explicit login events are not exposed.
What happens if a key expires?
What happens if a key expires?
The key stops working on the expiration date. Any integration using it will start receiving authentication errors until you issue and install a new key.