REST API
Every public /api/v1 route with its method, scope, parameters, body, response and errors
Base URL: https://app.makesmores.com/api/v1. Send Authorization: Bearer <key> on every route except GET /models and the device sign-in routes. Bodies are JSON with Content-Type: application/json; unknown fields, duplicate keys and null values are refused with 400 invalid_request. Answers are never cached, except GET /models, which is cached for 60 seconds.
Every error is {code, message} and some add fields. See Errors. The billing column says how a route charges: free, 1 credit (api.call), the model's rate, or runs from your plan.
Models and credits
| Method and route | Auth | Billing | Does |
|---|---|---|---|
GET /models | None | Free | Every listed model and rate with price, scope, limits and status. See GET /api/v1/models |
GET /credits | Any key | Free | free, paid, available, available_for_scans, running_credits, personal, allowance, resets_at, credits_enforced, topup_url, and key with this key's id, month_credits, monthly_credit_cap and cap_remaining. See Credits |
Drafts
All writers share one resource. See Reddit writers, prose-1 and X writers.
| Method and route | Scope | Billing | Does |
|---|---|---|---|
POST /drafts | reddit:posts:write | Writer rate per token | Submits a draft. Body: platform, type, idempotency_key, optional model and count, then the platform's fields. Answers {schema_version, draft_id, platform, type, state, poll_after_s, ai_policy?, credits_deducted} |
GET /drafts/{id} | reddit:posts:read | Free | Reads a draft: state, options, choice, fact_check, notes, the platform's block and notice |
POST /drafts/{id}/choice | reddit:posts:write | Free | Records {"option": "A"} on a ready draft and reveals every option's model |
| Platform and type | Fields | Models |
|---|---|---|
reddit / post | subreddit, plan, confirm_rules_allow_ai | ember-v1, ember-14k, ember-28k |
reddit / reply | Coming soon: answers 400 draft_type_coming_soon | ember-reply-v1 |
email / outreach, follow_up, reply | to, from, goal, facts, thread, length_words | prose-1 |
newsletter, blog / post | topic, facts, audience, outline, title, length_words | prose-1 |
newsletter, blog / rewrite | source_text, instructions, keep_links | prose-1 |
x / post | topic, facts, audience | x-writer-v1 |
x / reply | thread, goal, facts | x-reply-v1 |
Errors: 400 invalid_request, draft_type_coming_soon, model_coming_soon; 404 draft_not_found; 409 idempotency_conflict, ai_text_banned, ai_policy_unconfirmed, text_posts_not_allowed, choice_conflict, drafts_off; 410 model_closed; 422 platform_unsupported, draft_type_unsupported, model_unsupported, subreddit_invalid, plan_invalid, email_invalid, content_invalid, choice_invalid; 429 drafts_queue_full, rate_limited; 402 credits_required.
Scoring
| Method and route | Scope | Billing | Does |
|---|---|---|---|
POST /viral-score | viral:score | Per title (reddit-pooled-v1) or per post (x-viral-v1) | network: "reddit" with subreddit, titles (1 to 3), body, post_type, flair, account; or network: "x" (or none) with post and audience. See Viral Score |
Errors: 400 invalid_request; 409 reddit_signals_off; 422 invalid_subreddit, subreddit_unavailable; 429 rate_limited; 503 scoring_busy, scoring_unavailable; 402 credits_required.
Reddit data
| Method and route | Scope | Billing | Does |
|---|---|---|---|
GET /top-posts?subreddit=&platform= | reddit:signals:read | 1 credit | What the subreddit's top 10% looks like. See Reddit top posts |
GET /mentions | reddit:signals:read | 1 credit | Without tracker, the trackers and limits. With tracker, the report: bucket, from, to, timezone, term, series_fields, include, compare, compare_from, compare_to, metric, limit, series_cursor, examples_cursor. Sends an ETag; If-None-Match answers 304 |
PUT /mentions | reddit:signals:write | 1 credit | Starts or changes a tracker: name, subreddit, terms, history_from, timezone. Owners and admins |
DELETE /mentions?tracker= | reddit:signals:write | 1 credit | Stops a tracker: {tracker, stopped} |
GET /pain-points?subreddit= | reddit:signals:read | 1 credit | Pain point groups for the watched subreddits |
GET /solution-requests?subreddit=&feature_requests= | reddit:signals:read | 1 credit | Solution request groups |
GET /signals?subreddit= | reddit:signals:read | 1 credit | Watched subreddits and X topics; with subreddit, its full picture |
GET /content-briefs?subreddit=&limit= | reddit:signals:read | 1 credit | This week's briefs for one watched subreddit (beta) |
GET /leads?kind=&channel=&subreddit=&topic=&group=&limit=&cursor= | reddit:signals:read | 1 credit | Found and replied leads. With agent_id, an agent's leads instead (below) |
PATCH /leads/{key} | reddit:signals:write | 1 credit | {"state": "handled"}: new, replied, dismissed, not_relevant or handled |
GET /watching | reddit:signals:read | 1 credit | The watched subreddits and X topics, and the profile |
PUT /watching | reddit:signals:write | 1 credit | Replaces the lists you send: subreddits, x_topics, digest, profile with revision. Owners and admins |
GET /opportunities?limit=&cursor= | reddit:signals:read | 1 credit | Leads, then on the first page pain points, solution requests and content briefs |
GET /profile | reddit:signals:read | 1 credit | The confirmed product profile |
POST /profile/proposal | reddit:signals:write | profile.proposal | {"website": "..."}: reads up to 40 pages and proposes a profile |
GET /profile/proposal/{id} | reddit:signals:read | Free | The proposal |
Errors: 400 invalid_request; 402 paid_required; 403 insufficient_scope, admin_required; 404 tracker_not_found, subreddit_not_found; 409 reddit_signals_off, revision_conflict, tracker_conflict, tracker_limit_reached, subreddit_not_ready, lead_gone; 422 validation codes named on each product page; 429 rate_limited; 503 reddit_signals_unavailable, reddit_mentions_disabled.
Repository scans
Open workspace by workspace; elsewhere every route answers 404 scans_off. See Repository scans.
| Method and route | Scope | Billing | Does |
|---|---|---|---|
POST /scans | scans:write | firewatch-1 per token, from purchased or granted credits | repo_url, idempotency_key and max_credits (1,000 to 2,000,000) required; ref, github_token and model optional. Answers 202 {id, status, credits_deducted, poll_after_s} with a Location header |
GET /scans?cursor= | scans:read | Free | {scans, next_cursor}: the workspace's scans, newest first, 50 a page |
GET /scans/{id} | scans:read | Free | The scan: status, stage, progress, max_credits, credits_deducted, credits_used, error_code, heartbeat_at, report_ready, the times, and at the end summary |
GET /scans/{id}/report | scans:read | Free | The report as an HTML attachment, once report_ready is true |
POST /scans/{id}/cancel | scans:write | Free; the scan pays for tokens used so far | Cancels and answers the scan. A queued scan is refunded in full |
Errors: 400 invalid_repo_url, invalid_ref, invalid_request; 402 credits_required; 403 insufficient_scope; 404 scans_off, scan_not_found; 409 idempotency_conflict, too_many_scans, report_not_ready, model_unavailable; 410 model_closed; 503 github_token_unavailable, scans_unavailable.
Agents and runs
Billed in runs from your plan; never credits. See Lead agents and Company research.
| Method and route | Scope | Does |
|---|---|---|
GET /agents | agents:read | Lists agents. Company agents also need prospecting:read |
POST /agents | agents:write | Creates an agent: name, brief (who, signals, never, goal), voice, job, platform; or a company agent with job: "find_prospects", approved, researchBrief (also prospecting:write) |
PATCH /agents/{id} | agents:write | Updates an agent |
POST /agents/{id}/runs | runs:start | Starts a run: {"idempotency_key": "..."} (required for company runs, which also need prospecting:start) |
GET /runs/{id} | runs:read | Reads a run |
POST /runs/{id}/cancel | runs:cancel | Cancels a run |
GET /leads?agent_id=&limit=&cursor= | leads:read | An agent's leads, 1 to 100 a page |
GET /runs/{id}/prospects?limit=&after=&qualification= | prospecting:read | A company run's companies |
GET /runs/{id}/policy, PUT /runs/{id}/policy | prospecting:read, prospecting:policy:write | Reads or retunes a company run's policy |
GET /research/templates | research:read | Research plan templates |
POST /research/proposals | research:write | Proposes a research plan |
POST /research/sources/discover | research:write | Finds candidate subreddits |
GET /agents/{id}/research-plan, POST /agents/{id}/research-plan | research:read, research:write | Reads or saves a plan version |
POST /agents/{id}/research-plan/approve | research:approve | Approves one exact version |
GET /runs/{id}/research-results, /research-evidence, /research-files | research:read | Results, evidence and files |
GET /research/files/{id} | research:read | Downloads a PDF |
Errors: 402 no_runs_remaining, plan_limit, agent_limit; 403 insufficient_scope, pilot_disabled; 409 run_conflict, agent_conflict, policy_conflict, plan_conflict, idempotency_conflict; 429 rate_limited.
Sign-in and MCP
| Method and route | Auth | Does |
|---|---|---|
POST /integrations/device/code | None | Starts a device sign-in: client_label, scopes. See CLI |
POST /integrations/device/token | None | Exchanges an approved device_code for tokens |
POST /integrations/token/refresh | None | Exchanges a refresh_token for a new pair |
GET, POST, DELETE /mcp | Bearer | The MCP server. See MCP |
Keys are created, capped and revoked in the console.
Coming soon
| Method and route | Scope | Product |
|---|---|---|
POST /drafts with platform: "reddit", type: "reply" | reddit:posts:write | Reddit reply writer |
POST /decisions | decisions:run | Decisions |
POST /web/search, POST /web/pages | web:read | Web search |