Course and coupon data without rebuilding the infrastructure.
This reference covers authentication, quotas, filters, coupon availability, trends, and the Comidoc MCP surface.
- REST base URL
- https://comidoc.com/api/v1
- MCP endpoint
- https://comidoc.com/mcp
- Date and time format
- ISO 8601 with an explicit offset
Getting started
A verified email address is required to generate a key. The complete key is displayed only once, and Comidoc stores only its cryptographic digest. Send it as a Bearer token.
curl 'https://comidoc.com/api/v1/courses?q=python&rating_min=4.5&has_active_coupon=true' \
-H 'Authorization: Bearer cmd_live_your_key'Free: 250 requests/month. Pro: 100,000 requests/month, 10 requests/second, and up to 100 results/page. Responses include RateLimit-*, X-RateLimit-*, and X-Request-Id headers.
Prefer learning by example? The tutorial Build a Udemy Coupon Discord Bot in 5 Minutes goes from zero to a running integration in forty lines of Node.js on the free plan.
Coupon availability contract
Redemption capacity is public on every plan. redemptions.total is the initial capacity reported by Udemy, remaining is the capacity available at the latest successful observation, and redeemed is calculated when both values are known.
{
"data": [{
"coupon_code": "KEEPLEARNING",
"redemptions": {
"total": 100,
"remaining": 80,
"redeemed": 20,
"state": "known",
"observed_at": "2026-07-18T14:20:00.000Z"
},
"expires_at": "2026-07-21T23:59:59.000Z",
"created_at": "2026-07-17T09:05:00.000Z",
"last_verified_at": "2026-07-18T14:20:00.000Z",
"last_confirmed_active_at": "2026-07-18T14:20:00.000Z"
}],
"pagination": {
"total": 1,
"limit": 25,
"next_cursor": null
},
"meta": {
"request_id": "req_…",
"source": "direct",
"plan": "pro",
"coupon_codes_included": true,
"quota": {
"limit": 100000,
"used": 42,
"remaining": 99958,
"resets_at": "2026-08-01T00:00:00.000Z"
}
}
}created_at records when Comidoc first tracked the coupon. last_verified_at is the latest verification attempt, even if it failed, while last_confirmed_active_at is the latest successful active check. redemptions.observed_at timestamps the returned capacity values.
States: known for a fresh measurement, unknown when Udemy does not provide capacity, stale for an old measurement or inactive offer, and exhausted when no redemptions remain. On Free, coupon_code is null and meta.coupon_codes_included is false. Pro returns the coupon code, sets that metadata flag to true, and includes the complete Udemy URL.
Course filters
REST and MCP expose the same discovery surface as the website coupon-filter overlay. REST list values are comma-separated; MCP accepts one value or an array. In every public contract, course_id and a course object's id are Udemy's numeric course ID. Comidoc's internal identifier is not exposed.
Swipe horizontally to view every column.
| Parameter | Value | Effect |
|---|---|---|
| q | Text | Course title, description, or instructor |
| topic | Slug | Comidoc topic |
| course_id | Positive integer | Udemy course ID (not Comidoc's internal ID) |
| category / language / level | Comma-separated | Canonical values; matching ignores case and multiple values use OR |
| course_type | courses | tests | Include courses, practice tests, or both |
| duration | short | medium | long | Under 1 hour, 1–10 hours, or over 10 hours |
| rating | lt-4 | gte-4-lt-4_5 | gte-4_5 | Website rating bands, combinable with OR |
| rating_min / rating_max | 0–5 | Rating range |
| published_after | ISO 8601 | Udemy publication date |
| last_course_updated_after | ISO 8601 | Last course-content update reported by Udemy |
| coupon_status / status | Comma-separated | Active, recent expired, invalid, pending, or all |
| coupon_age | 24h | Coupon creation age, not course publication age |
| coupon_created_after | ISO 8601 | Custom coupon creation cutoff |
| has_active_coupon | Boolean | Requires a verified, unexpired offer with capacity |
| expires_before / expires_after | ISO 8601 | Offer expiry window |
| remaining_min | Integer | Minimum remaining redemptions |
| discount_type | free | percentage | One or more discount types |
| repeat_coupon_course | include | exclude | only | Uses the same recent frequent-coupon rule as the website |
| regular_issuer | include | exclude | only | Instructors who publish coupons regularly |
| sort | Depends on endpoint | Includes rating, published date, duration, remaining uses, price, and trend |
| unique_course | Boolean (/offers) | At most one offer per course, like the website grid |
| horizon | 24h | 7d | 30d | Time window used by trending results |
curl 'https://comidoc.com/api/v1/offers?course_type=courses&category=Development,IT%20%26%20Software&language=English,French&duration=short,medium&rating=gte-4-lt-4_5,gte-4_5&coupon_age=24h&repeat_coupon_course=exclude&sort=remaining&unique_course=true' \
-H 'Authorization: Bearer cmd_live_your_key'last_course_updated_after always targets Udemy's course-content update date and never uses Comidoc's technical database timestamp.
Use /api/v1/filter-options or the MCP tool get_filter_options instead of hard-coding categories or languages. Values are matched case-insensitively and returned in their canonical form; an unknown category, language, or level returns a 400 error instead of an empty success. All Levels is an explicit level value and can be selected on its own. Course responses expose exact offer_count and active_offer_count values, plus returned_offer_count and offers_truncated when the embedded offer array is capped.
REST endpoints
/api/v1/filter-optionsDiscover current categories, languages, levels, and filter enums/api/v1/coursesSearch courses with quality and offer filters/api/v1/courses/{id}Fetch a course by Udemy ID or slug/api/v1/offersSearch current or historical coupon offers/api/v1/topicsBrowse and search the topic catalog/api/v1/topics/{slug}Fetch topic details/api/v1/topics/{slug}/coursesSearch courses associated with a topic/api/v1/trending/coursesFetch time-based course trends/api/v1/trending/topicsFetch time-based topic trends/api/v1/changesRead the incremental change feed from a timestampPagination and synchronization
Pass pagination.next_cursor unchanged in the next request’s cursor parameter. Do not decode or construct cursor values. For incremental replication, call /changes?since=…, follow the cursor until it is exhausted, and advance your watermark only after processing succeeds. Course changes with is_active: false or is_opted_out: true act as tombstones and should remove the course and its offers from replicas.
Errors and retries
REST errors use application/problem+json with code, title, detail, instance, and request_id. Retry 429 and 503 responses with exponential backoff and jitter. Do not automatically retry 400, 401, or 403 responses without correcting the request or identity.
Each problem type URL opens its cause and resolution. Browse the complete error catalog.
MCP for agents
Configure an HTTP MCP server at https://comidoc.com/mcp. Anonymous access is intentionally limited and never reveals raw coupon codes; active offers include an opaque, short-lived, single-use Comidoc URL. Add the same Bearer token used for REST to apply the account quota. A Pro plan unlocks coupon codes.
Only tools/call consumes the anonymous hourly or account monthly business quota. Discovery, tools/list, notifications, and legacy 2025 initialization and ping remain protected by a separate per-IP transport rate limit. Every tool result exposes the same request, plan, coupon-code, and quota metadata as REST so an agent can regulate its own request rate.
search_courses and find_offers accept the same categories, languages, levels, course types, durations, rating bands, coupon age, Udemy update cutoff, frequent-coupon mode, and identifiers as their REST counterparts. Useunique_course: true with find_offers to reproduce the website grid.
search_coursesSearch the historical catalog with multiple filtersfetch_courseFetch a course and its active offersfind_offersSearch coupon offers and redemption capacityget_filter_optionsDiscover current categories, languages, and canonical filter valueslist_topicsDiscover available topicsfetch_topicFetch a topicget_trending_coursesCourse trends over 24 hours, 7 days, or 30 daysget_trending_topicsTopic trends over 24 hours, 7 days, or 30 days{
"mcpServers": {
"comidoc": {
"url": "https://comidoc.com/mcp",
"headers": { "Authorization": "Bearer cmd_live_your_key" }
}
}
}Set up in your client
Claude Code
claude mcp add --transport http comidoc https://comidoc.com/mcpClaude Desktop and claude.ai
Settings, then Connectors, then Add custom connector. Name it comidoc and paste https://comidoc.com/mcp as the URL.
Cursor
Add to Cursor in one click or declare the server in .cursor/mcp.json with the JSON above.
VS Code
code --add-mcp '{"name":"comidoc","type":"http","url":"https://comidoc.com/mcp"}'Every client works without a key at the anonymous quota. Add the Authorization header shown above to apply your account quota and, on the Pro plan, receive raw coupon codes.
RapidAPI
The optional RapidAPI adapter serves the same /api/v1 contract when enabled. The identity and plan supplied by the proxy are verified with a server-side shared secret. Only the explicit pro, ultra, and mega subscription labels unlock Pro; unknown labels fail closed to Free. Proxy headers must never be sent directly by a public client. RapidAPI and direct usage remain separately observable in the administration portal.
Versions and stability
Breaking changes receive a new URL version. Fields may be added to v1, so clients must ignore unknown fields. Trending scores expose score_version so algorithm changes remain detectable. The MCP server pins TypeScript SDK 2.0.0, implements the stable stateless 2026-07-28 protocol, and retains a stateless fallback for 2025 clients.