WebsitePlatform Login

Sponsorship API

API for programmatic management of partner sponsorship campaigns, links, and billing status

Partner Sponsorship API

The Partner Sponsorship API is for partner organizations that want to automate sponsorship campaigns, redemption links, and internal billing status tracking. Access requires both partnerSponsorship and partnerSponsorshipApi to be enabled for the partner organization.

This API does not include public validate or end-user redeem endpoints. The actual redemption step is only available through the in-app product flow.

Authentication

This API uses Organization API Keys. Keys are created by organization administrators, use the sk_meingpt_um_ prefix, and are sent as a Bearer token.

curl -X GET "https://app.meingpt.com/api/sponsorship/v1/campaigns" \
  -H "Authorization: Bearer $MEINGPT_SPONSORSHIP_API_KEY"

Rate Limiting

All organization API keys have a default rate limit of 100 requests per minute. Rate limit information is returned in response headers:

  • X-RateLimit-Limit: Maximum requests per window
  • X-RateLimit-Remaining: Remaining requests
  • X-RateLimit-Reset: Unix timestamp when the limit resets

Creating API Keys

Workspace admins create organization API keys in settings. See API & Key Management for setup details.

The clear-text key is shown only once. Store it securely.

Endpoints

List campaigns

GET /api/sponsorship/v1/campaigns?page=1&pageSize=50&status=active|inactive|all

Lists sponsorship campaigns for the partner organization with pagination.

Request fields

FieldLocationTypeRequiredDescription
pageQueryIntegerNoPage number, default 1
pageSizeQueryIntegerNoItems per page, default 50, maximum 100
statusQueryStringNoFilter active, inactive, or all, default all

Response

{
  "status": "success",
  "campaigns": [
    {
      "id": "camp_123",
      "name": "Spring promotion",
      "durationMonths": 4,
      "maxRedemptions": 250,
      "expiresAt": "2026-06-30T23:59:59.000Z",
      "includedSeats": 5,
      "allowedEmailDomains": ["acme.com"],
      "allowedEmails": ["alice@acme.com"],
      "pricing": {
        "model": "FIXED",
        "amountEur": 5,
        "unit": "PER_REDEMPTION"
      },
      "isActive": true,
      "createdAt": "2026-04-01T08:00:00.000Z",
      "updatedAt": "2026-04-10T12:15:00.000Z",
      "completedRedemptionsCount": 18,
      "reservedRedemptionsCount": 20
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 50,
  "totalPages": 1
}

Error codes

  • 400 - Invalid query parameters
  • 401 - Invalid or missing API key
  • 403 - Feature not enabled or no access to the API
  • 404 - Resource not found

Create campaign

POST /api/sponsorship/v1/campaigns

Creates a new sponsorship campaign.

Request fields

FieldTypeRequiredDescription
nameStringYesCampaign name, 1 to 200 characters
durationMonthsIntegerYesSponsorship duration in months, integer from 1 to 6
maxRedemptionsIntegerNoOptional redemption cap, minimum 1
expiresAtString (Date-Time)NoOptional campaign expiry date
includedSeatsInteger or nullNoOptional seat cap per sponsored organization, 1 to 1000
allowedEmailDomainsString arrayNoOptional allowlist of email domains
allowedEmailsString arrayNoOptional allowlist of individual email addresses

Response

{
  "status": "success",
  "campaign": {
    "id": "camp_123",
    "name": "Spring promotion",
    "durationMonths": 4,
    "maxRedemptions": 250,
    "expiresAt": "2026-06-30T23:59:59.000Z",
    "includedSeats": 5,
    "allowedEmailDomains": ["acme.com"],
    "allowedEmails": ["alice@acme.com"],
    "pricing": null,
    "isActive": true,
    "createdAt": "2026-04-16T09:30:00.000Z",
    "updatedAt": "2026-04-16T09:30:00.000Z",
    "completedRedemptionsCount": 0,
    "reservedRedemptionsCount": 0
  }
}

Error codes

  • 400 - Invalid request body
  • 401 - Invalid or missing API key
  • 403 - Feature not enabled or no access to the API
  • 404 - Resource not found

Update campaign

PATCH /api/sponsorship/v1/campaigns/:campaignId

Updates individual fields of an existing campaign.

Request fields

FieldTypeRequiredDescription
nameStringNoNew campaign name, 1 to 200 characters
durationMonthsIntegerNoNew sponsorship duration, integer from 1 to 6
maxRedemptionsInteger or nullNoNew cap. Use null to clear an existing cap; omit to leave unchanged
expiresAtString (Date-Time) or nullNoNew expiry date. Use null to clear an existing date; omit to leave unchanged
isActiveBooleanNoEnables or disables the campaign
includedSeatsInteger or nullNoNew seat cap. Use null to clear the value
allowedEmailDomainsString arrayNoNew domain allowlist
allowedEmailsString arrayNoNew email allowlist

Response

{
  "status": "success",
  "campaign": {
    "id": "camp_123",
    "name": "Spring promotion DACH",
    "durationMonths": 5,
    "maxRedemptions": null,
    "expiresAt": null,
    "includedSeats": 10,
    "allowedEmailDomains": ["acme.com", "example.org"],
    "allowedEmails": ["alice@acme.com"],
    "pricing": {
      "model": "FIXED",
      "amountEur": 5,
      "unit": "PER_REDEMPTION"
    },
    "isActive": true,
    "createdAt": "2026-04-01T08:00:00.000Z",
    "updatedAt": "2026-04-16T10:00:00.000Z",
    "completedRedemptionsCount": 18,
    "reservedRedemptionsCount": 20
  }
}

Error codes

  • 400 - Invalid request body
  • 401 - Invalid or missing API key
  • 403 - Feature not enabled or no access to the API
  • 404 - Resource not found
GET /api/sponsorship/v1/campaigns/:campaignId/links?page=1&pageSize=100

Lists sponsorship links for a campaign.

Request fields

FieldLocationTypeRequiredDescription
campaignIdPathStringYesCampaign ID
pageQueryIntegerNoPage number, default 1
pageSizeQueryIntegerNoItems per page, default 100, maximum 100

Response

{
  "status": "success",
  "links": [
    {
      "id": "link_123",
      "name": "April landing page",
      "token": "abcdef1234567890abcdef1234567890",
      "url": "https://app.meingpt.com/auth?sponsored=abcdef1234567890abcdef1234567890",
      "isActive": true,
      "hasPassword": true,
      "createdAt": "2026-04-16T10:15:00.000Z",
      "completedRedemptionsCount": 7
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 100,
  "totalPages": 1
}

Error codes

  • 400 - Invalid query parameters
  • 401 - Invalid or missing API key
  • 403 - Feature not enabled or no access to the API
  • 404 - Resource not found
POST /api/sponsorship/v1/campaigns/:campaignId/links

Creates a new sponsorship link under a campaign.

Request fields

FieldTypeRequiredDescription
nameStringNoOptional display name for the link, 1 to 200 characters
passwordStringNoOptional link password, minimum 4 characters

Response

{
  "status": "success",
  "link": {
    "id": "link_123",
    "name": "April landing page",
    "token": "abcdef1234567890abcdef1234567890",
    "url": "https://app.meingpt.com/auth?sponsored=abcdef1234567890abcdef1234567890",
    "isActive": true,
    "hasPassword": true,
    "createdAt": "2026-04-16T10:15:00.000Z",
    "completedRedemptionsCount": 0
  }
}

Error codes

  • 400 - Invalid request body
  • 401 - Invalid or missing API key
  • 403 - Feature not enabled or no access to the API
  • 404 - Resource not found
PATCH /api/sponsorship/v1/links/:linkId

Updates the name and active state of an existing sponsorship link.

Request fields

FieldTypeRequiredDescription
nameStringNoNew display name, 1 to 200 characters
isActiveBooleanNoEnables or disables the link

Response

{
  "status": "success",
  "link": {
    "id": "link_123",
    "name": "Website header",
    "token": "abcdef1234567890abcdef1234567890",
    "url": "https://app.meingpt.com/auth?sponsored=abcdef1234567890abcdef1234567890",
    "isActive": false,
    "hasPassword": true,
    "createdAt": "2026-04-16T10:15:00.000Z",
    "completedRedemptionsCount": 7
  }
}

Error codes

  • 400 - Invalid request body
  • 401 - Invalid or missing API key
  • 403 - Feature not enabled or no access to the API
  • 404 - Resource not found
PATCH /api/sponsorship/v1/links/:linkId/password

Sets a password for a link or removes it again.

Request fields

FieldTypeRequiredDescription
passwordString or nullYesNew password with at least 4 characters, or null to remove the password

Response

{
  "status": "success",
  "success": true
}

Error codes

  • 400 - Invalid request body
  • 401 - Invalid or missing API key
  • 403 - Feature not enabled or no access to the API
  • 404 - Resource not found

List campaign redemptions

GET /api/sponsorship/v1/campaigns/:campaignId/redemptions?page=1&pageSize=100&billingStatus=UNBILLED|BILLED|DISPUTED|WAIVED

Lists completed redemptions for a campaign including billing metadata.

Request fields

FieldLocationTypeRequiredDescription
campaignIdPathStringYesCampaign ID
pageQueryIntegerNoPage number, default 1
pageSizeQueryIntegerNoItems per page, default 100, maximum 100
billingStatusQueryStringNoOptional filter: UNBILLED, BILLED, DISPUTED, or WAIVED

Response

{
  "status": "success",
  "redemptions": [
    {
      "id": "red_123",
      "redeemedAt": "2026-04-12T15:20:00.000Z",
      "sponsoredUntil": "2026-08-12T15:20:00.000Z",
      "extendedUntil": "2026-09-30T23:59:59.000Z",
      "extensionReason": "Partner extends pilot phase",
      "includedSeats": 5,
      "pricing": {
        "model": "FIXED",
        "amountEur": 5,
        "unit": "PER_REDEMPTION"
      },
      "billingStatus": "UNBILLED",
      "billingAmount": 99,
      "billedAt": null,
      "billingBatchId": null,
      "organizationName": "Example GmbH",
      "userEmail": "admin@example.com",
      "linkName": "April landing page"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 100,
  "totalPages": 1
}

Error codes

  • 400 - Invalid query parameters
  • 401 - Invalid or missing API key
  • 403 - Feature not enabled or no access to the API
  • 404 - Resource not found

Extending a sponsorship

PATCH /api/sponsorship/v1/redemptions/:redemptionId/extend

Extends an existing redemption to a later end date.

Request fields

FieldTypeRequiredDescription
newSponsoredUntilString (Date-Time)YesNew end date, must be later than the current sponsoredUntil
reasonStringNoOptional internal reason for the extension

Response

{
  "status": "success",
  "redemption": {
    "id": "red_123",
    "redeemedAt": "2026-04-12T15:20:00.000Z",
    "sponsoredUntil": "2026-09-30T23:59:59.000Z",
    "extendedUntil": "2026-09-30T23:59:59.000Z",
    "extensionReason": "Partner extends pilot phase",
    "campaignId": "camp_123",
    "campaignName": "Pilot Campaign Q3",
    "billingStatus": "UNBILLED",
    "billingAmount": 99,
    "billedAt": null,
    "billingBatchId": null,
    "includedSeats": 5,
    "organizationName": "Example GmbH",
    "userEmail": "admin@example.com",
    "linkName": "April landing page",
    "linkToken": "lnk_public_token",
    "pricing": {
      "model": "FIXED",
      "amountEur": 5,
      "unit": "PER_REDEMPTION"
    }
  }
}

Error codes

  • 400 - Invalid request body or the new date is not later than the current end date
  • 401 - Invalid or missing API key
  • 403 - Feature not enabled or no access to the API
  • 404 - Resource not found

Update redemption billing status

PATCH /api/sponsorship/v1/redemptions/:redemptionId/billing

Updates partner-side billing metadata for a completed redemption.

Request fields

FieldTypeRequiredDescription
billingStatusStringYesNew status: UNBILLED, BILLED, DISPUTED, or WAIVED
billingAmountNumberNoOptional amount, minimum 0
billingBatchIdStringNoOptional batch or invoice reference

Response

{
  "status": "success",
  "success": true
}

Error codes

  • 400 - Invalid request body
  • 401 - Invalid or missing API key
  • 403 - Feature not enabled or no access to the API
  • 404 - Resource not found

Redemption URL flow

The partner first creates a sponsorship link. The API already returns the full URL in the url field, which is ${ORIGIN}/auth?sponsored=${token}.

When an end user opens that URL, they enter the normal authentication flow at /auth?sponsored=<token>. After successful sign-up or sign-in, a new sponsored organization is provisioned for that user with the duration configured on the campaign.

Pricing is read-only via the API. If meinGPT platform support has configured commercial terms, they appear in the pricing field; partners cannot change those values through the API.

On this page