# Get my campaign claims (Convenience)

Convenience endpoint for authenticated users to retrieve their own campaign claims.
Equivalent to GET /campaign-claims but with required authentication and
automatic filtering to current user context. Use pagination parameters (page & limit) for optimal performance - recommended for active users. Legacy support: returns array without params (deprecated - will be removed in future).
Features:
- Automatic user context (no userId parameter needed)
- Optional campaign filtering
- Requires user authentication
- Simplified response structure
- Optional entity inclusion (campaign, user, business, transactions)
Usage Examples:
- GET /campaign-claims/me (all claims for authenticated user)
- GET /campaign-claims/me?campaignId=123 (user claims for specific campaign)
- GET /campaign-claims/me?include=campaign,transactions (with related entities)

Endpoint: GET /campaigns/claims/me
Version: 2.0.53
Security: authJWT

## Query parameters:

  - `campaignId` (string)
    Filter by specific campaign ID

  - `include` (array)
    Include related entities: campaign, user, business, triggerSource, transactions (comma-separated)

  - `page` (number)
    Page number (1-based)

  - `limit` (number)
    Items per page

  - `dateFrom` (string)
    Filter items created after this date (ISO 8601)

  - `dateTo` (string)
    Filter items created before this date (ISO 8601)

## Response 200 fields (application/json):

  - `id` (string, required)
    The id of the campaign user claim

  - `externalReferenceId` (string, required)
    External reference ID for idempotency. Used to prevent duplicate claims. Use case: Stripe payment ID, order ID, webhook event ID, etc.

  - `createdAt` (string, required)
    The date the campaign user claim was created

  - `userId` (string, required)
    User ID who claimed the campaign

  - `campaignId` (string, required)
    Campaign ID that was claimed

  - `businessId` (string)
    Business ID associated with this claim (if applicable)

  - `triggerSourceId` (string)
    Trigger Source ID that was used for this claim (e.g., specific QR code, NFC tag, etc.)

  - `user` (object, required)
    User object (DEPRECATED: use userId instead. Only contains {id} during migration. Will be removed in Q2 2026)
    Example: {"id":"user-uuid-123"}

  - `campaign` (object, required)
    Campaign object (DEPRECATED: use campaignId instead. Only contains {id} during migration. Will be removed in Q2 2026)
    Example: {"id":"campaign-uuid-123"}

  - `business` (object)
    Business object (DEPRECATED: use businessId instead. Only contains {id} during migration. Will be removed in Q2 2026)
    Example: {"id":"business-uuid-123"}

  - `userCountryCode` (string, required)
    Country code of the user claiming the campaign

  - `latitude` (number)
    Latitude coordinate where claim was made (reduced precision ~1.1km for privacy compliance)
    Example: 41.39

  - `longitude` (number)
    Longitude coordinate where claim was made (reduced precision ~1.1km for privacy compliance)
    Example: 2.18

  - `status` (string, required)
    Status of the claim processing (PENDING, PROCESSING, COMPLETED, FAILED)
    Enum: "PENDING", "PROCESSING", "COMPLETED", "FAILED"

  - `message` (string)
    Status or error message for the claim

  - `dataSource` (object)
    Analytics tracking: source/channel of this claim action
    Example: {"channel":"mobile","medium":"referral","campaign":"summer_promo"}

  - `included` (object)
    Included related entities. Only populated when include parameter is specified. Contains campaign, user, business, triggerSource, and/or transactions entities based on requested relations.

  - `included.campaign` (object)

  - `included.campaign.id` (string, required)
    Campaign id

  - `included.campaign.ownerBusinessId` (string, required)
    Optional owner business ID. If set, this campaign belongs to a specific business. If null, the campaign is tenant-owned (system-level).

  - `included.campaign.name` (string, required)
    Campaign name

  - `included.campaign.description` (string, required)
    Campaign description

  - `included.campaign.beneficiaryAccountAddress` (string, required)
    Campaign beneficiary account address

  - `included.campaign.startDate` (string, required)
    Campaign start date, default is the current date

  - `included.campaign.endDate` (string, required)
    Campaign end date

  - `included.campaign.imageUrl` (string, required)
    img url

  - `included.campaign.logoUrl` (string, required)
    Logo URL for the campaign

  - `included.campaign.externalUrl` (string, required)
    Campaign url

  - `included.campaign.isActive` (boolean, required)
    Campaign isActive

  - `included.campaign.approval` (object, required)
    Approval metadata for this campaign.

  - `included.campaign.approval.status` (string, required)
    Approval state: pending_approval = awaiting admin review, approved = active, rejected = denied.
    Enum: "pending_approval", "approved", "rejected"

  - `included.campaign.approval.approvedAt` (string)
    Timestamp when the entity was approved or rejected by an admin.

  - `included.campaign.approval.approvedBy` (string)
    Admin user ID who approved or rejected this entity.

  - `included.campaign.approval.rejectionReason` (string)
    Reason provided when the entity was rejected.

  - `included.campaign.isTestnet` (boolean)
    Campaign isTestnet, this means that the campaign is running on testnet, not mainnet

  - `included.campaign.createdAt` (string, required)
    create date

  - `included.campaign.updatedAt` (string, required)
    update date

  - `included.campaign.order` (number, required)
    Campaign order

  - `included.campaign.tags` (array, required)
    Campaign tags

  - `included.campaign.countryCodeRestrictions` (object)
    Country code restrictions as an array of strings (e.g., ["NOT_ES", "FR"])
    Example: ["NOT_ES","FR"]

  - `included.campaign.trigger` (object, required)
    Campaign trigger: what triggers the campaign, and what are the conditions for the trigger to be activated

  - `included.campaign.trigger.name` (number)
    Campaign trigger name

  - `included.campaign.trigger.description` (string)
    Campaign trigger description

  - `included.campaign.trigger.terms` (string)
    Terms and conditions for participation. Plain text or HTML. Multi-language handling at app level.

  - `included.campaign.trigger.maxPerDay` (number)
    DEPRECATED - use maxPerDayPerUser: Campaign trigger max per day

  - `included.campaign.trigger.maxPerDayPerUser` (number)
    Campaign trigger max per day per user

  - `included.campaign.trigger.maxPerUser` (number)
    Campaign trigger max per user

  - `included.campaign.trigger.minCooldownSeconds` (number)
    Campaign trigger min cooldown seconds

  - `included.campaign.trigger.maxGeoDistanceInMeters` (number)
    Campaign trigger max geo distance to Business in meters

  - `included.campaign.trigger.requiredUserInfo` (string)
    Campaign trigger required user info

  - `included.campaign.trigger.triggerType` (string)
    WHO can initiate a claim for this campaign.
**Values:**
- `CLAIM_BY_USER`: End users initiate claims (scan QR, tap NFC, enter geofence)
- `CLAIM_BY_BUSINESS`: Business claims on behalf of users (POS, kiosk, staff-assisted)
- `CLAIM_BY_SYSTEM`: Server/webhook automated claims (webhooks, scheduled jobs)

**Important:** This defines WHO can claim.
NOT to be confused with TriggerSource.type which defines HOW to claim (QR_CODE, NFC_TAG, GPS_GEOFENCE, etc.).
**App Logic:**
- If CLAIM_BY_USER: App shows claim UI based on triggerSources[].type
- If CLAIM_BY_BUSINESS: Requires business auth + userIdentifier in request
- If CLAIM_BY_SYSTEM: Server-to-server only, requires tenant API key
    Enum: "CLAIM_BY_USER", "CLAIM_BY_SYSTEM", "CLAIM_BY_BUSINESS"

  - `included.campaign.trigger.maxMultiplier` (number)
    Campaign trigger max multiplier

  - `included.campaign.trigger.completionThreshold` (number)
    Campaign trigger completion threshold. This indicates the number of completions required before the reward is granted

  - `included.campaign.trigger.maxTotal` (number)
    Campaign trigger max total completions across all users

  - `included.campaign.trigger.maxPerDayTotal` (number)
    Campaign trigger max total completions per day across all users

  - `included.campaign.trigger.maxPerSource` (number)
    Maximum claims per trigger source for this campaign. Limits how many times each individual trigger source can be used.

  - `included.campaign.trigger.conditions` (array)
    Campaign trigger conditions

  - `included.campaign.trigger.conditions.conditionType` (string, required)
    Trigger condition type
    Enum: "EQUALS", "NOT_EQUALS", "GREATER_THAN", "LESS_THAN", "CONTAINS", "IS_PART_OF"

  - `included.campaign.trigger.conditions.value` (object, required)
    Trigger condition value

  - `included.campaign.trigger.conditions.key` (string, required)
    Trigger condition key

  - `included.campaign.trigger.sourceLogic` (string)
    Source logic type defining how multiple trigger sources combine to activate the flow
    Enum: "any"

  - `included.campaign.trigger.id` (string, required)
    Campaign trigger id

  - `included.campaign.tokenUnits` (array, required)

  - `included.campaign.tokenUnits.id` (string, required)
    Database UUID for this token unit

  - `included.campaign.tokenUnits.token` (object, required)
    The token contract this unit references

  - `included.campaign.tokenUnits.token.id` (string, required)
    Database UUID for this token contract entity

  - `included.campaign.tokenUnits.token.contractAddress` (string, required)
    Smart contract address deployed on the blockchain

  - `included.campaign.tokenUnits.token.metadata` (array)
    Token metadata templates - blueprints used when minting NFTs. Each template defines properties (name, image, expiry) and has a unique tokenMetadataIncrementalId. Null for ERC20 (Points) tokens.

  - `included.campaign.tokenUnits.token.metadata.ownerBusinessId` (string)
    Optional owner business ID. If set, this token metadata belongs to a specific business. If null, the token metadata is tenant-owned (system-level).

  - `included.campaign.tokenUnits.token.metadata.isActive` (boolean)
    Whether this template is active and can be used for minting

  - `included.campaign.tokenUnits.token.metadata.imageUrl` (string)
    This is the URL to the image of the item. Can be just about any type of image (including SVGs, which will be cached into PNGs by OpenSea), IPFS or Arweave URLs or paths. We recommend using a minimum 3000 x 3000 image.

  - `included.campaign.tokenUnits.token.metadata.externalUrl` (string)
    This is the URL that will appear below the asset's image

  - `included.campaign.tokenUnits.token.metadata.description` (string)
    A human-readable description of the item. Markdown is supported.
**ERC721 Template Interpolation:** Supports `{{placeholder}}` syntax for dynamic personalization at mint time (without AI costs).
**Available placeholders:**
- `{{user.firstName}}`, `{{user.lastName}}` - User data
- `{{campaign.name}}`, `{{business.displayName}}` - Campaign/business
- `{{context.xxx}}` - Dynamic context values (TriggerSource.context or claim request)
- `{{defaults.xxx}}` - Default values from defaultPromptContext

**Example:** `"Thank you {{user.firstName}} for visiting {{business.displayName}}! Your exclusive reward for {{context.eventName}}."`
**Processing order:** Template interpolation runs first, then AI processing (if configured) can further enhance the result.

  - `included.campaign.tokenUnits.token.metadata.name` (string)
    Name of the item.
**ERC721 Template Interpolation:** Supports `{{placeholder}}` syntax for dynamic personalization at mint time (without AI costs).
**Available placeholders:**
- `{{user.firstName}}`, `{{user.lastName}}` - User data
- `{{campaign.name}}`, `{{business.displayName}}` - Campaign/business
- `{{context.xxx}}` - Dynamic context values (TriggerSource.context or claim request)
- `{{defaults.xxx}}` - Default values from defaultPromptContext

**Example:** `"Welcome {{context.guestName}} - VIP Pass"` or `"{{user.firstName}}'s {{campaign.name}} Reward"`
**Processing order:** Template interpolation runs first, then AI processing (if configured) can further enhance the result.

  - `included.campaign.tokenUnits.token.metadata.validityType` (string)
    **ERC721 only** - Validity type defines how token expiry is calculated. Use with validityDuration for relative types. Ignored for ERC1155 tokens.
    Enum: "fixed_date", "days_from_issuance", "hours_from_issuance", "months_from_issuance", "end_of_month", "end_of_year", "trigger_date", "trigger_date_range", "days_from_trigger", "hours_from_trigger"

  - `included.campaign.tokenUnits.token.metadata.validityDuration` (number)
    **ERC721 only** - Duration in days or hours (used with days_from_issuance, hours_from_issuance validity types). Ignored for ERC1155 tokens.
    Example: 30

  - `included.campaign.tokenUnits.token.metadata.expiryDate` (string)
    Fixed expiry date (used with fixed_date validity type). For other validity types, this is computed at issuance time.

  - `included.campaign.tokenUnits.token.metadata.animationUrl` (string)
    A URL to a multi-media attachment for the item. The file extensions GLTF, GLB, WEBM, MP4, M4V, OGV, and OGG are supported, along with the audio-only extensions MP3, WAV, and OGA. Animation_url also supports HTML pages, allowing you to build rich experiences and interactive NFTs using JavaScript canvas, WebGL, and more. Scripts and relative paths within the HTML page are now supported. However, access to browser extensions is not supported.

  - `included.campaign.tokenUnits.token.metadata.youtubeUrl` (string)
    A URL to a YouTube video (only used if animation_url is not provide

  - `included.campaign.tokenUnits.token.metadata.creatorAccountAddress` (string)
    Creator Address

  - `included.campaign.tokenUnits.token.metadata.previewUrl` (string)
    Preview Url

  - `included.campaign.tokenUnits.token.metadata.tags` (array)
    Tags for categorization and filtering
    Example: ["summer","vip","limited-edition"]

  - `included.campaign.tokenUnits.token.metadata.aiPromptConfigs` (array)
    **ERC721 only** - AI prompt configurations for dynamic content generation at mint time.
AI processing runs AFTER template interpolation, so prompts can reference already-interpolated values.
Results are mapped by key to override static fields (name, description, imageUrl). Ignored for ERC1155 tokens.
**Note:** For simple personalization without AI costs, use `{{placeholder}}` syntax directly in name/description fields instead.
    Example: [{"type":"TEXT_GENERATION","key":"name","prompt":"Generate a unique reward name for {{user.firstName}} at {{business.displayName}}"},{"type":"IMAGE_GENERATION","key":"imageUrl","prompt":"A {{defaults.…

  - `included.campaign.tokenUnits.token.metadata.allowExternalContextOverwrite` (boolean)
    **ERC721 only** - Allow USER-PROVIDED external context from claim/redeem requests to be used in template interpolation and AI prompts.
**Security model:**
- `false` (default): Only admin-controlled context (TriggerSource.context, Redemption.context, defaultPromptContext) is available
- `true`: User-provided context from API requests is also merged and available as `{{context.xxx}}`

**Note:** Admin-controlled context (QR/NFC data) is ALWAYS applied regardless of this flag.
    Example: true

  - `included.campaign.tokenUnits.token.metadata.defaultPromptContext` (object)
    **ERC721 only** - Default context values for template interpolation and AI prompts. Available as `{{defaults.xxx}}` placeholders.
Always applied regardless of allowExternalContextOverwrite. Use for brand defaults, styling preferences, or fallback values.
**Example usage in name:** `"{{defaults.brand}} - {{user.firstName}}'s Reward"`
    Example: {"brand":"PERS Rewards","style":"minimal","defaultLocation":"Online"}

  - `included.campaign.tokenUnits.token.metadata.businessIds` (array)
    Business IDs where this token can be redeemed/spent. Empty array means any business in the tenant.
    Example: ["business-uuid-1","business-uuid-2"]

  - `included.campaign.tokenUnits.token.metadata.webhookId` (string)
    **ERC721 only** - Webhook ID for dynamic data fetch at mint time.
If set, the webhook is executed before metadata generation and response data is merged into the NFT.
**Use cases:**
- Fetch guest data from PMS/CRM systems
- Get real-time pricing or availability
- Retrieve user-specific content from external APIs

**Processing order:** Webhook fetch runs AFTER template interpolation but BEFORE AI processing.
    Example: webhook-uuid-for-pms-lookup

  - `included.campaign.tokenUnits.token.metadata.webhookPayloadTemplate` (object)
    **ERC721 only** - Payload template for webhook request.
Supports `{{placeholder}}` interpolation with same context as AI prompts.
**Example:**

```json
{
  "userId": "{{user.id}}",
  "campaignId": "{{campaign.id}}",
  "bookingId": "{{context.bookingId}}"
}
```
    Example: {"userId":"{{user.id}}","bookingId":"{{context.bookingId}}"}

  - `included.campaign.tokenUnits.token.metadata.webhookFieldMapping` (object)
    **ERC721 only** - Field mapping from webhook response to metadata fields.
Keys are webhook response paths (dot notation for nested), values are target field names.
**Mapping rules:**
- Explicit mapping: `"response.path": "targetField"`
- Known fields (name, description, imageUrl): auto-mapped if present
- Unknown fields or `"attributes"` target: become NFT attributes

**Example:**

```json
{
  "guestName": "name",
  "data.guest.image": "imageUrl",
  "roomNumber": "attributes",
  "checkInDate": "attributes"
}
```
If null/undefined, uses auto-mapping.
    Example: {"guestName":"name","roomNumber":"attributes","data.image":"imageUrl"}

  - `included.campaign.tokenUnits.token.metadata.consumable` (boolean)
    Whether this token template is consumable (burned on redemption) or collectible (transferred). Applies to ERC1155 and ERC721 only — ERC20 is always transferred. When true, the token is destroyed (burn) when used as payment in a redemption. Defaults to true — most token templates are consumable. Set to false for collectible/non-burning use cases. Mirrored as a consumable attribute in the on-chain IPFS metadata.

  - `included.campaign.tokenUnits.token.metadata.id` (string, required)
    Database UUID for this token metadata template

  - `included.campaign.tokenUnits.token.metadata.animationWeb3StorageUrl` (string)
    IPFS/Arweave URL for animation file - immutable web3 storage

  - `included.campaign.tokenUnits.token.metadata.imageWeb3StorageUrl` (string)
    IPFS/Arweave URL for image - immutable web3 storage

  - `included.campaign.tokenUnits.token.metadata.web3StorageUrl` (string)
    IPFS/Arweave URL for complete metadata JSON - this URL is stored on-chain and links to off-chain metadata

  - `included.campaign.tokenUnits.token.metadata.tokenMetadataIncrementalId` (number, required)
    Incremental ID within the token contract. For ERC1155: becomes the on-chain tokenId. For ERC721: lookup key for template to generate unique metadata.

  - `included.campaign.tokenUnits.token.metadata.approval` (object, required)
    Approval metadata for this token metadata.

  - `included.campaign.tokenUnits.token.metadata.mintCount` (number)
    Total number of mints for this token metadata (via ?include=mintCount). Counts SUCCEEDED MINT transactions using tokenMetadataIncrementalId. Accurate for both ERC1155 and ERC721 (post v2.3.49). Historical ERC721 transactions before v2.3.49 are not counted.

  - `included.campaign.tokenUnits.token.metadata.burnCount` (number)
    Total number of burns for this token metadata (via ?include=burnCount). Counts SUCCEEDED BURN transactions using tokenMetadataIncrementalId. Accurate for both ERC1155 and ERC721 (post v2.3.49). Historical ERC721 transactions before v2.3.49 are not counted.

  - `included.campaign.tokenUnits.token.metadata.included` (object)
    Included related entities. Only populated when include parameter is specified.

  - `included.campaign.tokenUnits.token.metadata.included.ownerBusiness` (object)

  - `included.campaign.tokenUnits.token.metadata.included.token` (object)
    Parent token contract info (via ?include=token)

  - `included.campaign.tokenUnits.token.abi` (object, required)
    this is the abi of the contract, this is the interface of the contract to interact with it

  - `included.campaign.tokenUnits.token.chainId` (number, required)
    this is the chain id of the chain where the token is deployed

  - `included.campaign.tokenUnits.token.abiUrl` (string, required)
    this is the url of the abi of the contract, to be used to fetch the abi of the contract

  - `included.campaign.tokenUnits.token.name` (string)
    this is the name of the token contract

  - `included.campaign.tokenUnits.token.symbol` (string)
    this is the symbol of the token contract, this is optional and can be null

  - `included.campaign.tokenUnits.token.decimals` (number)
    this is the decimals of the token. This is optional and only used for ERC20 tokens (Points)

  - `included.campaign.tokenUnits.token.isActive` (boolean, required)
    This can be used to enable or disable the token

  - `included.campaign.tokenUnits.token.isGallery` (boolean, required)
    This can be used to enable or disable the token for gallery

  - `included.campaign.tokenUnits.token.type` (string, required)
    This is the underlying web3 native type of the token contract
    Enum: "ERC20", "ERC1155", "ERC721"

  - `included.campaign.tokenUnits.token.stampToken` (boolean, required)
    When true, this ERC1155 contract is used as a shared stamp contract. TokenMetadata entries are auto-provisioned per business and can be referenced in redemption priceTokenUnits with resolveByBusiness=true.

  - `included.campaign.tokenUnits.tokenMetadataIncrementalId` (number)
    Token metadata template ID. For ERC1155: becomes on-chain tokenId. For ERC721: lookup key for template to generate unique metadata.

  - `included.campaign.tokenUnits.amount` (number, required)
    Amount of tokens to mint/transfer. For ERC721 this is typically 1, for ERC1155/ERC20 can be any quantity.

  - `included.campaign.tokenUnits.maxAmount` (number)
    Token unit max amount. Applies to MINT/EARN contexts only (e.g. campaign reward capping where user earns tokens per revenue spent). Ignored for spend/transfer contexts such as redemption priceTokenUnits.

  - `included.campaign.businessEngagements` (array, required)

  - `included.campaign.businessEngagements.id` (string, required)
    id

  - `included.campaign.businessEngagements.shortDescription` (number, required)
    A short description of the business engagement with indications what to do etc

  - `included.campaign.businessEngagements.businessIds` (array, required)
    Business IDs associated with this engagement. Use CampaignDTO.included.businesses for full entities.

  - `included.campaign.businessEngagements.businesses` (array, required)
    Businesses (DEPRECATED: use businessIds + CampaignDTO.included.businesses instead. Will be removed in Q2 2026)
    Example: [{"id":"business-uuid-1"},{"id":"business-uuid-2"}]

  - `included.campaign.businessEngagements.campaignId` (string, required)
    Campaign id

  - `included.campaign.businessEngagements.maxPerBusiness` (number, required)
    max per business, the maximum number of times a user can engage with the buisness in the campaign

  - `included.campaign.businessEngagements.maxPerDay` (number, required)
    max per day, the maximum number of times a user can engage with the buisness in the campaign per day

  - `included.campaign.businessEngagements.externalUrl` (string, required)
    The external URL for the business engagement, e.g. a link to a website or app

  - `included.campaign.triggerSourceIds` (array, required)
    Trigger source IDs. Use to batch fetch or request via ?include=triggerSources
    Example: ["trigger-uuid-1","trigger-uuid-2"]

  - `included.campaign.included` (object)
    Included related data. Only populated when include parameter is specified.

  - `included.campaign.included.claimCount` (number)
    Total number of claims for this campaign (via ?include=claimCount)

  - `included.campaign.included.triggerSources` (array)
    Full trigger source entities (via ?include=triggerSources)

  - `included.campaign.included.triggerSources.type` (string, required)
    Type of trigger source - HOW to claim rewards.
**Available Types:**
- `QR_CODE`: Physical QR code scan. App opens camera, decodes QR, extracts triggerSourceId
- `NFC_TAG`: NFC tag tap. App activates NFC reader, reads tag data
- `GPS_GEOFENCE`: GPS-based geofence. App sends user coordinates for proximity validation
- `API_WEBHOOK`: Server-to-server webhook. External system triggers claim via API
- `TRANSACTION`: Purchase/transaction triggered. Claim activated by payment events

**Important:** This defines HOW claims are triggered (the touchpoint mechanism).
NOT to be confused with CampaignTriggerType which defines WHO can claim (CLAIM_BY_USER, CLAIM_BY_BUSINESS, CLAIM_BY_SYSTEM).
**App Integration:**

```typescript
const triggerTypes = campaign.included?.triggerSources?.map(ts => ts.type);
// Based on types, show appropriate UI (camera for QR, NFC prompt, location request, etc.)
```
    Enum: "QR_CODE", "NFC_TAG", "API_WEBHOOK", "GPS_GEOFENCE", "TRANSACTION"

  - `included.campaign.included.triggerSources.name` (string, required)
    Human-readable name for the trigger source
    Example: Main Entrance QR Code

  - `included.campaign.included.triggerSources.description` (number)
    Optional description explaining this trigger source
    Example: QR code located at the main entrance for visitor check-in

  - `included.campaign.included.triggerSources.context` (object)
    **ERC721 only** - Admin-controlled dynamic context for template interpolation and AI prompts. This data is ALWAYS applied (not subject to allowExternalContextOverwrite).
**Template Interpolation:** Values become available as `{{context.keyName}}` placeholders in TokenMetadata name/description fields and AI prompts.
**Special validity keys:**
- `validityDate` - Base date for trigger-based validity
- `validityEndDate` - End date for date ranges (e.g., hotel checkout)
- `validityDuration` - Override duration in days/hours

**Custom keys:** Any arbitrary key becomes `{{context.keyName}}` placeholder.
**Use cases:**
- QR at hotel room: `{ location: "Room 305", roomType: "Suite" }`
- NFC at event entrance: `{ eventName: "Summer Festival", zone: "VIP" }`
- Kiosk-specific: `{ deviceId: "kiosk-001", branch: "Downtown" }`
    Example: {"location":"Main Lobby","deviceId":"kiosk-001","validityDate":"2026-04-20T11:00:00Z"}

  - `included.campaign.included.triggerSources.maxUsage` (number)
    Maximum usage limit. null=unlimited, 1=single-use (receipt), 100=limited edition. Usage count calculated from claims via CQRS.
    Example: null

  - `included.campaign.included.triggerSources.businessId` (number)
    Reference to the business that owns this trigger source. Optional - can be tenant-wide trigger sources
    Example: business-uuid-123

  - `included.campaign.included.triggerSources.coordsLatitude` (number)
    Latitude. Geographic coordinates for location-based trigger validation.
**Universal Location Support:** ANY trigger type can use proximity validation (GPS_GEOFENCE, QR_CODE, NFC_TAG, API_WEBHOOK, TRANSACTION).
**Location Resolution Priority:**
1. TriggerSource coordinates (if set)
2. Business coordinates (if businessId exists)
3. Neither - No location validation

Distance constraints defined in CampaignTrigger.maxGeoDistanceInMeters. Both latitude and longitude must be provided together.
**Geocoding behavior:** Changing coords will auto-update address fields. To adjust pin position without changing address (e.g., parking entrance), set BOTH coordinates AND address fields in the same request.
    Example: 47.6062

  - `included.campaign.included.triggerSources.coordsLongitude` (number)
    Longitude. Geographic coordinates for location-based trigger validation.
**Universal Location Support:** ANY trigger type can use proximity validation (GPS_GEOFENCE, QR_CODE, NFC_TAG, API_WEBHOOK, TRANSACTION).
**Location Resolution Priority:**
1. TriggerSource coordinates (if set)
2. Business coordinates (if businessId exists)
3. Neither - No location validation

Distance constraints defined in CampaignTrigger.maxGeoDistanceInMeters. Both latitude and longitude must be provided together.
    Example: -122.3321

  - `included.campaign.included.triggerSources.streetAddress` (string)
    Street address (auto-populated from geocoding if coordinates provided)
    Example: 123 Main Street

  - `included.campaign.included.triggerSources.neighborhood` (string)
    Neighborhood/area name (e.g., "West Bay", "Pearl Qatar", "Lusail") - auto-populated from geocoding
    Example: West Bay

  - `included.campaign.included.triggerSources.district` (string)
    District/administrative area - auto-populated from geocoding
    Example: Doha Municipality

  - `included.campaign.included.triggerSources.city` (string)
    City. Auto-populated from geocoding if only coordinates provided. **Geocoding behavior:** Changing address fields will auto-update coordinates. To adjust pin without changing address, set BOTH coords AND address fields.
    Example: Doha

  - `included.campaign.included.triggerSources.postalCode` (string)
    Postal code (auto-populated from geocoding if coordinates provided)
    Example: 12345

  - `included.campaign.included.triggerSources.country` (string)
    Country (auto-populated from geocoding if coordinates provided)
    Example: Qatar

  - `included.campaign.included.triggerSources.countryCode` (string)
    ISO 3166-1 alpha-2 country code (auto-populated from geocoding)
    Example: QA

  - `included.campaign.included.triggerSources.id` (string, required)
    Unique identifier for the trigger source
    Example: source-12345

  - `included.campaign.included.triggerSources.isActive` (boolean, required)
    Whether this trigger source is currently active. Inactive sources won't trigger any flows
    Example: true

  - `included.campaign.included.triggerSources.isExhausted` (boolean, required)
    Whether this trigger source has been exhausted (agotado). Set via CQRS when claim count reaches maxUsage.

  - `included.campaign.included.triggerSources.createdAt` (object, required)
    Timestamp when the trigger source was created
    Example: 2024-01-01T12:00:00.000Z

  - `included.campaign.included.triggerSources.updatedAt` (object, required)
    Timestamp when the trigger source was last updated
    Example: 2024-01-10T12:00:00.000Z

  - `included.campaign.included.businesses` (array)
    Full business entities for all businessEngagements (via ?include=businesses)

  - `included.user` (object)

  - `included.user.id` (string, required)

  - `included.user.email` (string)

  - `included.user.identifierEmail` (string, required)
    Universal identifier email for deterministic operations. Generated from B2B inputs (email, externalId) for wallet salt generation and external integrations.
    Example: user123@user.pers.internal

  - `included.user.firstName` (string, required)
    User first name

  - `included.user.lastName` (string, required)
    User last name

  - `included.user.externalId` (string, required)
    User external id

  - `included.user.accountAddress` (string, required)
    User account address

  - `included.user.instagramAccountId` (string, required)
    Instagram account id

  - `included.user.googleAccountName` (string, required)
    Google account name

  - `included.user.customData` (object, required)
    Custom data

  - `included.user.publicProfile` (object, required)
    Public profile data

  - `included.user.isActive` (boolean, required)
    Is active

  - `included.user.currentSigningAccountId` (string)
    Current active signing account ID for external wallet operations

  - `included.user.wallets` (array, required)
    User-owned counterfactual smart contract wallets that can receive tokens

  - `included.user.wallets.id` (string, required)
    Unique identifier for the internal wallet

  - `included.user.wallets.ownerType` (string, required)
    Owner type for polymorphic ownership
    Enum: "user", "business", "tenant", "system", "external"

  - `included.user.wallets.ownerId` (string, required)
    Owner ID for polymorphic ownership
    Example: user_123

  - `included.user.wallets.walletManagementType` (string, required)
    Type of internal wallet
    Enum: "custodial", "non-custodial"

  - `included.user.wallets.address` (string, required)
    CREATE2 generated address that can receive tokens

  - `included.user.wallets.chainId` (number, required)
    Blockchain network chain identifier

  - `included.user.wallets.status` (string, required)
    Current status of the wallet
    Enum: "pending", "active", "suspended", "archived"

  - `included.user.wallets.ownerSigningAccountId` (string)
    ID of signing account that owns this internal wallet

  - `included.user.wallets.tags` (array, required)
    Tags associated with the wallet for categorization

  - `included.user.wallets.createdAt` (string, required)
    Timestamp when the wallet was created

  - `included.user.wallets.updatedAt` (string, required)
    Timestamp when the wallet was last updated

  - `included.user.createdAt` (string, required)
    Timestamp when the user was created

  - `included.user.updatedAt` (string, required)
    Timestamp when the user was last updated

  - `included.user.registrationSource` (object)
    Registration source tracking for analytics - captures channel and attribution when user was created
    Example: {"channel":"web","medium":"referral","campaign":"launch_2026"}

  - `included.user.lastActivityAt` (string)
    Last activity timestamp. Updated whenever user generates tokens (login or refresh). Tracks last time user was active (~1 hour precision).

  - `included.user.activityCount` (number)
    Total activity count. Increments on every token generation (login + refresh). Measures true user engagement.
    Example: 42

  - `included.user.included` (object)
    Included related entities. Only populated when include parameter is specified.

  - `included.user.included.statusTypes` (array)
    User status types earned based on token balances (via ?include=status)

  - `included.user.included.statusTypes.name` (string, required)
    User Status Type name

  - `included.user.included.statusTypes.description` (string)
    User Status Type description

  - `included.user.included.statusTypes.minTokenBalance` (string, required)
    User Status Type eligible Token Addresses

  - `included.user.included.statusTypes.discountPercentage` (number, required)
    User Status Type discount Rate in percentage

  - `included.user.included.statusTypes.imageUrl` (string)
    User Status Type image Url

  - `included.user.included.statusTypes.eligibleTokenAddresses` (array)
    Eligible token contract addresses for this status type
    Example: ["0x1234...","0x5678..."]

  - `included.user.included.statusTypes.tags` (array)
    Tags for categorization and filtering
    Example: ["vip","premium","gold"]

  - `included.user.included.statusTypes.order` (number)
    Explicit ordering for status hierarchy (higher = more prestigious). If not set, falls back to minTokenBalance for ordering.
    Example: 100

  - `included.user.included.statusTypes.id` (number, required)
    User Status Type id

  - `included.user.included.tokenBalances` (array)
    Token balances for user wallets (via ?include=balances)

  - `included.user.included.tokenBalances.accountAddress` (string, required)

  - `included.user.included.tokenBalances.tokenBalances` (array, required)

  - `included.user.included.tokenBalances.tokenBalances.contractAddress` (string, required)

  - `included.user.included.tokenBalances.tokenBalances.chainId` (number, required)

  - `included.user.included.tokenBalances.tokenBalances.balance` (number, required)

  - `included.user.included.tokenBalances.tokenBalances.tokenName` (string)

  - `included.user.included.tokenBalances.tokenBalances.tokenSymbol` (string)

  - `included.user.included.tokenBalances.tokenBalances.tokenType` (string, required)

  - `included.user.included.tokenBalances.tokenBalances.tokenId` (string, required)

  - `included.user.included.tokenBalances.tokenBalances.metadataUri` (string, required)

  - `included.user.included.tokenBalances.tokenBalances.metadata` (object, required)
    Token metadata (loaded from IPFS/storage when needed for filtering)

  - `included.transactions` (array)
    Included transaction entities created for this claim

  - `included.transactions.amount` (string, required)
    Transaction amount

  - `included.transactions.id` (string, required)
    Transaction id

  - `included.transactions.tokenAddress` (string, required)
    Transaction token address

  - `included.transactions.contractTokenId` (string, required)
    Transaction token contract id, this is the blockchain contract id of the token

  - `included.transactions.tokenType` (string, required)
    Transaction token type

  - `included.transactions.senderAddress` (string, required)
    Sender address

  - `included.transactions.recipientAddress` (string, required)
    Recipient address

  - `included.transactions.transactionHash` (string, required)
    Transaction hash

  - `included.transactions.type` (string, required)
    Transaction type
    Enum: "MINT", "TRANSFER", "BURN"

  - `included.transactions.triggerProcessType` (string, required)
    Trigger process type
    Enum: "PURCHASE", "SPEND", "TRANSFER", "EARN", "CAMPAIGN_USER_CLAIM", "CAMPAIGN_SYSTEM_CLAIM", "CAMPAIGN_BUSINESS_CLAIM", "REDEMPTION_SPEND", "REDEMPTION_RECEIVE", "REDEMPTION_PRICE_TOKEN_TRANSFER", "MIGRATION", "ADMIN_TRIGGERED", "BUSINESS_TRIGGERED"

  - `included.transactions.triggerProcessId` (string, required)
    Trigger process id, this is the id of the entity that triggered the transaction if applicable (e.g. CampaignUserClaim id)

  - `included.transactions.status` (string, required)
    Transaction status
    Enum: "created", "processing", "pending_signature", "pending_submission", "broadcasted", "succeeded", "failed", "cancelled", "expired"

  - `included.transactions.createdAt` (string, required)
    Transaction creation timestamp

  - `included.transactions.updatedAt` (string, required)
    Transaction last update timestamp

  - `included.transactions.tenantId` (string, required)
    Tenant ID for multi-tenant isolation

  - `included.transactions.chainId` (number, required)
    Blockchain chain ID

  - `included.transactions.senderId` (string, required)
    Sender entity ID (polymorphic reference)

  - `included.transactions.senderOwnerType` (string, required)
    Sender entity type (user, business, system etc.)
    Enum: "user", "business", "tenant", "system", "external"

  - `included.transactions.recipientId` (string, required)
    Recipient entity ID (polymorphic reference)

  - `included.transactions.recipientOwnerType` (string, required)
    Recipient entity type (user, Business, system, etc.)
    Enum: "user", "business", "tenant", "system", "external"

  - `included.transactions.message` (string, required)
    Optional message associated with the transaction, e.g. for error details

  - `included.transactions.engagedBusinessId` (string, required)
    Business commercially involved in this transaction (for stats/reporting)

  - `included.transactions.authorizedSubmitterId` (string, required)
    Entity authorized to submit this transaction (for POS flow security)

  - `included.transactions.authorizedSubmitterType` (string, required)
    Type of entity authorized to submit (USER, BUSINESS, etc.)
    Enum: "user", "business", "tenant", "system", "external"

  - `included.transactions.userCountryCode` (string, required)
    ISO 3166-1 alpha-2 country code derived from IP geolocation

  - `included.transactions.anonymizedIpAddress` (string, required)
    Anonymized IP address (last octet zeroed for privacy)

  - `included.transactions.metadataUri` (string, required)
    IPFS/storage URL for token metadata. For ERC721: unique URI per minted token. For ERC1155: shared URI per token type. Example: ipfs://Qm.../metadata.json
    Example: ipfs://QmXyz123.../metadata.json

  - `included.transactions.tokenMetadataIncrementalId` (number, required)
    Token metadata template ID - stable reference for mint/burn counting. For ERC1155: same as on-chain tokenId. For ERC721: template lookup key (preserved since on-chain ID differs).

  - `included.transactions.issuanceMode` (string)
    Economic issuance mechanism for reward transactions. TENANT_DELEGATED_MINT: master wallet mints. BUSINESS_OWNED_MINT: business owns the token contract. BUSINESS_BALANCE_TRANSFER: business transfers from own wallet balance. Null for non-reward or legacy transactions.
    Enum: "TENANT_DELEGATED_MINT", "BUSINESS_OWNED_MINT", "BUSINESS_BALANCE_TRANSFER"

  - `included.transactions.included` (object)
    Included related entities. Only populated when include parameter is specified. Contains sender, recipient, and/or engaged business entities based on requested relations.

  - `included.transactions.included.sender` (any)
    Included sender entity (User or Business)

  - `included.transactions.included.recipient` (any)
    Included recipient entity (User or Business)

