UGCDocumentation

Payment Links Endpoints

Create and manage shareable payment/invoice links

Updated August 28, 2026
POST/payment-links
Required

Create and manage shareable payment/invoice links

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/payment-links \
  -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/payment-links \
  -H "Authorization: Bearer YOUR_JWT_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "iPhone 15 Pro",
    "amount": 500000,
    "currency": "NGN",
    "productType": "PHYSICAL",
    "autoReleaseAfterDays": 7,
    "customSlug": "iphone-15-pro"
  }'

All endpoints below are under /payment-links and require a portal session JWT (Authorization: Bearer <jwt>) - the same token your dashboard session uses. See Payment Links guide for the conceptual overview.

POST /payment-links

FieldTypeRequiredDescription
titlestringYes
descriptionstringNo
amountnumberYes*Min 1, or min 0 if allowCustomAmount
currencyenumYes
allowCustomAmountbooleanNoCustomer enters their own amount
minAmountnumberNoMin 0.01, when allowCustomAmount is set
feeAbsorbedByenumNoMERCHANT (default), CUSTOMER, or SPLIT
linkTypeenumNoPAYMENT_LINK (default) or INVOICE
lineItemsarrayNo{ description, quantity, unitPrice }, invoices only
taxRatenumberNo0-1
paymentTermsstringNoe.g. "Net 30"
dueDatestringNoISO date, required for invoices
productTypeenumNoDIGITAL, PHYSICAL, or SERVICE - enables transaction protection
autoReleaseAfterDaysnumberNoMin 1, default 7
customSlugstringNo3-50 chars, lowercase/numbers/hyphens, auto-lowercased
successRedirectUrlstringNoWhere to send the payer after payment
maxUsesnumberNoMin 1; omit for unlimited
expiresAtstringNoISO date

The hosted link is https://ugc.africa/pay/{shortCode} (or the custom slug).


POST /payment-links/campaigns/:campaignId/fund

Same underlying rail, repurposed so a third party without a UGC account can fund one of your campaigns. Settlement emits campaign_funded.


GET /payment-links

Check slug availability

GET /payment-links/check-slug?slug=your-slug

GET /payment-links/:id

PATCH /payment-links/:id

DELETE /payment-links/:id - returns 200, not 204.

Change the slug

PATCH /payment-links/:id/slug - one-time edit.

Download the invoice PDF

GET /payment-links/:id/invoice-pdf - binary PDF response, invoices only.


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?