# PERS-api Documentation


**PERS API Documentation**

This RESTful API enables seamless integration of Web3 loyalty, token management, and engagement features into your applications.

**Usage Guidelines:**
- **RESTful Design**: Resources are accessed via standard HTTP methods (GET, POST, PUT, DELETE) with predictable, resource-oriented URLs.
- **Authentication**: Secure access is enforced via Bearer Tokens (JWT) and Project Keys (defining the Tenant context).
- **Data Format**: All requests and responses utilize standard JSON formatting.

Explore the modules below for detailed endpoint specifications, schemas, and testing capabilities.


---

### Error Handling

All API errors follow RFC 7807 (Problem Details for HTTP APIs) with a `StructuredError` schema. See the **Schemas** section below for the full structure.


Version: 2.0.35

## Servers

```
https://api.pers.ninja/v2
```

## Security

### authJWT

Authentication JWT token for user/business/admin/system access

Type: http
Scheme: bearer
Bearer Format: JWT

### projectKey

Project API key

Type: apiKey
In: header
Name: x-project-key

## Download OpenAPI description

[PERS-api Documentation](https://docs.pers.ninja/_bundle/swagger.yaml)

## Tenants

## Tenant Management
    <div style="font-size: 14px; line-height: 1.5;">
      Tenant management for multi-tenant PERS loyalty platform. Each tenant represents a business or organization running their own reward program with dedicated data isolation and configuration.
    </div>
    <b>Core Features:</b>
    <br/>•<b>Multi-Tenant Architecture:</b> Complete data isolation between tenant organizations
    <br/>•<b>Tenant Configuration:</b> Custom settings, branding, and program rules per tenant  
    <br/>•<b>Admin Dashboard Access:</b> Comprehensive management interface for tenant administrators
    <br/>•<b>Data Security:</b> Highest level confidentiality and security per tenant environment
    <br/>•<b>API Integration:</b> Seamless integration with existing business systems

### Create new tenant

 - [POST /tenants](https://docs.pers.ninja/swagger/tenants/tenantscontroller_createtenant.md): Create a new tenant (project) in the system. This is the initial setup step for new organizations.

### Update tenant configuration

 - [PUT /tenants](https://docs.pers.ninja/swagger/tenants/tenantscontroller_updatetenant.md): ADMIN: Update tenant information and settings

### Get client configuration

 - [GET /tenants/client-config](https://docs.pers.ninja/swagger/tenants/tenantscontroller_getclientconfig.md): Retrieve client-side configuration for the project

### Get login token

 - [GET /tenants/login-token](https://docs.pers.ninja/swagger/tenants/tenantscontroller_getlogintoken.md): Generate a login token for the project

### Get current tenant information

 - [GET /tenants/me](https://docs.pers.ninja/swagger/tenants/tenantscontroller_getcurrenttenant.md): Context-aware endpoint for retrieving your own tenant information.
        
        REQUIREMENTS:
        - Header: x-project-key (project identification)
        - Optional: Authorization Bearer token (for full access)
        
        RETURNS:
        - With API Key only: Public tenant information
        - With Tenant JWT: Full tenant information including allowedTokenIssuers and sensitive config

### Get tenant information by ID

 - [GET /tenants/{id}](https://docs.pers.ninja/swagger/tenants/tenantscontroller_gettenantbyid.md): Context-aware tenant information retrieval:
        
        UNAUTHENTICATED ACCESS:
        - No headers required
        - Returns: Basic public tenant information

## Admins

## Administrative Management
    <div style="font-size: 14px; line-height: 1.5;">
      Administrative user management for tenant administrators. Handles admin authentication, permissions, and tenant-level administrative operations with secure access controls.
    </div>
    <b>Admin Features:</b>
    <br/>• <b>Admin Authentication:</b> Secure admin login and session management
    <br/>• <b>Permission Management:</b> Role-based access control for administrative functions
    <br/>• <b>Tenant Administration:</b> Full tenant configuration and management capabilities
    <br/>• <b>Security Controls:</b> Enhanced security measures for administrative access
    <br/>• <b>Multi-Level Access:</b> Support for different administrative privilege levels

### Get current admin profile

 - [GET /admins/me](https://docs.pers.ninja/swagger/admins/adminscontroller_getcurrentadmin.md): ADMIN: Retrieve the currently authenticated admin profile

### Get all admins

 - [GET /admins](https://docs.pers.ninja/swagger/admins/adminscontroller_getadmins.md): ADMIN: Retrieve all admins associated with the current tenant. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future).

### Create or update admin

 - [POST /admins](https://docs.pers.ninja/swagger/admins/adminscontroller_createorupdateadmin.md): ADMIN: Create a new admin or update an existing admin within the tenant scope

### Toggle admin-tenant association

 - [PUT /admins/{adminId}/tenant](https://docs.pers.ninja/swagger/admins/adminscontroller_toggleadmintenantassociation.md): ADMIN: Associate or disassociate the specified admin with the current tenant. This affects admin tenant access.

## Tokens

## Token Management System
    <div style="font-size: 14px; line-height: 1.5;">
      Token system for PERS loyalty platform managing various token types including Credits, Rewards, and Status tokens. Provides comprehensive token lifecycle management from creation to redemption.
    </div>
    <b>Token Operations:</b>
    <br/>• <b>Token Creation:</b> Define custom token types with specific properties and rules
    <br/>• <b>Token Distribution:</b> Mint and distribute tokens to users through campaigns
    <br/>• <b>Balance Management:</b> Track token balances across user accounts  
    <br/>• <b>Token Transfer:</b> Enable token transfers between users when configured
    <br/>• <b>Token Burning:</b> Remove tokens from circulation for deflationary mechanics
    <br/><img src="https://s3.eu-west-1.amazonaws.com/pers.assets.prod/tenant/a0df6ebf-51cc-4c18-afcd-0de355c250dc_DemoApp_eXplorins/Documentation/Tokens_image.png" alt="Token Module" width="400" style="margin-top: 10px;"/>

### Get all token contracts

 - [GET /tokens](https://docs.pers.ninja/swagger/tokens/tokenscontroller_getalltokens.md): Retrieve all token contracts for the project. Only admins can access inactive tokens via ?active=false parameter. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future).

### Create new token contract

 - [POST /tokens](https://docs.pers.ninja/swagger/tokens/tokenscontroller_createtoken.md): ADMIN: Create a new testnet token contract for the project. This can later be converted to mainnet.

### Get token by contract address

 - [GET /tokens/address/{contractAddress}](https://docs.pers.ninja/swagger/tokens/tokenscontroller_gettokenbyaddress.md): Retrieve token information by contract address

### Get active point token

 - [GET /tokens/points](https://docs.pers.ninja/swagger/tokens/tokenscontroller_getactivepointtoken.md): Retrieve the active point token contract for the project

### Get all reward tokens

 - [GET /tokens/rewards](https://docs.pers.ninja/swagger/tokens/tokenscontroller_getrewardtokens.md): Retrieve all reward token contracts (ERC1155 tokens). Only admins can access inactive tokens via ?active=false parameter. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future).

### Get all stamp tokens

 - [GET /tokens/stamps](https://docs.pers.ninja/swagger/tokens/tokenscontroller_getstamptokens.md): Retrieve all stamp token contracts (ERC721 tokens). Only admins can access inactive tokens via ?active=false parameter. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future).

### Get all token types

 - [GET /tokens/types](https://docs.pers.ninja/swagger/tokens/tokenscontroller_getalltokentypes.md): Retrieve all available token types for the project. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future).

### Create new token type

 - [POST /tokens/types](https://docs.pers.ninja/swagger/tokens/tokenscontroller_createtokentype.md): ADMIN: Create a new token type for the project

### Get all token metadata

 - [GET /tokens/metadata](https://docs.pers.ninja/swagger/tokens/tokenscontroller_getalltokenmetadata.md): Retrieve all token metadata with filtering and pagination. Useful for displaying rewards/stamps in tables. Non-admin users always get active metadata only.

### Export token metadata as CSV (Admin)

 - [GET /tokens/metadata/export/csv](https://docs.pers.ninja/swagger/tokens/tokenscontroller_exporttokenmetadataascsv.md): Export all token metadata to CSV format with optional date filtering.

### Update token contract

 - [PUT /tokens/{id}](https://docs.pers.ninja/swagger/tokens/tokenscontroller_updatetoken.md): ADMIN: Update token contract information

### Toggle token active status

 - [PUT /tokens/{id}/status](https://docs.pers.ninja/swagger/tokens/tokenscontroller_toggletokenstatus.md): ADMIN: Toggle token active status to enable/disable usage

### Set mainnet contract address

 - [PUT /tokens/{id}/mainnet](https://docs.pers.ninja/swagger/tokens/tokenscontroller_setmainnetcontract.md): ADMIN: Associate mainnet contract address with existing testnet token

### Create token metadata

 - [POST /tokens/{id}/metadata](https://docs.pers.ninja/swagger/tokens/tokenscontroller_createtokenmetadata.md): ADMIN: Create metadata for a specific token contract

### Update token metadata

 - [PUT /tokens/metadata/{metadataId}](https://docs.pers.ninja/swagger/tokens/tokenscontroller_updatetokenmetadata.md): Update metadata for a specific token. Business can only update their own metadata. ERC721: only affects future mints. ERC1155: ⚠️ updates ALL existing minted tokens.

### Delete token metadata (soft delete)

 - [DELETE /tokens/metadata/{metadataId}](https://docs.pers.ninja/swagger/tokens/tokenscontroller_deletetokenmetadata.md): Soft delete token metadata. Business can only delete their own metadata. Returns 409 Conflict if metadata is used by active campaigns or redemptions.

### Toggle token metadata status

 - [PUT /tokens/metadata/{metadataId}/status](https://docs.pers.ninja/swagger/tokens/tokenscontroller_toggletokenmetadatastatus.md): ADMIN/BUSINESS: Toggle token metadata active status. Business can only toggle their own metadata.

### Approve or reject a token metadata (Admin)

 - [PATCH /tokens/metadata/{metadataId}/approval](https://docs.pers.ninja/swagger/tokens/tokenscontroller_approveorrejecttokenmetadata.md): Sets approval status to approved or rejected. Rejected requires a reason.

## Campaigns

## Core Campaign Management
    <div style="font-size: 14px; line-height: 1.5;">
      Core campaign CRUD operations with intelligent access detection. Handles campaign lifecycle management including creation, updates, activation, and querying with role-based access control.
    </div>
    <b>Campaign Operations:</b>
    <br/>• <b>Campaign Discovery:</b> Public browsing of active campaigns without authentication
    <br/>• <b>Advanced Filtering:</b> Query campaigns by tags, status, and custom criteria
    <br/>• <b>Lifecycle Management:</b> Full campaign CRUD with proper state transitions
    <br/>• <b>Environment Control:</b> Toggle campaigns between testnet and mainnet modes
    <br/>• <b>Access Intelligence:</b> Automatic privilege detection for appropriate data exposure
    <br/><img src="https://s3.eu-west-1.amazonaws.com/pers.assets.prod/tenant/a0df6ebf-51cc-4c18-afcd-0de355c250dc_DemoApp_eXplorins/Documentation/Campaign_image.png" alt="Campaign Module" width="400" style="margin-top: 10px;"/>

### Get campaigns (Intelligent Access)

 - [GET /campaigns](https://docs.pers.ninja/swagger/campaigns/campaignscontroller_getcampaigns.md): Endpoint that adapts based on authentication: Public users get active campaigns with filtering, Business users get all campaigns (active+inactive) for their business only, Admin users get all campaigns with full filtering. Use pagination parameters (page & limit) for optimal performance - critical for large campaign datasets. Legacy support: returns array without params (deprecated - will be removed in future). Replaces GET /campaign and GET /campaign/admin

### Create campaign (Admin)

 - [POST /campaigns](https://docs.pers.ninja/swagger/campaigns/campaignscontroller_createcampaign.md): Create a new campaign. Admin-only operation. Replaces POST /campaign/admin/

### Get campaign by ID

 - [GET /campaigns/{id}](https://docs.pers.ninja/swagger/campaigns/campaignscontroller_getcampaignbyid.md): Get single campaign details by ID. Available to public with project key. Replaces GET /campaign/{id}

### Update campaign

 - [PUT /campaigns/{id}](https://docs.pers.ninja/swagger/campaigns/campaignscontroller_updatecampaign.md): Update an existing campaign. Business can only update their own campaigns.

### Delete campaign

 - [DELETE /campaigns/{id}](https://docs.pers.ninja/swagger/campaigns/campaignscontroller_deletecampaign.md): Delete an existing campaign. Business can only delete their own campaigns.

### Toggle campaign status

 - [PUT /campaigns/{id}/status](https://docs.pers.ninja/swagger/campaigns/campaignscontroller_togglecampaignstatus.md): Toggle campaign active/inactive status. Business can only toggle their own campaigns.

### Toggle campaign environment (Admin)

 - [PUT /campaigns/{id}/environment](https://docs.pers.ninja/swagger/campaigns/campaignscontroller_togglecampaignenvironment.md): Toggle campaign between testnet and mainnet environment. Admin-only operation. Replaces PUT /campaign/admin/{id}/environment

### Assign trigger source to campaign (Admin)

 - [PUT /campaigns/{id}/trigger-sources/{triggerSourceId}](https://docs.pers.ninja/swagger/campaigns/campaignscontroller_assigntriggersourcetocampaign.md): Assign a trigger source to a specific campaign. Admin-only operation.

### Remove trigger source from campaign (Admin)

 - [DELETE /campaigns/{id}/trigger-sources/{triggerSourceId}](https://docs.pers.ninja/swagger/campaigns/campaignscontroller_removetriggersourcefromcampaign.md): Remove a trigger source assignment from a specific campaign. Admin-only operation.

### Export campaigns as CSV (Admin)

 - [GET /campaigns/export/csv](https://docs.pers.ninja/swagger/campaigns/campaignscontroller_exportcampaignsascsv.md): Export all campaigns to CSV format with optional date filtering.

### Approve or reject a campaign (Admin)

 - [PATCH /campaigns/{id}/approval](https://docs.pers.ninja/swagger/campaigns/campaignscontroller_approveorrejectcampaign.md): Sets approval status to approved or rejected. Rejected requires a reason.

## Campaign Tags

## Campaign Organization System  
    <div style="font-size: 14px; line-height: 1.5;">
      Campaign tagging system for organization and categorization. Enables efficient campaign discovery through tag-based filtering and provides comprehensive tag management.
    </div>
    <b>Tag Management:</b>
    <br/>• <b>Tag Discovery:</b> Browse all unique tags across campaign catalog  
    <br/>• <b>Campaign Tagging:</b> Associate multiple descriptive tags with campaigns
    <br/>• <b>Tag-Based Filtering:</b> Enhanced campaign search and discovery via tags
    <br/>• <b>Tag Administration:</b> Complete tag CRUD operations for administrators
    <br/>• <b>Organization Tools:</b> Categorize campaigns by business criteria and themes

### Get all unique campaign tags (Admin)

 - [GET /campaigns/{campaignId}/tags](https://docs.pers.ninja/swagger/campaign-tags/campaigntagscontroller_getalluniquetags.md): Get all unique tags used across all campaigns. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future). Admin-only operation for tag management. Set campaignId to "all" to retrieve tags from all campaigns.

### Update campaign tags (Admin)

 - [PUT /campaigns/{campaignId}/tags](https://docs.pers.ninja/swagger/campaign-tags/campaigntagscontroller_updatecampaigntags.md): Replace all tags for a campaign with new tag list. Admin-only operation. Replaces PUT /campaign/admin/{id}/tags

### Add tags to campaign (Admin)

 - [POST /campaigns/{campaignId}/tags](https://docs.pers.ninja/swagger/campaign-tags/campaigntagscontroller_addtagstocampaign.md): Add new tags to existing campaign tags without removing existing ones. Admin-only operation. Replaces POST /campaign/admin/{id}/tags

### Remove tag from campaign (Admin)

 - [DELETE /campaigns/{campaignId}/tags/{tag}](https://docs.pers.ninja/swagger/campaign-tags/campaigntagscontroller_removetagfromcampaign.md): Remove a specific tag from campaign while preserving other tags. Admin-only operation. Replaces DELETE /campaign/admin/{id}/tags/{tag}

## Campaign Tokens

## Campaign Reward Configuration
    <div style="font-size: 14px; line-height: 1.5;">
      Token unit management for campaign reward distribution. Defines specific token rewards that users receive when campaign participation conditions are met.
    </div>
    <b>Reward Configuration:</b>
    <br/>• <b>Token Association:</b> Link specific token types and amounts to campaigns
    <br/>• <b>Reward Rules:</b> Define token distribution rules and conditions
    <br/>• <b>Multi-Token Support:</b> Configure multiple token types per campaign
    <br/>• <b>Reward Calculation:</b> Set fixed or variable token amounts based on actions
    <br/>• <b>Distribution Management:</b> Control how and when tokens are distributed to users

### Create campaign token unit (Admin)

 - [POST /campaigns/{campaignId}/tokens](https://docs.pers.ninja/swagger/campaign-tokens/campaigntokenscontroller_createcampaigntokenunit.md): Add a new token unit to campaign for reward distribution. Admin-only operation. Replaces POST /campaign/admin/{id}/token-units

### Update campaign token unit (Admin)

 - [PUT /campaigns/{campaignId}/tokens/{tokenUnitId}](https://docs.pers.ninja/swagger/campaign-tokens/campaigntokenscontroller_updatecampaigntokenunit.md): Update an existing token unit in campaign. Admin-only operation. Replaces PUT /campaign/admin/{id}/token-units/{tokenUnitId}

### Remove campaign token unit (Admin)

 - [DELETE /campaigns/{campaignId}/tokens/{tokenUnitId}](https://docs.pers.ninja/swagger/campaign-tokens/campaigntokenscontroller_removecampaigntokenunit.md): Remove a token unit from campaign. Admin-only operation. Replaces DELETE /campaign/admin/{id}/token-units/{tokenUnitId}

## Campaign Triggers

## Campaign Activation System
    <div style="font-size: 14px; line-height: 1.5;">
      Campaign trigger system managing activation rules and eligibility conditions. Defines when and how campaigns activate including complex condition management for sophisticated campaign logic.
    </div>
    <b>Trigger Features:</b>
    <br/>• <b>Trigger Catalog:</b> Public browsing of available campaign activation triggers
    <br/>• <b>Condition Management:</b> Create complex trigger conditions with multiple criteria  
    <br/>• <b>Campaign Assignment:</b> Link triggers to campaigns for automated activation
    <br/>• <b>Eligibility Rules:</b> Define sophisticated user participation requirements
    <br/>• <b>Event-Based Activation:</b> Trigger campaigns based on user actions and external events

### Get all triggers (Public Catalog)

 - [GET /campaign-triggers](https://docs.pers.ninja/swagger/campaign-triggers/campaigntriggerscontroller_getalltriggers.md): Get all available triggers for campaign configuration. Public access for catalog browsing. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future). Replaces GET /campaign/trigger/all

### Create campaign trigger (Admin)

 - [POST /campaign-triggers](https://docs.pers.ninja/swagger/campaign-triggers/campaigntriggerscontroller_createcampaigntrigger.md): Create a new campaign trigger for use in campaigns. Admin-only operation. Replaces POST /campaign/admin/trigger

### Get trigger by ID

 - [GET /campaign-triggers/{triggerId}](https://docs.pers.ninja/swagger/campaign-triggers/campaigntriggerscontroller_gettriggerbyid.md): Get a specific campaign trigger by ID. Useful for dashboard selection and preview.

### Update campaign trigger (Admin)

 - [PUT /campaign-triggers/{triggerId}](https://docs.pers.ninja/swagger/campaign-triggers/campaigntriggerscontroller_updatecampaigntrigger.md): Update an existing campaign trigger. Admin-only operation. Replaces PUT /campaign/admin/trigger/{id}

### Delete campaign trigger (Admin)

 - [DELETE /campaign-triggers/{triggerId}](https://docs.pers.ninja/swagger/campaign-triggers/campaigntriggerscontroller_deletecampaigntrigger.md): Delete an existing campaign trigger. Admin-only operation. Replaces DELETE /campaign/admin/trigger/{id}

### Assign trigger to campaign (Admin)

 - [PUT /campaign-triggers/{triggerId}/assign/{campaignId}](https://docs.pers.ninja/swagger/campaign-triggers/campaigntriggerscontroller_assigntriggertocampaign.md): Assign a trigger to a specific campaign for activation conditions. Admin-only operation. Replaces PUT /campaign/admin/{id}/trigger/{triggerId}

### Remove trigger from campaign (Admin)

 - [DELETE /campaign-triggers/{triggerId}/assign/{campaignId}](https://docs.pers.ninja/swagger/campaign-triggers/campaigntriggerscontroller_removetriggerfromcampaign.md): Remove a trigger assignment from a specific campaign. Admin-only operation.

### Toggle condition in trigger (Admin)

 - [PUT /campaign-triggers/{triggerId}/conditions](https://docs.pers.ninja/swagger/campaign-triggers/campaigntriggerscontroller_toggleconditionintrigger.md): Add or remove a condition from a trigger (toggle relationship). Admin-only operation. Replaces PUT /campaign/admin/trigger/{triggerId}/condition/{conditionId}

## Campaign Engagements

## Business Relationship Management
    <div style="font-size: 14px; line-height: 1.5;">
      B2B engagement management for multi-business campaign relationships. Handles business partnerships and enterprise-level campaign participation in complex loyalty ecosystems.
    </div>
    <b>B2B Features:</b>
    <br/>• <b>Partner Integration:</b> Manage business-to-business campaign relationships  
    <br/>• <b>Enterprise Programs:</b> Support complex multi-business loyalty initiatives
    <br/>• <b>Engagement Tracking:</b> Monitor business participation and performance metrics
    <br/>• <b>Partnership Management:</b> Configure B2B reward sharing and attribution
    <br/>• <b>Cross-Business Rewards:</b> Enable rewards that span multiple business partners

### Create business engagement for campaign (Admin)

 - [POST /campaigns/{campaignId}/engagements](https://docs.pers.ninja/swagger/campaign-engagements/campaignengagementscontroller_createbusinessengagementforcampaign.md): Add a business engagement relationship to campaign for business-specific rewards. Admin-only operation. Replaces POST /campaign/admin/{id}/business-engagement

### Update business engagement in campaign (Admin)

 - [PUT /campaigns/{campaignId}/engagements/{businessEngagementId}](https://docs.pers.ninja/swagger/campaign-engagements/campaignengagementscontroller_updatebusinessengagementincampaign.md): Update an existing business engagement relationship in campaign. Admin-only operation. Replaces PUT /campaign/admin/{id}/business-engagement/{businessEngagementId}

### Remove business engagement from campaign (Admin)

 - [DELETE /campaigns/{campaignId}/engagements/{businessEngagementId}](https://docs.pers.ninja/swagger/campaign-engagements/campaignengagementscontroller_removebusinessengagementfromcampaign.md): Remove a business engagement relationship from campaign. Admin-only operation. Replaces DELETE /campaign/admin/{id}/business-engagement/{businessEngagementId}

## Campaign Claims

## Reward Claims Processing
    <div style="font-size: 14px; line-height: 1.5;">
      Multi-level reward claim processing with comprehensive security features and audit trails. Handles reward distribution with full security features.
    </div>
    <b>Security Features:</b>
    <br/>• <b>Multi-Level Access:</b> USER, BUSINESS, SYSTEM, ADMIN claim processing levels
    <br/>• <b>Security Monitoring:</b> IP tracking and behavioral analysis for security
    <br/>• <b>Audit Tracking:</b> Complete transaction history and activity logs  
    <br/>• <b>Context Attribution:</b> User and business context preservation for tracking
    <br/>• <b>Claim Verification:</b> Multi-step verification process for high-value rewards
    <br/>
    <b>Access Levels:</b>
    <br/>• <b>USER:</b> Direct customer reward claims with user authentication
    <br/>• <b>BUSINESS:</b> B2B reward processing with business context attribution  
    <br/>• <b>SYSTEM:</b> Automated claims processing via secure API integration
    <br/>• <b>ADMIN:</b> Complete administrative oversight and manual claim processing

### Create campaign claim

 - [POST /campaigns/claims](https://docs.pers.ninja/swagger/campaign-claims/campaignclaimscontroller_createcampaignclaim.md): Process campaign reward claims using role-based detection.

Understanding Campaign Claim Flow:

1. WHO can claim (campaign.trigger.triggerType):
   - CLAIM_BY_USER: End users initiate claims (scan QR, tap NFC, enter geofence)
   - CLAIM_BY_BUSINESS: Business claims on behalf of users (POS, kiosk)
   - CLAIM_BY_SYSTEM: Server/webhook automated claims

2. HOW to claim (campaign.triggerSources[].type):
   - QR_CODE: User scans QR code → App extracts triggerSourceId
   - NFC_TAG: User taps NFC tag → App reads triggerSourceId
   - GPS_GEOFENCE: User enters location → App sends lat/lng
   - API_WEBHOOK: External system triggers via API
   - TRANSACTION: Purchase event triggers claim

Request Body Fields:
- triggerSourceId (preferred): The specific trigger source ID from QR/NFC/etc
- campaignId (legacy, deprecated): Will be removed Q2 2026
- latitude/longitude: Required for GPS_GEOFENCE or distance-validated claims
- userIdentifier: Email/external ID for business/system claims
- userInfo: Additional user data if required by campaign
- metadata: Custom claim data
- multiplier: Reward multiplier (default: 1.0)
- context: Dynamic context for ERC721 token personalization (see below)

ERC721 Dynamic Context & Template Interpolation:

For ERC721 tokens, you can provide a context object whose values become available as {{context.xxx}} placeholders in the token's name/description and AI prompts.

Context sources (merge order):
1. TokenMetadata.defaultPromptContext → {{defaults.xxx}}
2. TriggerSource.context (admin QR/NFC) → {{context.xxx}} (always applied)
3. CampaignClaimRequest.context (this field) → {{context.xxx}} (only if allowExternalContextOverwrite=true)

Example - Hotel check-in:
json
{
  "triggerSourceId": "room-305-qr-uuid",
  "context": {
    "guestName": "María García",
    "roomNumber": "305",
    "validityEndDate": "2026-04-20T11:00:00Z"
  }
}

With TokenMetadata name: "Welcome {{context.guestName}} - Room {{context.roomNumber}}"
Result: "Welcome María García - Room 305"

App Integration Example:
typescript
// 1. Get campaign with trigger sources
const campaign = await getActiveCampaigns({ include: ['triggerSources'] });

// 2. Determine claim method
const triggerTypes = campaign.included?.triggerSources?.map(ts => ts.type);
// → ['QR_CODE', 'NFC_TAG']

// 3. Based on type, show appropriate UI and call claim
if (triggerTypes.includes('QR_CODE')) {
  // Open camera, scan QR, extract triggerSourceId
  claimCampaign({ triggerSourceId: 'scanned-id' });
}

### Get campaign claims with advanced filtering

 - [GET /campaigns/claims](https://docs.pers.ninja/swagger/campaign-claims/campaignclaimscontroller_getcampaignclaims.md): Get campaign claims with comprehensive filtering options. Use pagination parameters (page & limit) for optimal performance - critical for high-volume campaigns. Legacy support: returns array without params (deprecated - will be removed in future).
    - campaignId: Filter by specific campaign (optional)
    - userId: Filter by specific user ID (admin only)
    - businessId: Filter by specific business ID (admin only)
    - include: Optionally include related entities (campaign, user, business, transactions)
    
    Access Control:
    - Users: See only their own claims, campaignId optional
    - Business: See only claims associated with their business account, campaignId optional
    - Admin: Can filter by any combination of parameters or see all claims
    
    Security Notes:
    - Users cannot access userId or businessId parameters (automatically filtered)
    - Business accounts automatically filter to their own businessId regardless of parameter
    - Admin has full access to all filtering options

### Get my campaign claims (Convenience)

 - [GET /campaigns/claims/me](https://docs.pers.ninja/swagger/campaign-claims/campaignclaimscontroller_getmycampaignclaims.md): 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)

### Export campaign claims as CSV (Admin)

 - [GET /campaigns/claims/export/csv](https://docs.pers.ninja/swagger/campaign-claims/campaignclaimscontroller_exportclaimsascsv.md): Export all campaign claims to CSV format with optional filtering.

## Redemptions

## Token Exchange System
    <div style="font-size: 14px; line-height: 1.5;">
      Token exchange system facilitating conversion between different token types and redemption for rewards. Provides flexible reward experiences through diverse redemption options.
    </div>
    <b>Redemption Features:</b>
    <br/>• <b>Token Exchange:</b> Convert between different token types with exchange rates
    <br/>• <b>Reward Catalog:</b> Browse available rewards for token redemption
    <br/>• <b>Exchange Rules:</b> Configure conversion rates and redemption requirements  
    <br/>• <b>Partner Ecosystem:</b> Redemption options across business partner networks
    <br/>• <b>Flexible Rewards:</b> Support for products, services, and digital rewards
    <br/><img src="https://s3.eu-west-1.amazonaws.com/pers.assets.prod/tenant/a0df6ebf-51cc-4c18-afcd-0de355c250dc_DemoApp_eXplorins/Documentation/Redemption_image.png" alt="Redemption Module" width="400" style="margin-top: 10px;"/>

### Get redemption by ID

 - [GET /redemptions/{id}](https://docs.pers.ninja/swagger/redemptions/redemptionscontroller_getredemptionbyid.md): Get specific redemption details by ID. Requires valid project API key. Include missingUserFields to check which required fields the authenticated user is missing.

### Update redemption

 - [PUT /redemptions/{id}](https://docs.pers.ninja/swagger/redemptions/redemptionscontroller_updateredemption.md): Update existing redemption. Business can only update their own redemptions.

### Delete redemption

 - [DELETE /redemptions/{id}](https://docs.pers.ninja/swagger/redemptions/redemptionscontroller_deleteredemption.md): Permanently delete a redemption. Business can only delete their own redemptions.

### Get redemption available supply

 - [GET /redemptions/{id}/supply](https://docs.pers.ninja/swagger/redemptions/redemptionscontroller_getavailablesupply.md): Get the available supply count for a specific redemption. Used for inventory display.

### Get redemptions (Intelligent Access)

 - [GET /redemptions](https://docs.pers.ninja/swagger/redemptions/redemptionscontroller_getredemptions.md): Intelligent endpoint that adapts based on authentication: Public users get active redemptions only, Admin users get all redemptions with optional filtering. Consolidates GET /redemption and GET /redemption/admin. Use pagination parameters (page & limit) for optimal performance - critical for large datasets. Legacy support: returns array without params (deprecated - will be removed in future).

### Create redemption (Admin)

 - [POST /redemptions](https://docs.pers.ninja/swagger/redemptions/redemptionscontroller_createredemption.md): Create a new redemption with administrative privileges. Replaces POST /redemption/admin

### Toggle redemption status

 - [PUT /redemptions/{id}/status](https://docs.pers.ninja/swagger/redemptions/redemptionscontroller_toggleredemptionstatus.md): Toggle redemption between active and inactive status. Business can only toggle their own redemptions.

### Export redemptions to CSV

 - [GET /redemptions/export/csv](https://docs.pers.ninja/swagger/redemptions/redemptionscontroller_exportredemptionscsv.md): Export all redemptions as a CSV file. Supports date filtering.

### Approve or reject a redemption (Admin)

 - [PATCH /redemptions/{id}/approval](https://docs.pers.ninja/swagger/redemptions/redemptionscontroller_approveorrejectredemption.md): Sets approval status to approved or rejected. Rejected requires a reason.

## Purchases

## Payment Processing System
    <div style="font-size: 14px; line-height: 1.5;">
      Secure payment processing for account balance top-ups through credit card payments. Provides secure financial transactions for premium features and account funding within the loyalty ecosystem.
    </div>
    <b>Payment Features:</b>
    <br/>• <b>Secure Payments:</b> Credit card processing with industry-standard security
    <br/>• <b>Balance Top-Up:</b> Add funds to user accounts for premium features
    <br/>• <b>Payment Methods:</b> Support for multiple payment providers and methods
    <br/>• <b>Transaction Security:</b> Encrypted payment data and fraud protection
    <br/>• <b>Account Integration:</b> Seamless integration with token and reward systems
    <br/><img src="https://s3.eu-west-1.amazonaws.com/pers.assets.prod/tenant/a0df6ebf-51cc-4c18-afcd-0de355c250dc_DemoApp_eXplorins/Documentation/Purchase_image.png" alt="Purchase Module" width="400" style="margin-top: 10px;"/>

### Stripe payment webhook (Critical)

 - [POST /purchases/webhooks/stripe](https://docs.pers.ninja/swagger/purchases/purchasescontroller_handlestripewebhook.md): Handles Stripe payment events for financial reconciliation. CRITICAL: Do not modify without extensive testing. Replaces POST /purchase/stripe-webhook

### Get purchase tokens (Intelligent Access)

 - [GET /purchases/tokens](https://docs.pers.ninja/swagger/purchases/purchasescontroller_getpurchasetokens.md): Intelligent endpoint that adapts based on authentication. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future). Public users get active tokens only, Admin users get filtered tokens. Replaces GET /purchase/token

### Create purchase token (Admin)

 - [POST /purchases/tokens](https://docs.pers.ninja/swagger/purchases/purchasescontroller_createpurchasetoken.md): Create a new purchase token for the product catalog. Admin-only operation. Replaces POST /purchase/admin/token

### Get donation types

 - [GET /purchases/donation-types](https://docs.pers.ninja/swagger/purchases/purchasescontroller_getdonationtypes.md): Get all available donation types for public catalog browsing. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future). Requires valid project API key. Replaces GET /purchase/donation/type

### Create donation type (Admin)

 - [POST /purchases/donation-types](https://docs.pers.ninja/swagger/purchases/purchasescontroller_createdonationtype.md): Create a new donation type for system configuration. Admin-only operation. Replaces POST /purchase/admin/donation/type

### Create payment intent (Financial)

 - [POST /purchases/payment-intents](https://docs.pers.ninja/swagger/purchases/purchasescontroller_createpaymentintent.md): Create a new Stripe payment intent for purchase processing. Requires tenant context for Stripe API key. FINANCIAL OPERATION - handle with care. Replaces POST /purchase/payment-intent

### Update payment intent (Financial)

 - [PUT /purchases/payment-intents/{paymentIntentId}](https://docs.pers.ninja/swagger/purchases/purchasescontroller_updatepaymentintent.md): Update an existing Stripe payment intent. Requires tenant context for Stripe API key. FINANCIAL OPERATION - handle with care. Replaces PUT /purchase/payment-intent/{paymentIntentId}

### Cancel payment intent (Financial)

 - [DELETE /purchases/payment-intents/{paymentIntentId}](https://docs.pers.ninja/swagger/purchases/purchasescontroller_cancelpaymentintent.md): Cancel an existing Stripe payment intent. Requires tenant context for Stripe API key. FINANCIAL OPERATION - handle with care. Replaces DELETE /purchase/payment-intent/{paymentIntentId}

### Create user purchase (Financial Transaction)

 - [POST /purchases](https://docs.pers.ninja/swagger/purchases/purchasescontroller_createuserpurchase.md): Create a new purchase for the authenticated user. BUSINESS CRITICAL - handles real financial transactions with Stripe integration. Requires user and tenant context. Replaces POST /purchase/auth

### Get user purchase history

 - [GET /purchases/me](https://docs.pers.ninja/swagger/purchases/purchasescontroller_getuserpurchasehistory.md): Get all purchases made by the authenticated user. Use pagination parameters (page & limit) for optimal performance - recommended for users with many purchases. Legacy support: returns array without params (deprecated - will be removed in future).

### Export purchases as CSV (Admin)

 - [GET /purchases/export/csv](https://docs.pers.ninja/swagger/purchases/purchasescontroller_exporttocsv.md): Export all purchases as a CSV file. Supports date filtering.

### Update purchase token (Admin)

 - [PUT /purchases/tokens/{id}](https://docs.pers.ninja/swagger/purchases/purchasescontroller_updatepurchasetoken.md): Update an existing purchase token in the product catalog. Admin-only operation. Replaces PUT /purchase/admin/token/{id}

### Delete purchase token (Admin)

 - [DELETE /purchases/tokens/{id}](https://docs.pers.ninja/swagger/purchases/purchasescontroller_deletepurchasetoken.md): Delete an existing purchase token from the product catalog. Admin-only operation. Replaces DELETE /purchase/admin/token/{id}

### Create purchase type (Admin)

 - [POST /purchases/types](https://docs.pers.ninja/swagger/purchases/purchasescontroller_createpurchasetype.md): Create a new purchase type for system configuration. Admin-only operation. Replaces POST /purchase/admin/type

## Businesses

## Partner Ecosystem Management
    <div style="font-size: 14px; line-height: 1.5;">
      Business partner management for multi-stakeholder loyalty programs. Handles partner onboarding, collaboration frameworks, and performance tracking within the reward ecosystem.
    </div>
    <b>Partner Management:</b>
    <br/>• <b>Partner Onboarding:</b> Register and configure business partners in the ecosystem
    <br/>• <b>Collaboration Tools:</b> Facilitate joint campaigns and cross-partner rewards
    <br/>• <b>Performance Analytics:</b> Track partner engagement and contribution metrics  
    <br/>• <b>Incentive Structures:</b> Configure partner-specific reward and commission models
    <br/>• <b>Community Building:</b> Foster collaborative relationships between ecosystem partners

### Get current business info

 - [GET /businesses/me](https://docs.pers.ninja/swagger/businesses/businessescontroller_getcurrentbusiness.md): Get business info with current token balances (business authentication required)

### Get all businesses

 - [GET /businesses](https://docs.pers.ninja/swagger/businesses/businessescontroller_getallbusinesses.md): Get all businesses. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future). Project API key users get active businesses only. Admin users (with valid JWT) get full access with query parameters.

### Create a new business

 - [POST /businesses](https://docs.pers.ninja/swagger/businesses/businessescontroller_createbusiness.md): Create a new business account, will be inactive until activated by admin

### Get business by account address

 - [GET /businesses/account/{accountAddress}](https://docs.pers.ninja/swagger/businesses/businessescontroller_getbyaccountaddress.md): Get business info by account address

### Get business by ID

 - [GET /businesses/{id}](https://docs.pers.ninja/swagger/businesses/businessescontroller_getbyid.md): Get business info by ID

### Update a business

 - [PUT /businesses/{id}](https://docs.pers.ninja/swagger/businesses/businessescontroller_updatebusiness.md): Update a business account. Business tokens may only update their own business.

### Create multiple businesses

 - [POST /businesses/bulk](https://docs.pers.ninja/swagger/businesses/businessescontroller_createbusinessesbulk.md): Create multiple business accounts from a JSON array in the request body.

### Create multiple businesses from URL

 - [POST /businesses/bulk/url](https://docs.pers.ninja/swagger/businesses/businessescontroller_createbusinessesfromurl.md): Create multiple business accounts by fetching a JSON file from the provided URL. The file at the URL is expected to be a JSON object conforming to the BusinessBulkCreateRequestDTO structure, containing an array of business data.

### Toggle business status

 - [PUT /businesses/{id}/status](https://docs.pers.ninja/swagger/businesses/businessescontroller_togglebusinessstatus.md): Toggle business active status. Business owners can toggle isActive only; capability flags (canMintToken etc) require tenant admin.

### List business members

 - [GET /businesses/{businessId}/members](https://docs.pers.ninja/swagger/businesses/businessescontroller_getbusinessmembers.md): Get all members of a business. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future). Requires BUSINESS auth (min role: VIEWER) or TENANT admin.

### Add member to business

 - [POST /businesses/{businessId}/members](https://docs.pers.ninja/swagger/businesses/businessescontroller_addbusinessmember.md): Add a user as a member of the business. Requires BUSINESS auth (min role: ADMIN) or TENANT admin.

### Update member role

 - [PUT /businesses/{businessId}/members/{userId}](https://docs.pers.ninja/swagger/businesses/businessescontroller_updatememberrole.md): Update the role of an existing business member. Requires BUSINESS auth (min role: ADMIN) or TENANT admin.

### Remove member from business

 - [DELETE /businesses/{businessId}/members/{userId}](https://docs.pers.ninja/swagger/businesses/businessescontroller_removebusinessmember.md): Remove a user from business membership. Requires BUSINESS auth (min role: ADMIN) or TENANT admin.

### Export businesses as CSV (Admin)

 - [GET /businesses/export/csv](https://docs.pers.ninja/swagger/businesses/businessescontroller_exportbusinessesascsv.md): Export all businesses to CSV format with optional date filtering.

### Approve or reject a business (Admin)

 - [PATCH /businesses/{id}/approval](https://docs.pers.ninja/swagger/businesses/businessescontroller_approveorrejectbusiness.md): Sets approval status to approved or rejected. Rejected requires a reason.

## Transactions

## Transaction Management System  
    <div style="font-size: 14px; line-height: 1.5;">
      Comprehensive transaction management for credits and tokens with secure processing and real-time balance updates. Handles all operations within the loyalty platform.
    </div>
    <b>Transaction Operations:</b>
    <br/>• <b>Token Minting:</b> Create new tokens and add to user accounts
    <br/>• <b>Token Transfers:</b> Secure peer-to-peer token transfers between users
    <br/>• <b>Token Burning:</b> Remove tokens from circulation with proper audit trails
    <br/>• <b>Balance Queries:</b> Real-time balance checks across multiple token types  
    <br/>• <b>Transaction Authorization:</b> Verify user permissions and sufficient balances
    <br/>• <b>Transaction History:</b> Complete audit logs for all operations

### Get current user/business transactions

 - [GET /transactions/me](https://docs.pers.ninja/swagger/transactions/transactionscontroller_getcurrentusertransactions.md): Consolidated endpoint for user/business transactions. Use role parameter to filter: SENDER (sent), RECIPIENT (received), or omit for all transactions. Use include parameter to enrich with full entity data. Always returns PaginatedResponseDTO.

### Get all transactions with advanced filtering

 - [GET /transactions](https://docs.pers.ninja/swagger/transactions/transactionscontroller_getalltransactions.md): Get transactions with comprehensive filtering options:
        - include: Enrich with full entity data (sender, recipient, business)
        - search: Wildcard search for ID, address or transaction hash
        - participantId: Filter by user/business/tenant ID
        - role: Filter by SENDER, RECIPIENT, or both (omit for all)
        - status: Filter by transaction status
        - tokenType: Filter by token type
        - type: Filter by transaction type (MINT, BURN, TRANSFER)
        - Always returns PaginatedResponseDTO

### Create transaction

 - [POST /transactions](https://docs.pers.ninja/swagger/transactions/transactionscontroller_createsystemtransaction.md): Create any type of transaction (MINT/TRANSFER/BURN) using role-based trigger detection.

Sender resolution — sender field is optional:
If sender is omitted, it defaults to the authenticated caller:
- Business JWT → sender = your business ({ accountId: , accountType: "business" })
- User JWT → sender = your user
- Tenant/admin JWT → sender = the tenant

So a business that wants to send from itself can simply omit sender and only provide recipient + amount.

> Business "pull from user" rule: When a business initiates a transfer where the sender is a user
> (not the business itself), the points may only be received by that same authenticated business:
> - The business must have canChargeToken = true, otherwise the request is rejected (403).
> - recipient omitted → automatically set to the authenticated business (convenience for POS/redeem flows).
> - recipient explicitly set to the business → allowed.
> - recipient explicitly set to anyone else → rejected (403). A business cannot route a user's points to a third party.
>
> This rule only applies when the business is pulling from a user. When the business is the sender
> (rewarding / sending its own points), recipient is required and may be any valid account.

> Note: If sender is provided, the value is used as-is (no override). The create call does not
> reject a mismatched sender.accountId, but the transaction cannot actually settle from an account the
> caller does not control: signing/submission enforce custody ownership downstream (a business must be the
> sender or engaged business to sign; the sender's custodial wallet is required to submit). Prefer omitting
> sender when acting as yourself.

Token resolution — token field is optional:
If token is omitted, the server automatically resolves the active credit token for the tenant.
This works for all sender types (user, business, tenant).

> Production recommendation: Always specify token explicitly using contractAddress + chainId.
> The fallback is safe as long as there is exactly one active credit token per tenant (the standard setup),
> but omitting it makes the intent implicit and harder to debug. If a second credit token were ever
> activated, the fallback would silently pick one with no error.

ERC721 MINT with Dynamic Context:
For ERC721 mints, you can provide a context object for template interpolation and AI prompts.
Values become available as {{context.xxx}} placeholders in TokenMetadata name/description.

Example — minimal credit transfer (token omitted, fallback applies):
json
{
  "web3TransactionType": "TRANSFER",
  "sender":    { "accountId": "user-uuid",     "accountType": "user" },
  "recipient": { "accountId": "business-uuid", "accountType": "business" },
  "amount": 100
}


Example — explicit token (recommended for production):
json
{
  "web3TransactionType": "TRANSFER",
  "sender":    { "accountId": "user-uuid",     "accountType": "user" },
  "recipient": { "accountId": "business-uuid", "accountType": "business" },
  "token":     { "contractAddress": "0x...", "chainId": 39123 },
  "amount": 100
}


Example — ERC721 MINT with dynamic context:
json
{
  "web3TransactionType": "MINT",
  "recipient": { "accountId": "user-uuid", "accountType": "user" },
  "token": { "tokenEntityId": "token-uuid" },
  "amount": 1,
  "context": {
    "awardReason": "Employee of the Month",
    "recipientName": "John Smith"
  }
}


Depending on transaction type and signing context, returns prepared transaction for client-side signing or executes server-side directly.

### Get transaction by ID

 - [GET /transactions/{id}](https://docs.pers.ninja/swagger/transactions/transactionscontroller_gettransactionbyid.md): Get single transaction by ID with optional entity inclusion. Use include parameter to enrich with full entity data. Requires valid project API key.

### Prepare existing transaction for client-side signing

 - [GET /transactions/{id}/prepare](https://docs.pers.ninja/swagger/transactions/transactionscontroller_preparetransactionbyid.md): Prepares transaction data for client-side execution from existing transaction ID. Returns the data needed for the client to sign and submit the transaction.

### Sign transaction and return signature only (no submission)

 - [POST /transactions/{id}/sign](https://docs.pers.ninja/swagger/transactions/transactionscontroller_signtransactiononly.md): Signs a custodial EIP-712 transaction and returns the signature without submitting to the blockchain. Use this for business interface flows where the signature is displayed/scanned and submitted separately.

### Submit client-side signed transaction

 - [POST /transactions/submit](https://docs.pers.ninja/swagger/transactions/transactionscontroller_submittransaction.md): Submits a signed transaction from the client. This method is used to finalize the transaction after the client has signed it.

### Export transactions as CSV with business names

 - [GET /transactions/export/csv](https://docs.pers.ninja/swagger/transactions/transactionscontroller_exporttransactionsascsv.md): Downloads transactions as CSV with business names resolved. Supports filtering by date range and status. Includes engagedBusinessName column for easy analysis. RLS ensures tenant isolation automatically.

## Users

## User Account Management
    <div style="font-size: 14px; line-height: 1.5;">
      User account management and profile operations for loyalty platform participants. Handles user registration, authentication, profile management, and account lifecycle.
    </div>
    <b>User Operations:</b>
    <br/>• <b>Account Registration:</b> User signup and profile creation with verification
    <br/>• <b>Authentication:</b> Secure login and session management  
    <br/>• <b>Profile Management:</b> User profile updates and preference configuration
    <br/>• <b>Account Security:</b> Password management and two-factor authentication
    <br/>• <b>Privacy Controls:</b> Data management and privacy settings for users

### Get current user info

 - [GET /users/me](https://docs.pers.ninja/swagger/users/userscontroller_getcurrentuser.md): Get authenticated user account info. Use include=status,balances to include related data. Note: Including status/balances adds latency - consider separate calls for performance-critical scenarios. Wallets include virtual counterfactual addresses for chains with active tokens.

### Update current user

 - [PUT /users/me](https://docs.pers.ninja/swagger/users/userscontroller_updatecurrentuser.md): Update authenticated user account

### Get current user status

 - [GET /users/me/status](https://docs.pers.ninja/swagger/users/userscontroller_getcurrentuserstatus.md): Get authenticated user status types. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future).

### Check if user exists

 - [GET /users/exists](https://docs.pers.ninja/swagger/users/userscontroller_checkuserexists.md): Check if a user exists using any identifier field (id, email, etc.)

### Get all public profiles

 - [GET /users/public](https://docs.pers.ninja/swagger/users/userscontroller_getallpublicprofiles.md): Get all public user profiles. Use pagination parameters (page & limit) for optimal performance - essential for large user bases. Legacy support: returns array without params (deprecated - will be removed in future).

### Get public profile

 - [GET /users/public/{id}](https://docs.pers.ninja/swagger/users/userscontroller_getpublicprofile.md): Get a public profile by user ID

### Get all user status types

 - [GET /users/status-types](https://docs.pers.ninja/swagger/users/userscontroller_getalluserstatustypes.md): Get all available user status types. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future).

### Create user status type

 - [POST /users/status-types](https://docs.pers.ninja/swagger/users/userscontroller_createuserstatustype.md): Create user status type as admin

### Get user status type

 - [GET /users/status-types/{id}](https://docs.pers.ninja/swagger/users/userscontroller_getuserstatustype.md): Get a user status type by ID

### Update user status type

 - [PUT /users/status-types/{id}](https://docs.pers.ninja/swagger/users/userscontroller_updateuserstatustype.md): Update user status type as admin

### Delete user status type

 - [DELETE /users/status-types/{id}](https://docs.pers.ninja/swagger/users/userscontroller_deleteuserstatustype.md): Delete user status type as admin

### Update eligible token for status type

 - [PUT /users/status-types/{id}/eligible-tokens/{tokenAddress}](https://docs.pers.ninja/swagger/users/userscontroller_updateuserstatustypeeligibletoken.md): Add or remove eligible token for user status type as admin

### Get user info

 - [POST /users/info](https://docs.pers.ninja/swagger/users/userscontroller_getuserinfo.md): Get user account info (business with user management permission OR admin authentication required). Identifier is passed in the request body (safe for PII such as email). Use include parameter for related data. Note: Including status/balances adds latency - consider separate calls for performance-critical scenarios.

### Create or update user account

 - [POST /users](https://docs.pers.ninja/swagger/users/userscontroller_createorupdateuser.md): Create or update user account(s). Supports single user (business/admin) or bulk operations (admin only)

### Get all users

 - [GET /users](https://docs.pers.ninja/swagger/users/userscontroller_getallusers.md): Get all users with role-based access. Use pagination parameters (page & limit) for optimal performance. With merge param, only checks duplicates for users on current page (smart merge). Project API key users get public profiles only. Admin users get full access.

### Get user by identifier

 - [GET /users/{identifier}](https://docs.pers.ninja/swagger/users/userscontroller_getuserbyidentifier.md): Get user by any unique identifier field (id, email, externalId, accountAddress, etc.). Business (with user management permission) or admin. ⚠️ The identifier travels in the URL - for PII such as email prefer POST /users/info (identifier in body). Use include parameter for related data. Note: Including status/balances adds latency - consider separate calls for performance-critical scenarios.

### Update user by identifier (admin)

 - [PUT /users/{identifier}](https://docs.pers.ninja/swagger/users/userscontroller_updateuserbyidentifier.md): Update user account by any unique identifier field (id, email, externalId, accountAddress, etc.). Admin only.

### Delete user by identifier (admin)

 - [DELETE /users/{identifier}](https://docs.pers.ninja/swagger/users/userscontroller_deleteuserbyidentifier.md): Soft delete user by any unique identifier field (id, email, externalId, accountAddress, etc.). Admin only. ⚠️ This operation is irreversible via API - consider using PUT /users/{identifier}/status for temporary deactivation.

### Create users from URL (admin)

 - [POST /users/bulk/url](https://docs.pers.ninja/swagger/users/userscontroller_createusersfromurl.md): Create user accounts from external URL as admin

### Set or toggle user status by identifier

 - [PUT /users/{identifier}/status](https://docs.pers.ninja/swagger/users/userscontroller_toggleuserstatusbyidentifier.md): Set or toggle user active status by any unique identifier field (id, email, externalId, accountAddress, etc.). If body contains { isActive: true/false }, sets explicitly. If no body, toggles. Admin only.

### Restore deleted user (admin)

 - [POST /users/{identifier}/restore](https://docs.pers.ninja/swagger/users/userscontroller_restoreuserbyidentifier.md): Restore a soft-deleted user within the 30-day grace period. After GDPR anonymization, restoration is not possible.

### Export users as CSV

 - [GET /users/export/csv](https://docs.pers.ninja/swagger/users/userscontroller_exportusersascsv.md): Export all users to CSV format. Optional date filtering by createdAt.

### Get current user balance (deprecated)

 - [GET /users/me/balance](https://docs.pers.ninja/swagger/users/userscontroller_getcurrentuserbalance.md): Get authenticated user account with current token balances

### Get user balance (deprecated)

 - [POST /users/balance](https://docs.pers.ninja/swagger/users/userscontroller_getuserbalance.md): DEPRECATED: Use POST /users/info?include=balances instead. Get user account with current token balances (business with user management permission OR admin authentication required).

## Balances

## Account Balance Management
    <div style="font-size: 14px; line-height: 1.5;">
      Real-time balance tracking and management across all token types and user accounts. Provides comprehensive balance queries and balance-related operations.
    </div>
    <b>Balance Features:</b>  
    <br/>• <b>Multi-Token Balances:</b> Track balances across different token types per user
    <br/>• <b>Real-Time Updates:</b> Instant balance updates from all transaction sources
    <br/>• <b>Balance History:</b> Historical balance tracking and change audit trails
    <br/>• <b>Balance Queries:</b> Flexible balance lookup with filtering and aggregation
    <br/>• <b>Balance Notifications:</b> Alert systems for balance changes and thresholds

### Get account balance by address (Admin)

 - [GET /balances/accounts/{accountAddress}](https://docs.pers.ninja/swagger/balances/balancescontroller_getaccountbalance.md): Get detailed balance information including token metadata for any account address. Requires tenant admin privileges. Replaces GET /balance/admin/account/{accountAddress}

## Files

## File Management System
    <div style="font-size: 14px; line-height: 1.5;">
      File upload and management system for platform assets including campaign images, user avatars, and document attachments with secure storage and access control.
    </div>
    <b>File Operations:</b>
    <br/>• <b>Secure Upload:</b> File upload with type validation and security scanning
    <br/>• <b>Asset Management:</b> Organize and manage platform media assets
    <br/>• <b>Access Control:</b> Role-based file access and sharing permissions
    <br/>• <b>CDN Integration:</b> Fast global file delivery through content delivery networks
    <br/>• <b>File Processing:</b> Automatic image resizing and format optimization

### Generate signed URL for entity storage

 - [POST /files/entity-storage-url](https://docs.pers.ninja/swagger/files/filescontroller_getentitystorageurl.md): Creates S3 signed URLs for uploading or downloading entity files. Supports both business and admin authentication flows.

## Web3 Chains

## Blockchain Network Management  
    <div style="font-size: 14px; line-height: 1.5;">
      Blockchain network configuration and management for multi-chain token operations. Handles network connections, chain switching, and blockchain-specific operations.
    </div>
    <b>Chain Operations:</b>
    <br/>• <b>Multi-Chain Support:</b> Connect to multiple blockchain networks simultaneously  
    <br/>• <b>Network Configuration:</b> Configure blockchain endpoints and network parameters
    <br/>• <b>Chain Switching:</b> Dynamic switching between different blockchain networks
    <br/>• <b>Network Status:</b> Real-time monitoring of blockchain network health and status
    <br/>• <b>Gas Management:</b> Optimize transaction costs across different networks

### Get Web3 chain data by chain ID

 - [GET /chains/{chainId}](https://docs.pers.ninja/swagger/web3-chains/web3chainscontroller_getchaindata.md): Retrieve comprehensive chain data including authentication JWT token valid for 30 days. Supports both mainnet and testnet chains.

## Contracts

## Smart Contract Management
    <div style="font-size: 14px; line-height: 1.5;">
      Smart contract deployment and interaction management for blockchain-based loyalty operations. Handles contract lifecycle and blockchain integration.
    </div>
    <b>Contract Operations:</b>
    <br/>• <b>Contract Deployment:</b> Deploy loyalty-related smart contracts to blockchain networks
    <br/>• <b>Contract Interaction:</b> Execute smart contract functions for token operations
    <br/>• <b>Contract Monitoring:</b> Track contract events and transaction confirmations  
    <br/>• <b>Contract Upgrades:</b> Manage contract versioning and upgrade procedures
    <br/>• <b>Multi-Chain Contracts:</b> Deploy and manage contracts across multiple blockchains

### Create a new Web3 contract (Admin)

 - [POST /contracts](https://docs.pers.ninja/swagger/contracts/web3contractscontroller_createcontract.md): Create a new Web3 contract with administrative privileges. Requires tenant admin access. Replaces POST /contract

## Auth

## Authentication & Authorization  
    <div style="font-size: 14px; line-height: 1.5;">
      Comprehensive authentication and authorization system supporting multiple access levels including users, businesses, admins, and system-level access with JWT-based security.
    </div>
    <b>Auth Features:</b>
    <br/>• <b>Multi-Level Access:</b> Support for USER, BUSINESS, ADMIN, SYSTEM authentication levels
    <br/>• <b>JWT Security:</b> JSON Web Token-based authentication with secure key management
    <br/>• <b>Role-Based Access:</b> Fine-grained permission system with role hierarchy  
    <br/>• <b>API Key Management:</b> Secure API key generation and validation for system integrations
    <br/>• <b>Session Management:</b> Secure session handling with automatic expiration and refresh

### Create authentication token

 - [POST /auth/token](https://docs.pers.ninja/swagger/auth/authcontroller_createtoken.md): Universal token creation with consistent token-in-body pattern.

## Authentication Flows

### USER AUTHENTICATION
- Header: x-project-key (tenant identification)
- Body: { authToken: "jwt_from_provider", authType: "user" }
- Returns: User session with PERS JWT tokens

### BUSINESS AUTHENTICATION
- Header: x-project-key (tenant identification)
- Body: { authToken: "jwt_from_provider", authType: "business", context: { businessId: "uuid" } }
- Returns: Business session with PERS JWT tokens (includes role in JWT)
- If user has single business membership, context.businessId is auto-selected
- If user has multiple memberships without context.businessId, returns MULTIPLE_CONTEXT_SELECTION_REQUIRED error with available options

### ADMIN AUTHENTICATION
- Header: x-project-key (tenant identification)
- Body: { authToken: "firebase_jwt", authType: "tenant" }
- Returns: Admin session with PERS JWT tokens

---

## Third-Party JWT Requirements

When providing authToken from an external identity provider, the JWT must meet these requirements:

### JWT Header
| Field | Required | Description |
|-------|----------|-------------|
| kid | Yes | Key ID matching a key in your JWKS |
| alg | Yes | Signing algorithm (RS256, ES256, EdDSA) |

### JWT Payload Claims
| Claim | Required | Description |
|-------|----------|-------------|
| iss | Yes | Issuer URL (used for JWKS discovery) |
| sub | Yes | Subject identifier (user ID) |
| aud | Yes | Audience (your registered client ID) |
| exp | Yes | Expiration timestamp (Unix epoch) |
| iat | Yes | Issued at timestamp (Unix epoch) |

### Provider Requirements
Your identity provider must expose public keys via one of:
1. {issuer}/.well-known/jwks.json (JWKS endpoint)
2. {issuer}/.well-known/openid-configuration (OIDC discovery with jwks_uri)

### Verification Flow
1. PERS extracts iss claim from JWT
2. Fetches JWKS from {issuer}/.well-known/jwks.json
3. Matches kid header to find signing public key
4. Verifies signature using matched key
5. Validates exp, iat, aud claims
6. Issues PERS access/refresh tokens on success

### PERS JWKS (For verifying our tokens)
- JWKS: https://api.pers.ninja/.well-known/jwks.json
- Discovery: https://api.pers.ninja/.well-known/openid-configuration

### Refresh authentication tokens

 - [POST /auth/refresh](https://docs.pers.ninja/swagger/auth/authcontroller_refresh.md): Refresh access tokens using valid refresh token

### Verify JWT token

 - [POST /auth/verify](https://docs.pers.ninja/swagger/auth/authcontroller_verifytoken.md): Verify JWT tokens with automatic issuer detection:
        
        - Decodes JWT to extract issuer claim
        - PERS tokens: Verified internally
        - External tokens: Future support planned
        - Standards-compliant JWT verification

### Send magic link email

 - [POST /auth/magic-link/send](https://docs.pers.ninja/swagger/auth/authcontroller_sendmagiclink.md): Send a magic link email for passwordless authentication. Rate limited to 3 requests per email per 10 minutes.

## Root

## Platform Infrastructure  
    <div style="font-size: 14px; line-height: 1.5;">
      Core platform infrastructure endpoints including health checks, system status, and platform configuration. Provides essential system-level operations and monitoring.
    </div>
    <b>Infrastructure Operations:</b>
    <br/>• <b>Health Monitoring:</b> System health checks and status reporting
    <br/>• <b>Platform Status:</b> Real-time platform operational status
    <br/>• <b>Configuration Access:</b> System configuration and environment information
    <br/>• <b>Diagnostic Tools:</b> Platform diagnostics and troubleshooting endpoints
    <br/>• <b>System Integration:</b> Core infrastructure for system-level operations

### RootController_get

 - [GET /](https://docs.pers.ninja/swagger/root/rootcontroller_get.md)

### RootController_getCurrentTime

 - [GET /healthcheck](https://docs.pers.ninja/swagger/root/rootcontroller_getcurrenttime.md)

### Check if tenant system api key is valid

 - [GET /system](https://docs.pers.ninja/swagger/root/rootcontroller_getsystem.md): Check if tenant system api key is valid

### ADMIN: Check if admin

 - [GET /admin](https://docs.pers.ninja/swagger/root/rootcontroller_getadmin.md): Get if admin

### RootController_testGeo

 - [GET /geolocation](https://docs.pers.ninja/swagger/root/rootcontroller_testgeo.md)

## Well-known

## Security Infrastructure
    <div style="font-size: 14px; line-height: 1.5;">
      JSON Web Key Set (JWKS) endpoints for JWT token verification. Provides public keys for secure authentication token validation across the platform ecosystem.
    </div>
    <b>Security Features:</b>
    <br/>• <b>JWKS Endpoints:</b> Standard JSON Web Key Set for JWT verification
    <br/>• <b>Public Key Distribution:</b> Secure distribution of verification keys
    <br/>• <b>Token Validation:</b> Enable third-party JWT token verification
    <br/>• <b>Security Standards:</b> Compliance with OAuth 2.0 and OpenID Connect
    <br/>• <b>Cross-Platform Auth:</b> Support for distributed authentication verification

### Get JSON Web Key Set (JWKS)

 - [GET /jwks.json](https://docs.pers.ninja/swagger/well-known/jwkscontroller_getjwks.md)

### Get OIDC Discovery Document

 - [GET /openid-configuration](https://docs.pers.ninja/swagger/well-known/jwkscontroller_getopenidconfiguration.md)

## Webhooks

## Webhook Integration System
    <div style="font-size: 14px; line-height: 1.5;">
      Webhook proxy and integration system for external service notifications. Handles incoming webhook events and integrates with external platforms for real-time data synchronization.
    </div>
    <b>Webhook Features:</b>
    <br/>• <b>Webhook Proxy:</b> Secure proxy for external webhook integrations
    <br/>• <b>Event Processing:</b> Real-time processing of external service events
    <br/>• <b>Integration Management:</b> Manage connections with external platforms
    <br/>• <b>Security Validation:</b> Webhook signature verification and authentication
    <br/>• <b>Event Routing:</b> Intelligent routing of webhook events to appropriate handlers

### Create webhook

 - [POST /hooks](https://docs.pers.ninja/swagger/webhooks/webhookcontroller_create.md)

### List webhooks

 - [GET /hooks](https://docs.pers.ninja/swagger/webhooks/webhookcontroller_list.md)

### Get webhook executions

 - [GET /hooks/executions](https://docs.pers.ninja/swagger/webhooks/webhookcontroller_getexecutions.md): Get webhook execution history with filtering options.
      
      Filters:
      - hookId: Filter by specific webhook (optional - omit for all webhooks)
      - status: Filter by execution status (success, failed, pending)
      - dateFrom: Filter executions after this date (ISO 8601)
      - dateTo: Filter executions before this date (ISO 8601)
      
      Use pagination parameters (page & limit) for optimal performance.

### Get webhook

 - [GET /hooks/{hookId}](https://docs.pers.ninja/swagger/webhooks/webhookcontroller_get.md)

### Update webhook

 - [PUT /hooks/{hookId}](https://docs.pers.ninja/swagger/webhooks/webhookcontroller_update.md)

### Delete webhook

 - [DELETE /hooks/{hookId}](https://docs.pers.ninja/swagger/webhooks/webhookcontroller_delete.md)

## Trigger Sources

### Create trigger source

 - [POST /trigger-sources](https://docs.pers.ninja/swagger/trigger-sources/triggersourcescontroller_createtriggersource.md): Create a new trigger source (QR code, NFC tag, webhook, geofence, etc.) for a campaign

### Get all trigger sources

 - [GET /trigger-sources](https://docs.pers.ninja/swagger/trigger-sources/triggersourcescontroller_getalltriggersources.md): Retrieve all trigger sources with optional filtering and pagination. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future).

### Get trigger source by ID

 - [GET /trigger-sources/{id}](https://docs.pers.ninja/swagger/trigger-sources/triggersourcescontroller_gettriggersource.md): Retrieve a specific trigger source with its configuration

### Update trigger source

 - [PUT /trigger-sources/{id}](https://docs.pers.ninja/swagger/trigger-sources/triggersourcescontroller_updatetriggersource.md): Update an existing trigger source configuration

### Delete trigger source

 - [DELETE /trigger-sources/{id}](https://docs.pers.ninja/swagger/trigger-sources/triggersourcescontroller_deletetriggersource.md): Soft delete a trigger source (sets deletedAt timestamp)

## Business Types

### Create a new business type

 - [POST /businesses/types](https://docs.pers.ninja/swagger/business-types/businesstypescontroller_createbusinesstype.md): Create a new business type

### Update a business type

 - [PUT /businesses/types](https://docs.pers.ninja/swagger/business-types/businesstypescontroller_updatebusinesstype.md): Update a business type

### Get all business types

 - [GET /businesses/types](https://docs.pers.ninja/swagger/business-types/businesstypescontroller_getallbusinesstypes.md): Get all business types. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future).

### Delete a business type

 - [DELETE /businesses/types/{id}](https://docs.pers.ninja/swagger/business-types/businesstypescontroller_deletebusinesstype.md): Delete a business type

## Redemption Types

### Get redemption types

 - [GET /redemptions/types](https://docs.pers.ninja/swagger/redemption-types/redemptiontypescontroller_getredemptiontypes.md): Get all available redemption types for client reference. Requires valid project API key. Use pagination parameters (page & limit) for optimal performance. Legacy support: returns array without params (deprecated - will be removed in future).

### Create redemption type (Admin)

 - [POST /redemptions/types](https://docs.pers.ninja/swagger/redemption-types/redemptiontypescontroller_createredemptiontype.md): Create a new redemption type for system configuration. Replaces POST /redemption/admin/type

### Update redemption type (Admin)

 - [PUT /redemptions/types/{id}](https://docs.pers.ninja/swagger/redemption-types/redemptiontypescontroller_updateredemptiontype.md): Update an existing redemption type configuration

### Delete redemption type (Admin)

 - [DELETE /redemptions/types/{id}](https://docs.pers.ninja/swagger/redemption-types/redemptiontypescontroller_deleteredemptiontype.md): Delete a redemption type. Will fail if any redemptions are using this type.

## Redemption Redeems

### Execute redemption (Unified)

 - [POST /redemptions/redeems](https://docs.pers.ninja/swagger/redemption-redeems/redemptionredeemscontroller_executeredemption.md): Process redemption execution using role-based detection. Supports user, business, and admin redemption processing.

ERC721 Dynamic Context & Template Interpolation:

For ERC721 tokens, you can provide a context object whose values become available as {{context.xxx}} placeholders in the token's name/description and AI prompts.

Context sources (merge order):
1. TokenMetadata.defaultPromptContext → {{defaults.xxx}}
2. Redemption.context (admin-defined) → {{context.xxx}} (always applied)
3. RedemptionRedeemRequest.context (this field) → {{context.xxx}} (only if allowExternalContextOverwrite=true)

Example - Event ticket redemption:
json
{
  "redemptionId": "redemption-uuid",
  "context": {
    "seatNumber": "A12",
    "attendeeName": "John Smith"
  }
}

With TokenMetadata name: "{{context.attendeeName}} - Seat {{context.seatNumber}}"
Result: "John Smith - Seat A12"

### Get redemption redeems with advanced filtering

 - [GET /redemptions/redeems](https://docs.pers.ninja/swagger/redemption-redeems/redemptionredeemscontroller_getredemptionredeems.md): Get redemption redeems with comprehensive filtering options:
        - redemptionId: Filter by specific redemption (optional)
        - userId: Filter by specific user ID (admin only)
        - businessId: Filter by specific business ID (admin only)
        - include: Optionally include related entities (redemption, user, business, transactions)
        
        Access Control:
        - Users: See only their own redemptions
        - Business: See only redemptions associated with their business account
        - Admin: Can filter by any combination of parameters or see all redemptions
        
        Security Notes:
        - Users cannot access userId or businessId parameters (automatically filtered)
        - Business accounts automatically filter to their own businessId regardless of parameter
        - Admin has full access to all filtering options
        
        Use pagination parameters (page & limit) for optimal performance - critical for high-volume data. Legacy support: returns array without params (deprecated - will be removed in future).

### Get my redemption redeems (Convenience)

 - [GET /redemptions/redeems/me](https://docs.pers.ninja/swagger/redemption-redeems/redemptionredeemscontroller_getmyredemptionredeems.md): Convenience endpoint for authenticated users to retrieve their own redemption redeems.
        
        Equivalent to GET /redemption-redeems but with required authentication and 
        automatic filtering to current user context.
        
        Features:
        - Automatic user context (no userId parameter needed)
        - Optional redemption filtering
        - Optional status filtering (PENDING, PROCESSING, COMPLETED, FAILED)
        - Requires user authentication
        - Simplified response structure
        - Optional entity inclusion (redemption, user, business, transactions)
        - Use pagination parameters (page & limit) for optimal performance - recommended for active users
        - Legacy support: returns array without params (deprecated - will be removed in future)
        
        Usage Examples:
        - GET /redemption-redeems/me (all redemptions for authenticated user)
        - GET /redemption-redeems/me?redemptionId=123 (specific user redemption)
        - GET /redemption-redeems/me?status=COMPLETED (only completed redemptions)
        - GET /redemption-redeems/me?page=1&limit=10 (paginated results)
        - GET /redemption-redeems/me?include=redemption,user (with related entities)
        - GET /redemption-redeems/me?include=redemption,transactions (with transactions)

### Get specific redemption redeem

 - [GET /redemptions/redeems/{redeemId}](https://docs.pers.ninja/swagger/redemption-redeems/redemptionredeemscontroller_getredemptionredeembyid.md): Get current status of a specific redemption redeem with automatic access control based on authentication context. Optionally include related entities (redemption, user, business, transactions).

### Export redeems to CSV

 - [GET /redemptions/redeems/export/csv](https://docs.pers.ninja/swagger/redemption-redeems/redemptionredeemscontroller_exportredeemscsv.md): Export all redeems as a CSV file. Supports date filtering and including related entities.

## Redemption Tokens

### Add token unit to redemption

 - [POST /redemptions/{redemptionId}/tokens](https://docs.pers.ninja/swagger/redemption-tokens/redemptiontokenscontroller_addtokenunittoredemption.md): Add a new token unit to an existing redemption. Available to Admin and Business accounts.

### Update redemption token unit

 - [PUT /redemptions/{redemptionId}/tokens/{tokenUnitId}](https://docs.pers.ninja/swagger/redemption-tokens/redemptiontokenscontroller_updatetokenunit.md): Update an existing token unit within a redemption. Available to Admin and Business accounts.

### Remove token unit from redemption

 - [DELETE /redemptions/{redemptionId}/tokens/{tokenUnitId}](https://docs.pers.ninja/swagger/redemption-tokens/redemptiontokenscontroller_removetokenunit.md): Remove an existing token unit from a redemption. Available to Admin and Business accounts.

## API Keys

### Get all API keys (Admin/Business)

 - [GET /api-keys](https://docs.pers.ninja/swagger/api-keys/apikeyscontroller_gettenantapikeys.md): Admin: returns all integration keys for the tenant, optionally filtered by type. Business: returns only keys scoped to their own business entity. Use pagination parameters (page & limit) for optimal performance.

### Create new system JWT token (Admin)

 - [POST /api-keys](https://docs.pers.ninja/swagger/api-keys/apikeyscontroller_createapikey.md): Create a new long-lived system JWT for app integration (M2M). Provide businessId to create a business-scoped token (BUSINESS_SYSTEM_JWT) for server-to-server integrations. Omit businessId to create a tenant-scoped token (TENANT_SYSTEM_JWT). Store the returned token securely - it cannot be retrieved again.

### Revoke API key (Admin)

 - [DELETE /api-keys/{id}](https://docs.pers.ninja/swagger/api-keys/apikeyscontroller_revokeapikey.md): Permanently revoke an API key. This operation cannot be undone. The key will be marked as revoked and will no longer be valid for authentication.

## Webhook Proxy

### Receive callback from external system

 - [POST /hooks/{projectKey}/executions/{executionId}/callback](https://docs.pers.ninja/swagger/webhook-proxy/webhookproxycontroller_processcallback.md): Receive workflow completion callback from external systems (e.g., n8n).
      
      URL format: /hooks/{projectKey}/executions/{executionId}/callback
      
      Security:
      - Project key identifies tenant (RLS enforces isolation)
      - Execution ID is UUIDv4 (unguessable)
      - Execution must be < 1 hour old
      - Execution cannot receive multiple callbacks
      
      No authentication required - security via execution ID secrecy + RLS.

### Trigger webhook (forward request to configured target)

 - [GET /hooks/{projectKey}/{hookId}](https://docs.pers.ninja/swagger/webhook-proxy/webhookproxycontroller_receivewebhook_get.md): Project key in URL path identifies the tenant. Configure webhook URL as: /hooks/{projectKey}/{hookId}. Returns wrapped response with execution metadata.

### Trigger webhook (forward request to configured target)

 - [POST /hooks/{projectKey}/{hookId}](https://docs.pers.ninja/swagger/webhook-proxy/webhookproxycontroller_receivewebhook_post.md): Project key in URL path identifies the tenant. Configure webhook URL as: /hooks/{projectKey}/{hookId}. Returns wrapped response with execution metadata.

### Trigger webhook (forward request to configured target)

 - [PUT /hooks/{projectKey}/{hookId}](https://docs.pers.ninja/swagger/webhook-proxy/webhookproxycontroller_receivewebhook_put.md): Project key in URL path identifies the tenant. Configure webhook URL as: /hooks/{projectKey}/{hookId}. Returns wrapped response with execution metadata.

### Trigger webhook (forward request to configured target)

 - [DELETE /hooks/{projectKey}/{hookId}](https://docs.pers.ninja/swagger/webhook-proxy/webhookproxycontroller_receivewebhook_delete.md): Project key in URL path identifies the tenant. Configure webhook URL as: /hooks/{projectKey}/{hookId}. Returns wrapped response with execution metadata.

### Trigger webhook (forward request to configured target)

 - [PATCH /hooks/{projectKey}/{hookId}](https://docs.pers.ninja/swagger/webhook-proxy/webhookproxycontroller_receivewebhook_patch.md): Project key in URL path identifies the tenant. Configure webhook URL as: /hooks/{projectKey}/{hookId}. Returns wrapped response with execution metadata.

### Trigger webhook (forward request to configured target)

 - [OPTIONS /hooks/{projectKey}/{hookId}](https://docs.pers.ninja/swagger/webhook-proxy/webhookproxycontroller_receivewebhook_options.md): Project key in URL path identifies the tenant. Configure webhook URL as: /hooks/{projectKey}/{hookId}. Returns wrapped response with execution metadata.

### Trigger webhook (forward request to configured target)

 - [HEAD /hooks/{projectKey}/{hookId}](https://docs.pers.ninja/swagger/webhook-proxy/webhookproxycontroller_receivewebhook_head.md): Project key in URL path identifies the tenant. Configure webhook URL as: /hooks/{projectKey}/{hookId}. Returns wrapped response with execution metadata.

## Event Subscriptions

### Register a webhook URL to receive outbox events

 - [POST /events](https://docs.pers.ninja/swagger/event-subscriptions/eventsubscriptioncontroller_create.md)

### List event subscriptions

 - [GET /events](https://docs.pers.ninja/swagger/event-subscriptions/eventsubscriptioncontroller_list.md)

### Get event subscription by ID

 - [GET /events/{id}](https://docs.pers.ninja/swagger/event-subscriptions/eventsubscriptioncontroller_getbyid.md)

### Update event subscription

 - [PUT /events/{id}](https://docs.pers.ninja/swagger/event-subscriptions/eventsubscriptioncontroller_update.md)

### Delete event subscription

 - [DELETE /events/{id}](https://docs.pers.ninja/swagger/event-subscriptions/eventsubscriptioncontroller_delete.md)

## Custom Field Definitions

### List custom field definitions

 - [GET /custom-field-definitions](https://docs.pers.ninja/swagger/custom-field-definitions/customfielddefinitionscontroller_listdefinitions.md): Get all custom field definitions for the tenant. Filter by entityType to get fields for a specific entity.

### Create custom field definition

 - [POST /custom-field-definitions](https://docs.pers.ninja/swagger/custom-field-definitions/customfielddefinitionscontroller_create.md): Create a new custom field for the tenant. Key must be unique within tenant+entityType.

### Get custom field definition by ID

 - [GET /custom-field-definitions/{id}](https://docs.pers.ninja/swagger/custom-field-definitions/customfielddefinitionscontroller_getbyid.md): Get a single custom field definition by ID.

### Update custom field definition

 - [PUT /custom-field-definitions/{id}](https://docs.pers.ninja/swagger/custom-field-definitions/customfielddefinitionscontroller_update.md): Update field properties. Key and entityType cannot be changed.

### Delete custom field definition

 - [DELETE /custom-field-definitions/{id}](https://docs.pers.ninja/swagger/custom-field-definitions/customfielddefinitionscontroller_delete.md): Delete a field. Fails if field is referenced in any redemption baseRequiredUserFields/specificRequiredUserFields or campaign.

### Check field usages

 - [GET /custom-field-definitions/{id}/usages](https://docs.pers.ninja/swagger/custom-field-definitions/customfielddefinitionscontroller_getusages.md): Check if a field is referenced in any redemption or campaign. Useful before deletion.

## Analytics

### Get transaction analytics (Admin only)

 - [POST /analytics/transactions](https://docs.pers.ninja/swagger/analytics/analyticscontroller_gettransactionanalytics.md): Returns aggregated transaction data with flexible grouping and metrics. Supports complex filtering by date range, business, token, status, and more. Requires admin authentication.

### Get campaign claim analytics (Admin/Business)

 - [POST /analytics/campaign-claims](https://docs.pers.ninja/swagger/analytics/analyticscontroller_getcampaignclaimanalytics.md): Returns aggregated campaign claim data with flexible grouping and metrics. Business users are auto-filtered to their own campaigns (ownerBusinessId). Admin users see all data.

### Get redemption redeem analytics (Admin/Business)

 - [POST /analytics/redemption-redeems](https://docs.pers.ninja/swagger/analytics/analyticscontroller_getredemptionredeemanalytics.md): Returns aggregated redemption redeem data with flexible grouping and metrics. Business users are auto-filtered to their own redemptions (ownerBusinessId). Admin users see all data.

### Get user analytics (Admin only)

 - [POST /analytics/users](https://docs.pers.ninja/swagger/analytics/analyticscontroller_getuseranalytics.md): Returns aggregated user statistics including total users, active users, new users, transaction metrics, campaign claims, redemptions, and engagement rate. Supports date range filtering. Requires admin authentication.

### Get user transaction ranking (Admin only)

 - [POST /analytics/users/ranking](https://docs.pers.ninja/swagger/analytics/analyticscontroller_getuserranking.md): Returns ranked list of users with full user details and transaction metrics. Data enrichment via efficient SQL JOINs + UNION (handles legacy transactions). Supports filtering by business, token type, date range. Requires admin authentication.

### Get business transaction ranking (Admin only)

 - [POST /analytics/businesses/ranking](https://docs.pers.ninja/swagger/analytics/analyticscontroller_getbusinessranking.md): Returns ranked list of businesses with full business details and transaction metrics. Data enrichment via efficient SQL JOINs + UNION (handles legacy transactions). Supports filtering by token type, date range. Requires admin authentication.

### Get cohort-based user retention analytics (Admin only)

 - [POST /analytics/users/retention](https://docs.pers.ninja/swagger/analytics/analyticscontroller_getretentionanalytics.md): Returns cohort retention data showing how user cohorts perform over time. Each cohort represents users who joined in a specific month, tracked across subsequent months. Replaces 13 separate API calls with 1 efficient query. Industry-standard cohort analysis for retention heatmaps. Requires admin authentication.

### Get tag analytics across entities

 - [GET /analytics/tags](https://docs.pers.ninja/swagger/analytics/analyticscontroller_gettaganalytics.md): Returns aggregated tag usage data across Campaign, Redemption, Business, TokenMetadata, and UserStatusType entities. Useful for tag filtering in apps and autocomplete suggestions.

### Get AI usage summary for billing (Admin only)

 - [POST /analytics/ai/usage](https://docs.pers.ninja/swagger/analytics/analyticscontroller_getaiusagesummary.md): Returns aggregated AI usage metrics with breakdown by model and operation type. Perfect for billing reports and cost monitoring. Requires admin authentication.

### Get AI analytics with dynamic grouping (Admin only)

 - [POST /analytics/ai](https://docs.pers.ninja/swagger/analytics/analyticscontroller_getaianalytics.md): Returns aggregated AI generation data with flexible grouping and metrics. Supports filtering by model, operation type, user, and success status. Requires admin authentication.

