UGCDocumentation

Automation triggers (31)

REST-hook trigger names for the Automation subscribe API

Updated September 18, 2026
POST/automation/webhooks/subscribe
Required

REST-hook trigger names for the Automation subscribe API

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

Interactive API PlaygroundTest this endpoint directly from your browser

Credentials

Your API key is never stored and only used for this request

curl -X POST https://api.ugc.africa/automation/webhooks/subscribe \
  -H "Authorization: Bearer YOUR_API_KEY"
Coming soon

SDK examples (coming soon)

JavaScript
// 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

JSON
{
  "id": "..."
}
curl
curl -X POST https://api.ugc.africa/automation/webhooks/subscribe \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json"

These strings are the `trigger` value for POST /automation/webhooks/subscribe. The list matches AUTOMATION_TRIGGER_LIST in api/src/modules/automation/constants/trigger-types.ts. The Developer Console webhook picker exposes 19 UGC-focused events (campaign, slot, earnings, withdrawals) - not billing/username or AI/storage.

Delivery payloads are JSON and are signed with `X-UGC-Signature` (hex HMAC-SHA256 of the raw JSON body using the hookSecret returned at subscribe time); each delivery also carries an X-UGC-Event-Id header for idempotent processing.

Campaign lifecycle

TriggerFires when
campaign_createdA DRAFT campaign is created
campaign_fundedFunding settles (checkout, wallet, or payment link)
campaign_approvedModeration approves the campaign
campaign_rejectedModeration rejects the campaign
campaign_activatedCampaign goes live and starts accepting slot reservations
campaign_pausedCampaign is paused by the advertiser or platform
campaign_completedCampaign budget is exhausted or its end date passes

Slot lifecycle

TriggerFires when
slot_reservedA creator reserves a slot on a campaign
slot_submittedA creator submits a post URL for review
slot_approvedA submitted slot is approved
slot_rejectedA submitted slot is rejected
slot_expiredA reserved slot's window lapses without submission
slot_proof_requiredAdditional proof is requested before approval

Earnings & withdrawals

TriggerFires when
earnings_creditedA slot approval credits earnings (fires once per approval that credits > 0; carries payoutPercent and flatPayoutTierApplied so you can tell a full-rate credit from a reduced one on FLAT campaigns with performance tiers - see Create a campaign)
earnings_releasedCleared creator earnings move from pending balance into the spendable wallet
withdrawal_initiatedA wallet or crypto cash-out request is on the books (not under manual review)
withdrawal_reviewOps or policy holds the cash-out (high amount, float, pending approval, etc.)
withdrawal_completedThe rail confirms funds sent
withdrawal_failedTerminal failure on a cash-out

AI clip, credits & storage

TriggerFires when
ai_clip_job_succeededAn AI clip job completes successfully
ai_clip_job_failedAn AI clip job fails terminally
ai_credit_balance_lowAI credit balance drops below the configured threshold
storage_connection_reconnect_requiredA linked Drive/Dropbox (or similar) grant must be reconnected before ingest/clip jobs can run

Checkout, subscriptions & username

TriggerFires when
payment_intent_createdAn advertiser checkout payment intent is created
payment_paidA checkout payment intent is paid
subscription_createdA billing subscription starts
subscription_cancelledA billing subscription is cancelled
subscription_payment_succeededA recurring subscription charge succeeds
subscription_payment_failedA recurring subscription charge fails
username_purchasedA premium username is purchased
username_claimedA free username is claimed

Payload shape

json
{
  "id": "evt_...",
  "trigger": "campaign_funded",
  "timestamp": "2026-08-28T10:30:00Z",
  "data": { "...": "..." }
}

Exact data fields depend on the resource; treat unfamiliar fields as additive and non-breaking. See Actions for the Campaign/Slot shapes these triggers report on.

Common Errors

400INVALID_CURRENCY

Invalid Currency Code

The currency code provided is not supported.

Example Response
JSON
{
  "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.

400INSUFFICIENT_BALANCE

Insufficient Wallet Balance

The wallet does not have enough balance to complete this transaction.

Example Response
JSON
{
  "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.

401UNAUTHORIZED

Authentication Required

The request requires authentication but none was provided.

Example Response
JSON
{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or expired authentication token"
  }
}

Solution: Include a valid API key or JWT token in the Authorization header.

429RATE_LIMIT_EXCEEDED

Rate Limit Exceeded

Too many requests have been made in a short period.

Example Response
JSON
{
  "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?