Skip to content
Last updated

Campaign Claim — Error Reference

This page lists every error response your application can receive when claiming a campaign reward (POST /campaigns/claims) and when reading claim history (GET /campaigns/claims/me, GET /campaigns/claims).

For the general error envelope, categories, and client-handling patterns, see the Error Handling guide — this page only covers what's specific to claiming.


Using the @explorins/pers-sdk

If you're on the PERS SDK rather than calling the REST API directly, claims go through sdk.campaigns.claimCampaign(...) and surface the same error codes wrapped in the SDK's own error classes (SDK Error Handling):

import { PersApiError, AuthenticationError } from "@explorins/pers-sdk/core";

try {
  const claim = await sdk.campaigns.claimCampaign({
    campaignId: "campaign-123",
    businessId: "business-456" // optional business context
  });
} catch (error) {
  if (error instanceof AuthenticationError) {
    // 401 — redirect to login
  } else if (error instanceof PersApiError) {
    // The SDK passes the full backend structured error through onto the thrown
    // instance — not just status/message: error.code, error.category, error.domain,
    // error.retryable, and error.details all map 1:1 to the tables below.
    console.error("Claim failed:", error.code, error.status, error.category, error.retryable);
  }
}

POST /campaigns/claims — Claim a campaign reward

HTTPcodeRetryableWhat it meansWhat to do
401AUTHENTICATION_REQUIREDNoYou're not signed in.Sign the user in and retry.
401INVALID_TOKEN / TOKEN_EXPIRED / TOKEN_REVOKEDNoYour access token is invalid, expired, or revoked.Refresh the token (or re-authenticate), then retry.
404CAMPAIGN_NOT_FOUNDNoThe campaignId/triggerSourceId you sent doesn't match any campaign.Check the ID and retry.
404TRIGGER_SOURCE_NOT_FOUNDNoThe triggerSourceId you sent doesn't exist (e.g. a stale/invalid QR code).Re-scan/re-fetch a valid trigger source.
400VALIDATION_ERRORNoMalformed input — e.g. campaignId doesn't match the trigger source's campaign, the campaign has multiple trigger sources and you didn't specify which one, or neither ID was provided. Check message for specifics.Fix the request and retry.
409CAMPAIGN_NOT_ACTIVENoThis campaign isn't currently active.Not actionable by retry.
409CAMPAIGN_ENDED / CAMPAIGN_NOT_STARTEDNoThe campaign's date window doesn't cover now.Not actionable by retry.
422CAMPAIGN_USER_INFO_REQUIREDNoClaiming requires a user profile field (or a user identifier for business/system claims) that wasn't provided. See details.missingFields.Prompt for the missing field/identifier and retry.
422CAMPAIGN_BUSINESS_REQUIREDNoThis campaign must be claimed on behalf of a business, and none was provided.Provide business context and retry.
400CAMPAIGN_LOCATION_REQUIREDNoThis campaign checks proximity to a location and no user location was sent.Send latitude/longitude and retry.
422CAMPAIGN_DISTANCE_EXCEEDEDNoThe user is too far from the required location.Not actionable by retry — the user needs to be physically closer.
422CAMPAIGN_CONDITION_NOT_METNoA campaign-specific condition wasn't satisfied (e.g. a custom metadata condition, a per-source/global claim limit, or a trigger-type mismatch). Check message for which condition.Depends on the condition — usually not actionable by retry.
400LOCATION_VERIFICATION_REQUIREDNoThis campaign has a country restriction and we couldn't determine the user's location.Ensure location data is sent with the request, then retry.
422GEOGRAPHIC_RESTRICTIONNoThis campaign isn't available in the user's country.Not actionable by retry.
409CAMPAIGN_ALREADY_CLAIMEDNoThe user (or the given externalReferenceId/business) has already claimed this campaign. Permanent — not retryable.Not actionable by retry.
409CAMPAIGN_CLAIM_ALREADY_PROCESSINGNoThe user has a claim for this campaign currently in progress. Transient.Don't retry immediately — poll GET /campaigns/claims/me?campaignId=... (using the claim ID from the error) instead of resubmitting.
409CAMPAIGN_CLAIM_LIMIT_REACHEDNoThe user has already claimed this campaign the maximum number of times allowed.Not actionable by retry.
409CAMPAIGN_DAILY_LIMIT_REACHEDNoThe user (or business) has reached today's claim limit for this campaign.Retry after the daily window resets.
409CAMPAIGN_GLOBAL_LIMIT_REACHEDNoThis campaign has reached its total claim limit across all users.Not actionable by retry — the campaign is exhausted.
409CAMPAIGN_GLOBAL_DAILY_LIMIT_REACHEDNoThis campaign has reached its total claim limit for today across all users.Retry after the daily window resets.
422WALLET_MISSING_SIGNINGNoThe user's (or business's) wallet needs a one-time signing-account setup before it can receive the reward.Complete wallet/signing setup, then retry.
429CAMPAIGN_COOLDOWN_ACTIVEYes (after cooldown)The user must wait between claims for this campaign. See details.resetTime (ISO 8601 timestamp) and details.window.Retry after the cooldown elapses.
422BUSINESS_NOT_MINTERNoThe business isn't authorized to send this reward token.Contact support/admin to authorize the business as a minter.
422CAMPAIGN_NO_TRIGGERNoThe campaign is misconfigured (no trigger). This is a server-side configuration issue, not a client error.Contact support — this needs admin correction of the campaign setup.
500SYSTEM_ERRORYesAn unexpected error occurred while processing the reward transaction. The claim was marked as failed — no reward was left in an inconsistent state.Safe to retry after a short delay. If it keeps happening, contact support with the timestamp.

Note on 409 CAMPAIGN_CLAIM_ALREADY_PROCESSING: this is expected behavior for double-submits (e.g. a user double-tapping "Claim"), not necessarily an error state — debounce the claim button client-side.

Note on completion-threshold campaigns: if a campaign has a claim-count threshold that hasn't been reached yet, a successful claim (200) is returned without a reward transaction — this is expected, not an error. The reward is granted once the threshold is met on a later claim.


GET /campaigns/claims/me, GET /campaigns/claims

HTTPcodeWhat it meansWhat to do
401AUTHENTICATION_REQUIREDYou're not signed in.Sign in and retry.
400VALIDATION_ERRORAdmin list queries: you filtered by both userId and businessId at once (not supported).Use one or the other.

There is no GET /campaigns/claims/{id} endpoint — retrieve claims via the list/me endpoints.


Quick reference — all codes for this flow, by HTTP status

HTTPCodes
400VALIDATION_ERROR, CAMPAIGN_LOCATION_REQUIRED, LOCATION_VERIFICATION_REQUIRED
401AUTHENTICATION_REQUIRED, INVALID_TOKEN, TOKEN_EXPIRED, TOKEN_REVOKED
404CAMPAIGN_NOT_FOUND, TRIGGER_SOURCE_NOT_FOUND
409CAMPAIGN_ALREADY_CLAIMED, CAMPAIGN_CLAIM_ALREADY_PROCESSING, CAMPAIGN_CLAIM_LIMIT_REACHED, CAMPAIGN_DAILY_LIMIT_REACHED, CAMPAIGN_GLOBAL_LIMIT_REACHED, CAMPAIGN_GLOBAL_DAILY_LIMIT_REACHED, CAMPAIGN_NOT_ACTIVE, CAMPAIGN_ENDED, CAMPAIGN_NOT_STARTED
422WALLET_MISSING_SIGNING, CAMPAIGN_USER_INFO_REQUIRED, CAMPAIGN_CONDITION_NOT_MET, CAMPAIGN_BUSINESS_REQUIRED, CAMPAIGN_DISTANCE_EXCEEDED, GEOGRAPHIC_RESTRICTION, BUSINESS_NOT_MINTER, CAMPAIGN_NO_TRIGGER
429CAMPAIGN_COOLDOWN_ACTIVE
500SYSTEM_ERROR

For the underlying error envelope, categories, and general client-side handling patterns, see the Error Handling guide.