Skip to content

Create trigger source

Request

Create a new trigger source (QR code, NFC tag, webhook, geofence, etc.). Businesses create trigger sources owned by themselves; tenant admins can create shared (tenant-level) trigger sources.

Security
authJWT
Bodyapplication/jsonrequired
typestringrequired

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:

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"
Example:"QR_CODE"
namestringrequired

Human-readable name for the trigger source

Example:"Main Entrance QR Code"
descriptionnumber or null

Optional description explaining this trigger source

Example:"QR code located at the main entrance for visitor check-in"
metadataobject

Type-specific configuration: tokenConfig (override token ID). See TriggerSourceMetadata interface.

Example:
{ "tokenConfig": { "tokenId": "1" } }
contextobject

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" }
maxUsagenumber or null

Maximum usage limit. null=unlimited, 1=single-use (receipt), 100=limited edition. When usage reaches maxUsage, trigger becomes exhausted.

Default:null
Example:1
businessIdnumber or null

Reference to the business that owns this trigger source. Optional - can be tenant-wide trigger sources

Example:"business-uuid-123"
coordsLatitudenumber or null

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
coordsLongitudenumber or null

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
streetAddressstring or null

Street address (auto-populated from geocoding if coordinates provided)

Example:"123 Main Street"
neighborhoodstring or null

Neighborhood/area name (e.g., "West Bay", "Pearl Qatar", "Lusail") - auto-populated from geocoding

Example:"West Bay"
districtstring or null

District/administrative area - auto-populated from geocoding

Example:"Doha Municipality"
citystring or null

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"
postalCodestring or null

Postal code (auto-populated from geocoding if coordinates provided)

Example:"12345"
countrystring or null

Country (auto-populated from geocoding if coordinates provided)

Example:"Qatar"
countryCodestring or null

ISO 3166-1 alpha-2 country code (auto-populated from geocoding)

Example:"QA"
curl -i -X POST \
  https://docs.pers.ninja/_mock/swagger/trigger-sources \
  -H 'Authorization: Bearer <YOUR_JWT_HERE>' \
  -H 'Content-Type: application/json' \
  -d '{
    "type": "QR_CODE",
    "name": "Main Entrance QR Code",
    "description": "QR code located at the main entrance for visitor check-in",
    "metadata": {
      "tokenConfig": {
        "tokenId": "1"
      }
    },
    "context": {
      "location": "Main Lobby",
      "deviceId": "kiosk-001",
      "validityDate": "2026-04-20T11:00:00Z"
    },
    "maxUsage": 1,
    "businessId": "business-uuid-123",
    "coordsLatitude": 47.6062,
    "coordsLongitude": -122.3321,
    "streetAddress": "123 Main Street",
    "neighborhood": "West Bay",
    "district": "Doha Municipality",
    "city": "Doha",
    "postalCode": "12345",
    "country": "Qatar",
    "countryCode": "QA"
  }'

Responses

Trigger source created successfully

Bodyapplication/json
typestringrequired

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:

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"
Example:"QR_CODE"
namestringrequired

Human-readable name for the trigger source

Example:"Main Entrance QR Code"
descriptionnumber or null

Optional description explaining this trigger source

Example:"QR code located at the main entrance for visitor check-in"
metadataobject

Type-specific configuration: tokenConfig (override token ID). See TriggerSourceMetadata interface.

Example:
{ "tokenConfig": { "tokenId": "1" } }
contextobject

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" }
maxUsagenumber or null

Maximum usage limit. null=unlimited, 1=single-use (receipt), 100=limited edition. Usage count calculated from claims via CQRS.

Default:null
Example:null
businessIdnumber or null

Reference to the business that owns this trigger source. Optional - can be tenant-wide trigger sources

Example:"business-uuid-123"
coordsLatitudenumber or null

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
coordsLongitudenumber or null

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
streetAddressstring or null

Street address (auto-populated from geocoding if coordinates provided)

Example:"123 Main Street"
neighborhoodstring or null

Neighborhood/area name (e.g., "West Bay", "Pearl Qatar", "Lusail") - auto-populated from geocoding

Example:"West Bay"
districtstring or null

District/administrative area - auto-populated from geocoding

Example:"Doha Municipality"
citystring or null

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"
postalCodestring or null

Postal code (auto-populated from geocoding if coordinates provided)

Example:"12345"
countrystring or null

Country (auto-populated from geocoding if coordinates provided)

Example:"Qatar"
countryCodestring or null

ISO 3166-1 alpha-2 country code (auto-populated from geocoding)

Example:"QA"
idstringrequired

Unique identifier for the trigger source

Example:"source-12345"
isActivebooleanrequired

Whether this trigger source is currently active. Inactive sources won't trigger any flows

Example:true
isExhaustedbooleanrequired

Whether this trigger source has been exhausted (agotado). Set via CQRS when claim count reaches maxUsage.

Default:false
createdAtobjectrequired

Timestamp when the trigger source was created

Example:"2024-01-01T12:00:00.000Z"
updatedAtobjectrequired

Timestamp when the trigger source was last updated

Example:"2024-01-10T12:00:00.000Z"
Response
{ "type": "QR_CODE", "name": "Main Entrance QR Code", "description": "QR code located at the main entrance for visitor check-in", "metadata": { "tokenConfig": {} }, "context": { "location": "Main Lobby", "deviceId": "kiosk-001", "validityDate": "2026-04-20T11:00:00Z" }, "maxUsage": null, "businessId": "business-uuid-123", "coordsLatitude": 47.6062, "coordsLongitude": -122.3321, "streetAddress": "123 Main Street", "neighborhood": "West Bay", "district": "Doha Municipality", "city": "Doha", "postalCode": "12345", "country": "Qatar", "countryCode": "QA", "id": "source-12345", "isActive": true, "isExhausted": false, "createdAt": "2024-01-01T12:00:00.000Z", "updatedAt": "2024-01-10T12:00:00.000Z" }