MCP server
Connect any MCP-compatible LLM to the platform's campaign, slot, wallet, trust, and Relay tools via Streamable HTTP. Discovery, JWT or OAuth auth, and the full tool list.
https://api.ugc.africa/actions-gateway/openapi.jsonRequired
Requires API key authentication (UGSK_xxx)
Connect any MCP-compatible LLM to the platform's campaign, slot, wallet, trust, and Relay tools via Streamable HTTP. Discovery, JWT or OAuth auth, and the full tool list.
Rate Limit
This endpoint is limited to 100 requests per 1 minute per API key.
Rate limit headers are included in all responses: X-RateLimit-Limit, X-RateLimit-Remaining
Credentials
Your API key is never stored and only used for this request
curl -X GET https://api.ugc.africa/https://api.ugc.africa/actions-gateway/openapi.json \ -H "Authorization: Bearer YOUR_API_KEY"
SDK examples (coming soon)
// Official Node SDK - coming soon. Use REST (see Getting Started) or fetch() examples.
// Planned: npm install @UGC/node
Official @UGC/* client libraries are on the roadmap. Integrate with the REST API and webhooks today. SDK pages · Email notify
Success
{
"id": "..."
}curl -X GET https://api.ugc.africahttps://api.ugc.africa/actions-gateway/openapi.json \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json"The platform exposes a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server so AI models - Claude, GPT, Gemini, Llama, Mistral, and any other MCP-compatible LLM - can orchestrate campaign, slot, wallet, and Relay workflows through typed, self-describing tool calls.
agcred_ keys) when an agent must send transfers or create payment links under hard spend limits.>
GET https://api.ugc.africa/actions-gateway/openapi.json (interactive docs: /actions-gateway/docs) with the same automation OAuth IdP.Discovery
No authentication required for manifest discovery:
GET https://api.ugc.africa/.well-known/mcp.jsonReturns the public manifest: available tools, schemas, and transport hints. MCP clients fetch this automatically during initialization.
Transport
| Mechanism | URL | Description | |
|---|---|---|---|
| Streamable HTTP | POST https://api.ugc.africa/mcp | JSON-RPC initialize / tools/list / tools/call | |
| Session GET | GET https://api.ugc.africa/mcp | Optional session stream (mcp-session-id header) | |
| Session close | DELETE https://api.ugc.africa/mcp | End Streamable HTTP session | JSON-RPC tool calls within an established SSE session |
Tools
Chat-callable tool names come from the ActionRegistry at runtime (platform, campaign, crypto checkout, and payout packs, including check_username). There are no ugc_* or deed_* aliases. Delegated transfers and Clip Studio are not MCP tools. Supplemental Trust, Relay, Insights, and agent_check_balance are merged without colliding with registry names. Use exact names from GET /.well-known/mcp.json. The published registry name is africa.ugc/ugc. Connector URL: https://api.ugc.africa/mcp (this product's example: https://api.ugc.africa/mcp).
Platform
| Tool | Required params | Purpose |
|---|---|---|
check_username | username | Check whether a username is available. OAuth scope username:read. |
Advertiser campaigns
| Tool | Required params | Purpose |
|---|---|---|
campaign_list_mine | - | List the authenticated advertiser's campaigns. Optional status. Scope campaign:read. |
campaign_get_detail | campaignId | Get one campaign the caller owns. Scope campaign:read. |
campaign_create | title, payoutType, advertiserCpmRate, totalBudget | Create a DRAFT campaign. Fund it separately with campaign_fund. Scope campaign:write. |
campaign_fund | campaignId | Fund via checkout, wallet, or payment_link. Scope campaign:fund. destructiveHint: confirm before calling. |
campaign_feature | campaignId | Buy sponsored placement. Scope campaign:fund. destructiveHint: confirm before calling. If create used purchaseFeaturedPlacement: true, first funding already bundles this - do not call it again for that checkout. |
campaign_fund_status | campaignId | Poll whether funding has settled. Scope campaign:read. |
slot_list | campaignId | List creator slots on a campaign the caller owns. Optional status, page, limit. Scope slot:read. |
There is no campaign patch, pause, or analytics MCP tool, and no upload tool. Creative files are URLs on assets (and assetVariants when you need more than one kit).
campaign_create body
Channels are targetPlatforms (platform slugs such as whatsapp_status and snapchat). Channels are targetPlatforms only. payoutType is FLAT, CPM_SOCIAL, or CPM_STREAMING. The rate field is advertiserCpmRate (per 1,000 views, or per post when FLAT).
| Field | Required | Notes | ||
|---|---|---|---|---|
title | yes | Campaign title | ||
payoutType | yes | FLAT | CPM_SOCIAL | CPM_STREAMING |
advertiserCpmRate | yes | Per 1,000 views (CPM types) or per post (FLAT) | ||
totalBudget | yes | Budget in USD | ||
description | no | Broadcaster brief | ||
campaignType | no | STANDARD_VIDEO (default), MUSIC_PROMO, MUSIC_PROMO_PRERELEASE, FIXED_FEE, TEXT_DISTRIBUTION, PRODUCT_PLACEMENT, CLIP_CAMPAIGN. CLIP_CAMPAIGN and TEXT_DISTRIBUTION need a feature flag; a disabled flag returns 403 FEATURE_NOT_AVAILABLE. | ||
campaignGoal | no | STANDARD_VIDEO only: AWARENESS, PRODUCT_LAUNCH, APP_INSTALL | ||
campaignMode | no | BROADCAST (default) or CREATOR_ORIGINAL | ||
clipSourceMode, sourceContentUrl, sourceRightsConfirmed | no | CLIP_CAMPAIGN. clipSourceMode is RAW_FOOTAGE or PRECLIPPED_TEMPLATE. | ||
language | no | Language code, default en | ||
assets, assetVariants | no | CDN URLs plus metadata. Assets may be empty on a DRAFT; required before go-live except TEXT_DISTRIBUTION. | ||
captionTemplate, textContent, requiredHashtags, broadcastInstructions | no | textContent is the verbatim copy for TEXT_DISTRIBUTION. | ||
allowCreatorHook, suppressBrandHashtag | no | Personal intro/outro, and whether to hide the brand-hashtag recommendation | ||
| Music | no | soundUrl, soundTitle, soundArtist, musicPromoMode (OFFICIAL_SOUND | UPLOADED_TRACK | PRERELEASE_TEASER), soundContentKind, soundReferences, streamingLinks, parentCampaignId, scheduledActivateAt |
| Targeting | no | targetPlatforms, countryAllowlist (empty = all countries), targetNiches, cityTargeting, regionTargeting, customRequirements, minKycTier, minCreatorLevel, minFollowers | ||
flatPayoutTiers, maxSlots | no | Tiers are FLAT only. maxSlots is ignored for FLAT (server-computed). | ||
| Other | no | minimumPostDays, minimumPayableViewsPerCycle, minimumPayableViewsTotal, startDate, endDate, conversionUrl, conversionTrackingEnabled, product-placement fields, sourceLinkAccessConfirmed, sourceAssetLink, sourceStorageKey, agencyId, templateId, adDisclosureAccepted, purchaseFeaturedPlacement, idempotencyKey |
Creator
| Tool | Required params | Purpose |
|---|---|---|
campaign_discover | - | Active campaigns with remaining slots. Filters: campaignType, payoutType, platform, country, search, sort (HIGHEST_PAYING, MOST_SLOTS, EXPIRING_SOON, NEW), page, limit. OAuth needs campaign:discover and campaign:read. |
slot_reserve | campaignId | Reserve a slot for the authenticated creator. Scope slot:write. |
slot_list_mine | - | The creator's slots. Optional status. Scope slot:read. |
slot_submit | slotId, platform | Submit the published post. Also send postUrl (link platforms) or postProofUrls (screenshot platforms such as Snapchat Spotlight). platform is TIKTOK, INSTAGRAM_REELS, YOUTUBE_SHORTS, X_TWITTER, WHATSAPP_STATUS, FACEBOOK_REELS, LINKEDIN, PINTEREST, TELEGRAM_CHANNEL, or SNAPCHAT_SPOTLIGHT. originalAssetUrl is required for CREATOR_ORIGINAL. Scope slot:write. |
slot_earnings | slotId | Pro-rata CPM or flat earnings for one slot. Scope earnings:read. |
payout_get_earnings | - | Creator earnings summary (pending, available, totals). Scope earnings:read. |
payout_rate_preview | amount, toCurrency | Preview a USD-to-local conversion. Does not move funds. Scope earnings:read. |
payout_transfer_to_wallet | - | Move cleared earnings into the USD wallet. Optional amount (omit = full available balance). Scope payout:transfer. destructiveHint: confirm the amount first. |
payout_transfer_earnings | - | Move cleared earnings to USD_WALLET, LOCAL_WALLET (needs preferredCurrency), or CRYPTO. Scope payout:transfer. destructiveHint: confirm amount and destination first. |
Wallet
| Tool | Required params | Purpose |
|---|---|---|
wallet_get_balance | - | Balances per currency, minus locked amounts. Optional currency. Scope wallet:read. |
wallet_get_history | - | Paginated history. Optional days, currency, limit. Scope wallet:read. |
wallet_generate_crypto_address | currency, network | Static crypto deposit address for the caller. Scope crypto:deposit. |
Trust
| Tool | Required params | Purpose |
|---|---|---|
trust_get_summary | userId | TrustScore and verification status for a user |
Relay (automated wallet rules)
| Tool | Required params | Purpose |
|---|---|---|
relay_list_rules | - | List active Relay rules. Optional includeInactive. |
relay_create_rule | name, actionType, scheduleType, fromCurrency, amountType | Create a draft rule. The user must approve it in the app before it can execute. |
relay_pause_rule | ruleId | Pause an active rule |
UGSK_ API Key, or MCP tokens, to LLM context windows.Insights
| Tool | Required params | Purpose |
|---|---|---|
spending_get_insights | - | Spending summaries, anomaly alerts, cash-flow predictions. Optional type, unreadOnly, limit. Requires the relay insights feature flag. |
Crypto checkout
| Tool | Required params | Purpose |
|---|---|---|
advertiser_checkout_create_crypto | currency, network | Pay a campaign-funding or advertiser-checkout payment link with cryptocurrency. Pass paymentLinkId (or deprecated paymentId). Scope campaign:fund. destructiveHint: confirm before calling. |
Agent credential (read only)
| Tool | Required params | Purpose |
|---|---|---|
agent_check_balance | - | Available wallet balance and remaining Agent Credential daily cap. Optional currency. Delegated transfers stay on the Agent Credential HTTP API (POST /agent/transfer); they are not an MCP tool. |
Idempotency
Pass Idempotency-Key: <unique_value> on mutating tool calls (campaign_create, campaign_fund, slot_reserve, slot_submit, payout transfers, and others). Several of those tools also accept idempotencyKey in the body when the header is absent. Do not retry a money tool without the same key, and do not call it until the user has confirmed.
Error codes
Tool calls surface the same structured errors as the underlying REST APIs. Agents can make deterministic decisions on every failure:
| HTTP | ApiErrorCode example | Meaning |
|---|---|---|
401 | AUTH_REQUIRED | Missing or invalid JWT / OAuth token |
403 | MCP_NOT_ENABLED | Account lacks mcp_server entitlement |
403 | INSUFFICIENT_SCOPE | OAuth token missing a required action scope (e.g. campaign:fund) |
403 | WALLET_FROZEN | Account is frozen |
409 | SLOT_NO_CAPACITY | No remaining slot capacity on the campaign |
422 | WALLET_INSUFFICIENT_FUNDS | Not enough balance |
429 | RATE_LIMITED | Too many requests |
LLM compatibility
| Model family | MCP support |
|---|---|
| Claude (Anthropic) | ✓ Native MCP client |
| GPT (OpenAI) | ✓ Via MCP adapter |
| Gemini (Google) | ✓ Via MCP adapter |
| Llama / Mistral (open source) | ✓ Via MCP adapter |
| Any MCP-compatible agent | ✓ |
Related
- AI agents overview
- Agent Credentials - scoped
agcred_keys for delegated transfers - Automation - webhook and OAuth integrations
- Actions Gateway OpenAPI:
https://api.ugc.africa/actions-gateway/openapi.json· docs/actions-gateway/docs
Common Errors
INVALID_CURRENCYInvalid Currency Code
The currency code provided is not supported.
{
"success": false,
"error": {
"code": "INVALID_CURRENCY",
"message": "Currency code \"XYZ\" is not supported",
"supportedCurrencies": [
"USD",
"EUR",
"GBP",
"GHS",
"NGN"
]
}
}Solution: Use a valid ISO 4217 currency code. See our list of supported currencies.
INSUFFICIENT_BALANCEInsufficient Wallet Balance
The wallet does not have enough balance to complete this transaction.
{
"success": false,
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient balance in USD wallet",
"required": 5000,
"available": 2500
}
}Solution: Add funds to your wallet or use a different payment method.
UNAUTHORIZEDAuthentication Required
The request requires authentication but none was provided.
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or expired authentication token"
}
}Solution: Include a valid API key or JWT token in the Authorization header.
RATE_LIMIT_EXCEEDEDRate Limit Exceeded
Too many requests have been made in a short period.
{
"success": false,
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 60 seconds",
"retryAfter": 60
}
}Solution: Wait for the specified retry period before making another request. Consider implementing exponential backoff.
Did this solve your problem?