Trenzhub for developers

Your agent. Your research workspace.

Explore demand, organize trends, and run research from any agent. One API key connects the REST API and remote MCP.

Start with agent.md

Sign in, create a key in API keys, and give agent.md to Codex, Claude Code, or your own agent. The file contains the complete workflow, endpoints, permissions, and MCP configuration.

Free trial. No payment or credit card required. 120 requests/minute and 10,000 requests/day per account. Website mining quotas also apply; check GET /usage. Daily limits reset at 00:00 UTC.
REST · first request
export TRENZHUB_API_KEY='YOUR_API_KEY'

curl --fail-with-body 'https://trenzhub.com/api/v1/me' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"

curl --fail-with-body 'https://trenzhub.com/api/v1/keywords/trend?keyword=AI%20agents&locale=en&market=us' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
Example response · GET /me
{
  "data": {
    "id": "your-user-id",
    "name": "Researcher",
    "email": "you@example.com",
    "role": "user",
    "image": null,
    "plan": "free_trial",
    "billingEnabled": false,
    "key": {
      "id": "your-key-id",
      "scopes": [
        "account:read",
        "trends:read"
      ],
      "expiresAt": 1801267200000
    }
  },
  "meta": {
    "requestId": "request-uuid",
    "apiVersion": "v1",
    "plan": "free_trial"
  }
}

Connect through MCP

Endpoint: https://trenzhub.com/mcp. Uses stateless Streamable HTTP with a Bearer API key on every request. There is no OAuth login flow. Tools, scopes, validation, ownership checks, and quotas match REST.

Codex · ~/.codex/config.toml
[mcp_servers.trenzhub]
url = "https://trenzhub.com/mcp"
bearer_token_env_var = "TRENZHUB_API_KEY"
Claude Code · private shell
claude mcp add --transport http trenzhub 'https://trenzhub.com/mcp' \
  --header "Authorization: Bearer ${TRENZHUB_API_KEY}"

Set the environment variable before starting your agent. Claude Code stores the resolved header in its local MCP configuration: protect that file and keep it out of version control. If your client cannot send HTTP headers, call REST directly.

Tools use the prefix trenzhub_, such as trenzhub_get_keyword_trend. Only tools allowed by your key appear in tools/list. Resources include agent.md and the OpenAPI reference. Export tools return filename, contentType, and content so your agent can save a file.

Research workflow · tool calls
trenzhub_list_markets({})
trenzhub_get_usage({})
trenzhub_create_mining_run({
  "seedKeyword": "AI agents, automation",
  "locale": "en", "market": "us", "keywordCount": 100
})
// Save the returned runId. Poll at most once every 5 seconds.
trenzhub_get_mining_progress({ "runId": "YOUR_RUN_ID" })
trenzhub_get_mining_run({ "runId": "YOUR_RUN_ID" })

Authentication & permissions

Send Authorization: Bearer YOUR_API_KEY. Keys are shown once, stored as hashes, and can expire or be revoked immediately. Up to 10 active keys per account. Rotate by creating a replacement, updating your agent, then revoking the old key.

ScopeAccess
account:readYour profile, current key, and usage.
account:writeUpdate your profile name and avatar.
account:securityPassword changes, session revocation, provider management, and account deletion. Optional; excluded from default keys.
trends:readRead and export trends data available to your account.
watchlist:readRead and export watchlist data available to your account.
watchlist:writeCreate and manage your watchlist data.
mining:readRead and export mining data available to your account.
mining:writeCreate and manage your mining data.
keys:manageList, create, and revoke your keys. Optional; excluded from default keys. Child keys cannot exceed the caller's scopes or expiry.

API/MCP traffic shares the account limits across all keys. Responses include X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (Unix seconds), X-DailyLimit-Remaining, and X-Request-Id. Mining jobs use the same daily quotas as the website.

Endpoint reference

Base URL: https://trenzhub.com/api/v1. JSON for POST/PATCH; query parameters for GET. IDs in braces belong in the URL. Parameters are strict: unknown fields return 400. Expand an endpoint for its parameters and a runnable example.

GET/meYour account

Read your profile, current key permissions, and free trial status.

Returns: Profile: id, name, email, role, image; plan='free_trial', billingEnabled=false; key: id, scopes, expiresAt (Unix milliseconds).

Scope: account:read · MCP: trenzhub_get_account

No parameters.

GET /me
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/me' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
PATCH/meUpdate profile

Update your display name across your account and active website sessions.

Returns: Updated profile: id, name, email, role, image.

Scope: account:write · MCP: trenzhub_update_account

ParameterTypeRequiredConstraints / default
name (body)stringYes{"type":"string","minLength":1,"maxLength":100}
PATCH /me
curl --fail-with-body -X PATCH 'https://trenzhub.com/api/v1/me' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"name":"Research workspace"}'
POST/me/avatarSet avatar

Upload a PNG, JPEG, or WebP avatar as base64 (maximum decoded size 45 KiB).

Returns: {image}: the stored image path, served under /images/.

Scope: account:write · MCP: trenzhub_set_avatar

ParameterTypeRequiredConstraints / default
contentType (body)stringYes{"type":"string","enum":["image/png","image/jpeg","image/webp"]}
base64 (body)stringYes{"type":"string","minLength":4,"maxLength":61440}
POST /me/avatar
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/me/avatar' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"contentType":"image/png","base64":"VALUE"}'
DELETE/me/avatarRemove avatar

Remove your profile avatar.

Returns: {image: null}.

Scope: account:write · MCP: trenzhub_delete_avatar

No parameters.

DELETE /me/avatar
curl --fail-with-body -X DELETE 'https://trenzhub.com/api/v1/me/avatar' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
GET/me/sessionsWebsite login sessions

List your active website login sessions. Session tokens are never returned.

Returns: Array of {id, createdAt, expiresAt, userAgent, ipAddress}; dates are ISO 8601 strings. Tokens are omitted.

Scope: account:read · MCP: trenzhub_list_sessions

No parameters.

GET /me/sessions
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/me/sessions' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
DELETE/me/sessions/{sessionId}Revoke website session

Sign out one of your website sessions by its ID. Does not revoke API keys.

Returns: {revoked: true, sessionId}.

Scope: account:security · MCP: trenzhub_revoke_session

ParameterTypeRequiredConstraints / default
sessionId (path)stringYes{"type":"string","minLength":1,"maxLength":200}
DELETE /me/sessions/{sessionId}
curl --fail-with-body -X DELETE 'https://trenzhub.com/api/v1/me/sessions/YOUR_SESSION_ID' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
POST/me/sessions/revoke-allSign out all website sessions

Sign out all of your website login sessions. API keys continue to work.

Returns: {revoked: true}.

Scope: account:security · MCP: trenzhub_revoke_all_sessions

ParameterTypeRequiredConstraints / default
confirm (body)stringYes{"type":"string","const":"sign out all sessions"}
POST /me/sessions/revoke-all
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/me/sessions/revoke-all' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"confirm":"VALUE"}'
POST/me/passwordChange password

Change your email/password credential using your current password. Revokes website sessions and all other API keys.

Returns: {changed: true, websiteSessionsRevoked: true, otherApiKeysRevoked: true}. The calling key remains valid.

Scope: account:security · MCP: trenzhub_change_password

ParameterTypeRequiredConstraints / default
currentPassword (body)stringYes{"type":"string","minLength":1,"maxLength":128}
newPassword (body)stringYes{"type":"string","minLength":8,"maxLength":32}
POST /me/password
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/me/password' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"currentPassword":"YOUR_CURRENT_PASSWORD","newPassword":"YOUR_NEW_PASSWORD"}'
GET/me/connectionsLinked login providers

List your linked login providers. Provider secrets and access tokens are never returned.

Returns: Array of {providerId, accountId, createdAt}. Provider tokens and credential hashes are omitted.

Scope: account:read · MCP: trenzhub_list_connections

No parameters.

GET /me/connections
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/me/connections' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
POST/me/connectionsConnect login provider

Return the account-connections page where the user can complete provider consent in their signed-in browser.

Returns: {provider, requiresBrowserConsent: true, url, instruction}. Open url in the user's signed-in browser.

Scope: account:security · MCP: trenzhub_connect_account

ParameterTypeRequiredConstraints / default
provider (body)stringYes{"type":"string","enum":["google","github"]}
POST /me/connections
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/me/connections' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"provider":"google"}'
POST/me/deleteDelete your account

Permanently delete your account and its owned data. Requires your exact email as confirmation. Admin accounts cannot be deleted. All keys and sessions lose access.

Returns: {deleted: true, keysRevoked: true, websiteSessionsRevoked: true}.

Scope: account:security · MCP: trenzhub_delete_account

ParameterTypeRequiredConstraints / default
confirmEmail (body)stringYes{"type":"string","format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"}
confirm (body)stringYes{"type":"string","const":"permanently delete my account"}
POST /me/delete
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/me/delete' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"confirmEmail":"you@example.com","confirm":"VALUE"}'
GET/marketsLanguages and markets

List supported languages and markets for keyword targeting.

Returns: {languages, markets}. Use locale from languages and marketKey from markets in subsequent calls.

Scope: trends:read · MCP: trenzhub_list_markets

No parameters.

GET /markets
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/markets' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
GET/usageUsage and limits

Read shared API/MCP request usage and your website mining quotas. Quotas reset at midnight UTC.

Returns: {plan, billingEnabled, dateKey, resetTimezone, api, mining}. api contains requests, minute, minuteRequests and account limits. mining contains usage and limits for the account role.

Scope: account:read · MCP: trenzhub_get_usage

No parameters.

GET /usage
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/usage' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
GET/keywords/trendKeyword trend

Get monthly search history, volume, competition, and bid metrics for a keyword.

Returns: {keyword, slug, hasData, trend, records, avgMonthlySearches, competition, competitionIndex, lowTopOfPageBidMicros, highTopOfPageBidMicros, aggregateMetricResults, rawResults}. trend: {month,value}[]; records: {label,value,display}[]. Bid values are micros; unavailable metrics are null.

Scope: trends:read · MCP: trenzhub_get_keyword_trend

ParameterTypeRequiredConstraints / default
keyword (query)stringYes{"type":"string","minLength":1,"maxLength":200}
locale (query)stringNo{"default":"en","description":"Language from list_markets.","type":"string","maxLength":10}
market (query)stringNo{"default":"global","description":"Market from list_markets.","type":"string","maxLength":20}
years (query)integerNo{"default":4,"type":"integer","minimum":1,"maximum":4}
GET /keywords/trend
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/keywords/trend?keyword=AI+agents&locale=en&market=global&years=4' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
GET/keywords/ideasRelated keywords

Find related keywords and demand metrics with pagination.

Returns: {keyword, slug, page, perPage, totalResults, totalPages, hasMore, nextPageAvailable, prevPageAvailable, entriesReturned, storedEntries, isPartial, entries, fetchedAt, chart}. entries contain text, search volume, competition, bid micros, and monthlySearchVolumes. Use nextPageAvailable to paginate.

Scope: trends:read · MCP: trenzhub_get_keyword_ideas

ParameterTypeRequiredConstraints / default
keyword (query)stringYes{"type":"string","minLength":1,"maxLength":200}
locale (query)stringNo{"default":"en","description":"Language from list_markets.","type":"string","maxLength":10}
market (query)stringNo{"default":"global","description":"Market from list_markets.","type":"string","maxLength":20}
page (query)integerNo{"default":1,"type":"integer","minimum":1,"maximum":10000}
limit (query)integerNo{"default":50,"type":"integer","minimum":1,"maximum":100}
GET /keywords/ideas
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/keywords/ideas?keyword=AI+agents&locale=en&market=global&page=1&limit=50' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
GET/keywords/ideas/export.csvExport related keywords

Export one page of related keyword metrics as CSV. Use page and limit to export additional pages.

Returns: CSV columns: keyword, avgMonthlySearches, competition, competitionIndex, lowTopOfPageBidMicros, highTopOfPageBidMicros.

Scope: trends:read · MCP: trenzhub_export_keyword_ideas

ParameterTypeRequiredConstraints / default
keyword (query)stringYes{"type":"string","minLength":1,"maxLength":200}
locale (query)stringNo{"default":"en","description":"Language from list_markets.","type":"string","maxLength":10}
market (query)stringNo{"default":"global","description":"Market from list_markets.","type":"string","maxLength":20}
page (query)integerNo{"default":1,"type":"integer","minimum":1,"maximum":10000}
limit (query)integerNo{"default":50,"type":"integer","minimum":1,"maximum":100}
GET /keywords/ideas/export.csv
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/keywords/ideas/export.csv?keyword=AI+agents&locale=en&market=global&page=1&limit=50' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
GET/watchlist/projectsYour watchlist projects

List the projects in your My Trends workspace.

Returns: Array of {id, name, createdAt, updatedAt}. IDs are positive integers; dates are ISO 8601 strings.

Scope: watchlist:read · MCP: trenzhub_list_projects

No parameters.

GET /watchlist/projects
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/watchlist/projects' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
POST/watchlist/projectsCreate project

Create a My Trends project, or return an existing project with the same name.

Returns: {id, name, createdAt, updatedAt}. Returns the existing project for a duplicate name.

Scope: watchlist:write · MCP: trenzhub_create_project

ParameterTypeRequiredConstraints / default
name (body)stringYes{"type":"string","minLength":1,"maxLength":100}
POST /watchlist/projects
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/watchlist/projects' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"name":"Research workspace"}'
PATCH/watchlist/projects/{id}Rename project

Rename a project you own. Duplicate project names return a conflict.

Returns: {updated: true, id, name}.

Scope: watchlist:write · MCP: trenzhub_rename_project

ParameterTypeRequiredConstraints / default
id (path)integerYes{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}
name (body)stringYes{"type":"string","minLength":1,"maxLength":100}
PATCH /watchlist/projects/{id}
curl --fail-with-body -X PATCH 'https://trenzhub.com/api/v1/watchlist/projects/1' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"name":"Research workspace"}'
DELETE/watchlist/projects/{id}Delete project

Delete a project you own. Saved keywords remain in My Trends without a project.

Returns: {deleted: true, id}. Keywords remain saved without a project.

Scope: watchlist:write · MCP: trenzhub_delete_project

ParameterTypeRequiredConstraints / default
id (path)integerYes{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}
DELETE /watchlist/projects/{id}
curl --fail-with-body -X DELETE 'https://trenzhub.com/api/v1/watchlist/projects/1' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
GET/watchlist/keywordsYour saved keywords

List your My Trends keywords, optionally filtered by project, with pagination.

Returns: {items, page, limit, total}. items contain id, keyword, slug, projectId, projectName, metrics, trendPreviewPoints, lastSyncedAt, createdAt and updatedAt.

Scope: watchlist:read · MCP: trenzhub_list_saved_keywords

ParameterTypeRequiredConstraints / default
projectId (query)integerNo{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}
page (query)integerNo{"default":1,"type":"integer","minimum":1,"maximum":10000}
limit (query)integerNo{"default":50,"type":"integer","minimum":1,"maximum":100}
GET /watchlist/keywords
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/watchlist/keywords?page=1&limit=50' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
POST/watchlist/keywordsSave keyword

Save a keyword to My Trends, refresh its metrics, and optionally assign it to a project you own.

Returns: The saved keyword, including id, keyword, slug, projectId, projectName and current metrics.

Scope: watchlist:write · MCP: trenzhub_save_keyword

ParameterTypeRequiredConstraints / default
keyword (body)stringYes{"type":"string","minLength":1,"maxLength":200}
projectId (body)objectNo{"default":null,"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]}
POST /watchlist/keywords
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/watchlist/keywords' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"keyword":"AI agents","projectId":null}'
POST/watchlist/keywords/moveMove saved keywords

Move up to 50 of your saved keywords to a project, or pass null to remove project assignments.

Returns: {updated: true, ids, projectId}.

Scope: watchlist:write · MCP: trenzhub_move_saved_keywords

ParameterTypeRequiredConstraints / default
ids (body)arrayYes{"minItems":1,"maxItems":50,"type":"array","items":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}
projectId (body)objectYes{"anyOf":[{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},{"type":"null"}]}
POST /watchlist/keywords/move
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/watchlist/keywords/move' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"ids":[1],"projectId":null}'
POST/watchlist/keywords/deleteDelete saved keywords

Delete up to 50 saved keywords you own.

Returns: {deleted: true, ids}.

Scope: watchlist:write · MCP: trenzhub_delete_saved_keywords

ParameterTypeRequiredConstraints / default
ids (body)arrayYes{"minItems":1,"maxItems":50,"type":"array","items":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}}
POST /watchlist/keywords/delete
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/watchlist/keywords/delete' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"ids":[1]}'
POST/watchlist/keywords/{id}/refreshRefresh saved keyword

Refresh the metrics of one saved keyword. Existing metrics are preserved if the provider fails.

Returns: {id, keyword, avgMonthlySearches, competitionIndex, competition, bid micros, latestDataMonth, trendChange3m, trendDirection3m, trendPreviewPoints}.

Scope: watchlist:write · MCP: trenzhub_refresh_saved_keyword

ParameterTypeRequiredConstraints / default
id (path)integerYes{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}
POST /watchlist/keywords/{id}/refresh
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/watchlist/keywords/1/refresh' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{}'
GET/watchlist/export.csvExport My Trends

Export your saved keyword metrics as CSV, optionally for one project.

Returns: CSV attachment containing saved keywords, project assignments, metrics and trend history.

Scope: watchlist:read · MCP: trenzhub_export_watchlist

ParameterTypeRequiredConstraints / default
projectId (query)integerNo{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991}
GET /watchlist/export.csv
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/watchlist/export.csv' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
GET/mining/runsYour mining runs

List your 12 most recent Trends Mining runs for a language and market.

Returns: Array of up to 12 recent runs for the selected language and market, including id, topic, status, counts and dates.

Scope: mining:read · MCP: trenzhub_list_mining_runs

ParameterTypeRequiredConstraints / default
locale (query)stringNo{"default":"en","description":"Language from list_markets.","type":"string","maxLength":10}
market (query)stringNo{"default":"global","description":"Market from list_markets.","type":"string","maxLength":20}
GET /mining/runs
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/mining/runs?locale=en&market=global' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
POST/mining/runsStart Trends Mining

Start a background mining run using your existing website quota. Poll get_mining_progress every 5 seconds.

Returns: {runId, status:'queued', progressUrl}. Persist runId before polling.

Scope: mining:write · MCP: trenzhub_create_mining_run

ParameterTypeRequiredConstraints / default
locale (body)stringNo{"default":"en","description":"Language from list_markets.","type":"string","maxLength":10}
market (body)stringNo{"default":"global","description":"Market from list_markets.","type":"string","maxLength":20}
seedKeyword (body)stringYes{"type":"string","minLength":1,"maxLength":2000,"description":"Seed topics separated by commas or newlines."}
industryTopic (body)stringNo{"default":"No industry restriction","type":"string","maxLength":80}
keywordCount (body)integerNo{"default":100,"type":"integer","minimum":1,"maximum":100000}
advancedFilters (body)objectNo{"type":"object","properties":{"enabled":{"default":false,"type":"boolean"},"minAvgMonthlySearches":{"default":null,"anyOf":[{"type":"integer","minimum":0,"maximum":1000000000},{"type":"null"}]},"minGrowthPercent":{"default":null,"anyOf":[{"type":"number","minimum":0,"maximum":100000},{"type":"null"}]},"minGrowthPeriod":{"default":"3m","type":"string","enum":["1m","2m","3m","6m","1y","2y","3y"]},"competitionLevels":{"default":[],"maxItems":3,"type":"array","items":{"type":"string","enum":["LOW","MEDIUM","HIGH"]}},"excludedTerms":{"default":[],"maxItems":50,"type":"array","items":{"type":"string","minLength":1,"maxLength":80}}},"additionalProperties":false}
POST /mining/runs
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/mining/runs' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"locale":"en","market":"global","seedKeyword":"AI agents, automation","industryTopic":"No industry restriction","keywordCount":100}'
GET/mining/runs/{runId}Mining results

Read your mining run, candidates, and logs. Only the run owner can access private results.

Returns: {run, candidates, logs}. run includes topic, status, counts, targeting and filter settings. candidates contain keyword, status, metrics and trendPoints; logs contain ts, level and message.

Scope: mining:read · MCP: trenzhub_get_mining_run

ParameterTypeRequiredConstraints / default
runId (path)stringYes{"type":"string","minLength":1,"maxLength":100}
GET /mining/runs/{runId}
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/mining/runs/YOUR_RUN_ID' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
GET/mining/runs/{runId}/progressMining progress

Poll your mining run status and progress. Wait at least 5 seconds between polls.

Returns: {version, run, queue, recentLogs}. run.status is queued, running, completed, failed or stopped. queue contains queued, checking, pending, results, failed and total. Poll at most every 5 seconds.

Scope: mining:read · MCP: trenzhub_get_mining_progress

ParameterTypeRequiredConstraints / default
runId (path)stringYes{"type":"string","minLength":1,"maxLength":100}
GET /mining/runs/{runId}/progress
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/mining/runs/YOUR_RUN_ID/progress' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
POST/mining/runs/{runId}/stopStop mining

Stop your queued or running mining job and keep its results.

Returns: {runId, status:'stopped'}.

Scope: mining:write · MCP: trenzhub_stop_mining_run

ParameterTypeRequiredConstraints / default
runId (path)stringYes{"type":"string","minLength":1,"maxLength":100}
POST /mining/runs/{runId}/stop
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/mining/runs/YOUR_RUN_ID/stop' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{}'
DELETE/mining/runs/{runId}Delete mining run

Delete your mining run, candidates, and logs.

Returns: {deleted: true, runId}.

Scope: mining:write · MCP: trenzhub_delete_mining_run

ParameterTypeRequiredConstraints / default
runId (path)stringYes{"type":"string","minLength":1,"maxLength":100}
DELETE /mining/runs/{runId}
curl --fail-with-body -X DELETE 'https://trenzhub.com/api/v1/mining/runs/YOUR_RUN_ID' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
GET/mining/runs/{runId}/exportExport mining results

Export your mining results as JSON or CSV.

Returns: CSV or JSON attachment of qualified keyword results and full monthly trend history.

Scope: mining:read · MCP: trenzhub_export_mining_run

ParameterTypeRequiredConstraints / default
runId (path)stringYes{"type":"string","minLength":1,"maxLength":100}
format (query)stringNo{"default":"json","type":"string","enum":["json","csv"]}
GET /mining/runs/{runId}/export
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/mining/runs/YOUR_RUN_ID/export?format=json' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
GET/keysYour API keys

List your key names, prefixes, scopes, expiry, and usage. Secret values are never returned.

Returns: Array of up to 100 keys; active keys are always listed first. Fields: id, name, prefix, scopes, createdAt, expiresAt, revokedAt, lastUsedAt, requestCount. Key timestamps are Unix milliseconds. Secrets and hashes are omitted.

Scope: keys:manage · MCP: trenzhub_list_api_keys

No parameters.

GET /keys
curl --fail-with-body -X GET 'https://trenzhub.com/api/v1/keys' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"
POST/keysCreate API key

Create a new key. The secret is returned once. New keys cannot exceed the calling key's scopes or expiry.

Returns: {id, name, prefix, scopes, createdAt, expiresAt, key}. key is the secret, returned only at creation.

Scope: keys:manage · MCP: trenzhub_create_api_key

ParameterTypeRequiredConstraints / default
name (body)stringYes{"type":"string","minLength":1,"maxLength":80}
scopes (body)arrayYes{"minItems":1,"maxItems":9,"type":"array","items":{"type":"string","enum":["account:read","account:write","account:security","trends:read","watchlist:read","watchlist:write","mining:read","mining:write","keys:manage"]}}
expiresInDays (body)integerNo{"default":90,"type":"integer","minimum":1,"maximum":365}
POST /keys
curl --fail-with-body -X POST 'https://trenzhub.com/api/v1/keys' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{"name":"Research workspace","scopes":["trends:read","watchlist:read"],"expiresInDays":90}'
DELETE/keys/{keyId}Revoke API key

Immediately revoke one of your keys. Revoking the current key ends its API and MCP access.

Returns: {revoked: true, id}.

Scope: keys:manage · MCP: trenzhub_revoke_api_key

ParameterTypeRequiredConstraints / default
keyId (path)stringYes{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}
DELETE /keys/{keyId}
curl --fail-with-body -X DELETE 'https://trenzhub.com/api/v1/keys/YOUR_KEY_ID' \
  -H "Authorization: Bearer $TRENZHUB_API_KEY"

Responses & errors

Successful JSON responses wrap results in data and include meta.requestId. Export endpoints download CSV or JSON directly. MCP results use the same envelope in structuredContent and text; tool failures set isError.

Error response
{
  "error": {
    "code": "insufficient_scope",
    "message": "This key requires the watchlist:write scope."
  },
  "meta": {
    "requestId": "request-uuid"
  }
}
HTTPAction
400Fix the parameters or JSON. Validation errors include field details.
401Create or provide a valid, unexpired key.
403Grant the required scope. Browser requests must use the same origin; server-side clients can call directly.
404Check the endpoint or resource ID. Private resources must belong to you.
409Check the resource state, project name, or active-key cap.
413 / 415Use a JSON object smaller than 64 KiB with Content-Type: application/json.
429Honor Retry-After, inspect usage, and wait for the minute or daily reset.
503Retry reads with bounded backoff. Include X-Request-Id when contacting support.

Do not blindly retry creation requests. A job may already exist if the response was lost; inspect your recent runs first. Wait at least 5 seconds between progress polls.

Feature coverage

REST and MCP cover keyword trends and ideas, My Trends projects and batch actions, mining creation and advanced filters, progress, stopping and deletion, exports, profile and avatar updates, passwords, website sessions, linked providers, account deletion, usage, and scoped key management.

Connecting a new Google or GitHub provider requires the user's browser consent; connect_account returns the correct settings page. Appearance and viewed-keyword history live in the browser; agents keep their own local history. Admin controls are outside the registered-user API.