Overview
Swaarm provides the Rewarded Users API, which enables rewards app developers to manage rewarded users, deliver offers, track task completion, and handle reward distribution within their applications. The API provides functionality for user management, offer delivery, reward tracking, and analytics within rewarded applications. The API can be queried using GraphQL.
What is GraphQL?
GraphQL is a query language and runtime for APIs that allows clients to request exactly the data they need. Unlike REST APIs with multiple endpoints, GraphQL uses a single endpoint where you send queries and mutations to fetch or modify data.
GraphQL Clients and Libraries
You can interact with GraphQL APIs using various clients:
JavaScript/TypeScript
Apollo Client
urql
Mobile
Apollo iOS (Swift)
Apollo Android (Kotlin/Java)
graphql-flutter (Flutter)
Using standardised clients is highly recommended as it will automatically generate the types and verify that your queries are correct.
Making Requests with GraphQL
If you do not use a client library, you can send GraphQL requests via HTTP POST requests to a single endpoint with a JSON body containing:
{
"query": "query GetUser { rewardedUser { id email } }",
"variables": {}
}Getting Started with Rewarded API
Authentication
Registration: No authentication is required for user registration.
All Other Requests: You must authenticate using the login mutation and include the access token in subsequent requests.
NOTE: The access token is valid for 24 hours, you should request a new token when receiving a 401 error, or proactively refresh tokens every few hours to avoid authentication errors.
Login Mutation
mutation Login {
login(input: {
username: "rewardeduser@swaarm.com",
password: "newSuperSecurePasswrd123$"
}) {
authChallenge
token {
accessToken
refreshToken
tokenType
expiresIn
}
}
}
Using Access Tokens
Include the access token in the Authorization header for all authenticated requests:
Authorization: Bearer YOUR_ACCESS_TOKEN
GraphQL Endpoint
All API interactions use a single GraphQL endpoint which is provided in your Swaarm dashboard. Queries and mutations must follow the schema described below.
Core Concepts
Users - users of your rewards app. Each user has a profile, custom fields, and associated offers and rewards.
Offers - tasks or actions users can complete to earn rewards. They include tracking URLs, creative assets, and payout information.
Rewards - track completed offers and the points/currency earned by users.
Events - individual milestones within offers, each with their own payout structure.
Schema Reference
Pagination
All list queries use offset-based pagination:
input Pagination {
offset: Int # Starting position (0-based)
limit: Int # Maximum number of items to return
}RewardedUser
The central entity representing a user in your rewards app.
type RewardedUser {
id: String!
email: String!
nickName: String!
firstName: String
lastName: String
customFields: [RewardedUserProfileCustomField!]
status: RewardedUserStatus!
offers(filter: RewardedOffersFilter, pagination: Pagination!): RewardedOfferConnection!
rewards(pagination: Pagination!): RewardedUserRewardConnection!
report(input: RewardedReportInput!): RewardedReport!
internalId: String
referralId: String
}Fields:
id: Unique identifier for the user, generated by Swaarmemail: User's email address (required)nickName: Display name for the userfirstName,lastName: Optional personal informationcustomFields: Array of custom profile data for storing additional user information (e.g., preferences, app-specific data)status: Current user status (ACTIVE, PENDING, INACTIVE)offers: Available offers for this user (filtered and paginated)rewards: User's completed rewards (paginated)report: Analytics data for the user's activityinternalId: User's id given by the app if one existsreferralId: Id of the user that referred this user
Creating and Updating Users
Create User - Use the
RewardedUserInputto create new users:
input RewardedUserInput {
internalId: String
email: String!
firstName: String
lastName: String
nickname: String
password: String!
country: String
status: RewardedUserStatus!
customFields: [RewardedUserProfileCustomFieldInput!]
referralId: String
} Update User - Use
RewardedUserUpdateInputto update existing user information:
input RewardedUserUpdateInput {
id: String!
internalId: String
firstName: String
lastName: String
nickname: String
country: String
customFields: [RewardedUserProfileCustomFieldInput!]
referralId: String
}Available Mutations
# Create a new user (no authentication required)
createRewardedUser(input: RewardedUserInput!): RewardedUser!
# Update existing user (authentication required)
updateRewardedUser(input: RewardedUserUpdateInput!): RewardedUser!
Examples
Creating a User
mutation CreateUser($input: RewardedUserInput!) {
createRewardedUser(input: $input) {
id
email
nickName
status
customFields {
name
value
}
}
}Updating a User
mutation UpdateUser($input: RewardedUserUpdateInput!) {
updateRewardedUser(input: $input) {
id
nickName
firstName
lastName
customFields {
name
value
}
}
} Offers and Filtering
Use RewardedOffersFilter to control which offers are returned:
input RewardedOffersFilter {
autoFilter: Boolean # Apply automatic filtering based on user profile
excludeCompleted: Boolean # Hide offers already completed by the user
country: String # Filter by target country
keyword: String # Search offers by keyword
os: String # Filter by operating system
}RewardedOffer
Represents a task or action that users can complete for rewards.
type RewardedOffer {
id: String!
name: String!
trackingUrl: String! # URL for tracking user interactions
impressionUrl: String # URL fired when offer is displayed
description: String
appStoreId: String # App store identifier if applicable
previewUrl: String # URL for previewing the offer
status: OfferStatus!
eventTypes: [RewardedEventType!]! # Steps users need to complete with payout info
leadflow: Leadflow! # Payment model (CPI, CPM, CPC, CPA, CPL, CPS)
kpi: String # Key performance indicators
additionalInformation: String
tags: [String!]
creatives: [RewardedOfferCreativePack!]
}Payment Models (Leadflow)
CPI: Cost Per Install
CPM: Cost Per Mille (impressions)
CPC: Cost Per Click
CPA: Cost Per Action
CPL: Cost Per Lead
CPS: Cost Per Sale
RewardedUserReward
Tracks completed offers and associated events.
type RewardedUserReward {
offer: RewardedOffer!
completed: [RewardedCompletedEvent!]!
}
type RewardedCompletedEvent {
event: RewardedEventType!
theyGetPoints: Float # Points awarded to user
theyGet: Float # Currency/value awarded to user
time: LocalDateTime! # When the event was completed
}Payments & Payouts
Swaarm Rewarded API allows rewarded users to request payouts from within a mobile app, while payment approval and execution are fully controlled by admins via Swaarm platform.
How Payments Work
Payouts in Swaarm Rewarded follow a request-and-approval model.
Users can request payouts only for rewards they have already earned, but no payout is processed automatically. Every payout request must be reviewed and approved by an admin before payment is completed. This approach ensures control over fraud prevention, reward validation, and internal payout policies, while still providing a smooth in-app reward experience for users.
Overview of the Payment Flow
The rewarded user earns rewards in the app
Rewards accumulate as available balance
The user requests a payment via the Rewarded API
The payment request appears in the Swaarm platform
Once a payment request is made, the requested funds move to pending balance
An admin approves or denies the request
If approved, the user may claim the reward via an external URL
Important: Creating a payment request does not guarantee payment. All payouts must be explicitly approved in the Swaarm platform.
User Balances
Before requesting a payment, your app must fetch the rewarded user’s balances.
Query: RewardedUser
query RewardedUser {
rewardedUser {
id
email
balance {
availableBalance
pendingBalance
}
}Balance fields
Field | Description |
availableBalance | Funds the user can request for payout |
pendingBalance | Funds under validation or review |
Important: Only availableBalance can be requested for payment.
Requesting a Payment
Rewarded users initiate payouts from the app by creating a payment request via the API.
Mutation: requestRequestRewardedUserPayment
mutation RequestRewardedUserPayment($input: PartneradminPaymentInput!) {
requestRequestRewardedUserPayment(input: $input) {
id
createdAt
amount
start
end
status
}
}Input fields
Field | Type | Required | Description |
rewardedUserId | String | Yes | ID of the rewarded user |
amount | Float | Yes | Amount to be paid out |
start | DateTime | Yes | Start of the earning period |
end | DateTime | Yes | End of the earning period |
Recommended client-side validation
Apps should ensure:
amount > 0
amount ≤ availableBalance
the user is authenticated
a valid rewardedUserId is present
Review & Approval in the Swaarm Platform
After a payment request is created and the request becomes visible in the Swaarm platform, an admin can:
approve the payment, or
deny the payment.
This review step allows admins to:
validate reward legitimacy,
detect fraud or abuse,
apply internal payout policies.
If a request is denied, it will not be processed further.
Listing Payment Requests
To show payment history in your app, query all payment requests for the rewarded user.
Query: RewardedUserPayments
query RewardedUserPayments($userId: String!, $first: Int, $offset: Int) {
rewardedUserPayments(userId: $userId, first: $first, offset: $offset) {
edges {
node {
id
amount
createdAt
start
end
status
paymentProcessorResponse {
key
value
}
}
}
totalCount
}
}Pagination is supported via first and offset.
Payment Status Lifecycle
Each payment request transitions through the following states:
Status | Description |
REQUESTED | Payment requested by the user, awaiting review |
OPEN | Accepted and being processed internally |
APPROVED | Approved in the Swaarm platform |
DENIED | Rejected by the admin |
PAID | Payment completed and ready to be claimed |
Claiming a Reward
Some payment providers require the user to actively claim their reward. When a payment reaches the PAID status, claim details are returned via paymentProcessorResponse.
Extracting the claim URL
const claimUrl = payment.paymentProcessorResponse?.find(
param => param?.key === 'url'
)?.value;
Claim flow
Ensure the payment status is PAID
Check for a url in paymentProcessorResponse
Open the URL in the system browser
Analytics and Reporting
Generate detailed reports using the RewardedReport system:
input RewardedReportInput {
start: LocalDateTime!
end: LocalDateTime!
granularity: RewardedReportInputGranularity! # DAY, WEEK, MONTH, YEAR, ALL
dimensions: [RewardedReportDimension!]! # DATETIME, OFFER_ID
}
type RewardedReport {
start: LocalDateTime!
end: LocalDateTime!
granularity: RewardedReportInputGranularity!
rows: [RewardedReportRow!]!
}
type RewardedReportRow {
dimensions: [RewardedReportDimensionResult!]!
theyGet: Float! # Total currency earned
theyGetPoints: Float! # Total points earned
}
Available Queries and Mutations
Queries
Get Current User
Retrieve the currently authenticated user's information:
query GetCurrentUser {
rewardedUser {
id
email
nickName
firstName
lastName
status
customFields {
name
value
}
}
}Sample Response
{
"data": {
"rewardedUser": {
"id": "user_12345",
"email": "user@example.com",
"nickName": "GamerPro",
"firstName": "John",
"lastName": "Doe",
"status": "ACTIVE",
"customFields": [
{
"name": "preferred_category",
"value": "gaming"
},
{
"name": "user_level",
"value": "advanced"
}
]
}
}
}Mutations
Authentication
mutation Login($input: LoginInput!) {
login(input: $input) {
authChallenge
token {
accessToken
refreshToken
tokenType
expiresIn
}
}
}Variables
{
"input": {
"username": "developer@swaarm.com",
"password": "newSuperSecurePasswrd123$"
}
}Sample Response
{
"data": {
"login": {
"authChallenge": null,
"token": {
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "def502004a8c2c4e1f4d5a6b7c8d9e0f1...",
"tokenType": "Bearer",
"expiresIn": 3600
}
}
}
}User Management
Create User
mutation CreateUser($input: RewardedUserInput!) {
createRewardedUser(input: $input) {
id
email
nickName
status
customFields {
name
value
}
}
}Variables
{
"input": {
"email": "user@example.com",
"password": "userPassword123!",
"nickname": "GamerPro",
"firstName": "John",
"lastName": "Doe",
"country": "US",
"status": "PENDING",
"customFields": [
{
"name": "preferred_category",
"value": "gaming"
},
{
"name": "user_level",
"value": "beginner"
}
],
"referralId": "REF123456"
}
}Sample Response
{
"data": {
"createRewardedUser": {
"id": "user_12345",
"email": "user@example.com",
"nickName": "GamerPro",
"status": "PENDING",
"customFields": [
{
"name": "preferred_category",
"value": "gaming"
},
{
"name": "user_level",
"value": "beginner"
}
]
}
}
} Update User
mutation UpdateUser($input: RewardedUserUpdateInput!) {
updateRewardedUser(input: $input) {
id
nickName
firstName
lastName
customFields {
name
value
}
}
}Variables
{
"input": {
"nickname": "ProGamer2024",
"firstName": "John",
"lastName": "Smith",
"country": "CA",
"customFields": [
{
"name": "preferred_category",
"value": "action"
},
{
"name": "user_level",
"value": "advanced"
},
{
"name": "last_active",
"value": "2024-07-10"
}
]
}
}Sample Response
{
"data": {
"updateRewardedUser": {
"id": "user_12345",
"nickName": "ProGamer2024",
"firstName": "John",
"lastName": "Smith",
"customFields": [
{
"name": "preferred_category",
"value": "action"
},
{
"name": "user_level",
"value": "advanced"
},
{
"name": "last_active",
"value": "2024-07-10"
}
]
}
}
}Common Query Examples
1. Get Current User with Available Offers
Query
query GetUserOffers {
rewardedUser {
id
nickName
offers(
filter: {
excludeCompleted: true,
autoFilter: true
},
pagination: {
offset: 0,
limit: 20
}
) {
totalCount
edges {
node {
id
name
description
trackingUrl
leadflow
eventTypes {
id
name
description
payout {
theyGet
theyGetPoints
}
creativeUrl
creativeThumbnail
}
creatives {
title
creatives {
url
type
}
}
}
}
}
}
}
Sample Response
{
"data": {
"rewardedUser": {
"id": "user_12345",
"nickName": "GamerPro",
"offers": {
"totalCount": 45,
"edges": [
{
"node": {
"id": "offer_67890",
"name": "Download SuperGame App",
"description": "Download and play SuperGame for 5 minutes to earn 100 points",
"trackingUrl": "https://track.example.com/click?offer=67890&user=12345",
"leadflow": "CPI",
"eventTypes": [
{
"id": "event_001",
"name": "App Install",
"description": "Download and install the SuperGame app",
"payout": {
"theyGet": 0.50,
"theyGetPoints": 50.0
},
"creativeUrl": "https://cdn.example.com/install_step.jpg",
"creativeThumbnail": "https://cdn.example.com/install_step_thumb.jpg"
},
{
"id": "event_002",
"name": "First Launch",
"description": "Open the app and complete the initial setup",
"payout": {
"theyGet": 0.25,
"theyGetPoints": 25.0
},
"creativeUrl": "https://cdn.example.com/launch_step.jpg",
"creativeThumbnail": "https://cdn.example.com/launch_step_thumb.jpg"
},
{
"id": "event_003",
"name": "Play 5 Minutes",
"description": "Play the game for at least 5 minutes",
"payout": {
"theyGet": 0.25,
"theyGetPoints": 25.0
},
"creativeUrl": "https://cdn.example.com/play_step.jpg",
"creativeThumbnail": "https://cdn.example.com/play_step_thumb.jpg"
}
],
"creatives": [
{
"title": "Main Campaign",
"creatives": [
{
"url": "https://cdn.example.com/creative_banner.jpg",
"type": "IMAGE"
},
{
"url": "https://cdn.example.com/creative_video.mp4",
"type": "VIDEO"
}
]
}
]
}
},
{
"node": {
"id": "offer_67891",
"name": "Complete Survey",
"description": "Answer a 5-minute survey about your gaming preferences",
"trackingUrl": "https://track.example.com/click?offer=67891&user=12345",
"leadflow": "CPL",
"eventTypes": [
{
"id": "event_004",
"name": "Survey Completion",
"description": "Complete the full survey with all questions answered",
"payout": {
"theyGet": 1.00,
"theyGetPoints": 100.0
},
"creativeUrl": "https://cdn.example.com/survey_completion.jpg",
"creativeThumbnail": "https://cdn.example.com/survey_completion_thumb.jpg"
}
],
"creatives": [
{
"title": "Survey Campaign",
"creatives": [
{
"url": "https://cdn.example.com/survey_banner.jpg",
"type": "IMAGE"
}
]
}
]
}
}
]
}
}
}
}
2. Get Current User's Completed Rewards
Query
query GetUserRewards {
rewardedUser {
rewards(pagination: {
offset: 0,
limit: 20
}) {
totalCount
edges {
node {
offer {
id
name
}
completed {
event {
name
description
}
theyGetPoints
theyGet
time
}
}
}
}
}
}Sample Response
{
"data": {
"rewardedUser": {
"rewards": {
"totalCount": 12,
"edges": [
{
"node": {
"offer": {
"id": "offer_67890",
"name": "Download SuperGame App"
},
"completed": [
{
"event": {
"name": "App Install",
"description": "User successfully installed the app"
},
"theyGetPoints": 50.0,
"theyGet": 0.50,
"time": "2024-07-08T14:30:00"
},
{
"event": {
"name": "First Launch",
"description": "User opened the app for the first time"
},
"theyGetPoints": 25.0,
"theyGet": 0.25,
"time": "2024-07-08T14:32:15"
}
]
}
},
{
"node": {
"offer": {
"id": "offer_67891",
"name": "Complete Survey"
},
"completed": [
{
"event": {
"name": "Survey Completion",
"description": "User completed the full survey"
},
"theyGetPoints": 100.0,
"theyGet": 1.00,
"time": "2024-07-09T10:15:30"
}
]
}
}
]
}
}
}
}
3. Generate Current User Performance Report
Query
query GetUserReport {
rewardedUser {
report(input: {
start: "2024-01-01T00:00:00",
end: "2024-12-31T23:59:59",
granularity: MONTH,
dimensions: [DATETIME, OFFER_ID]
}) {
rows {
dimensions {
dimension
value
}
theyGet
theyGetPoints
}
}
}
}Sample Response
{
"data": {
"rewardedUser": {
"report": {
"rows": [
{
"dimensions": [
{
"dimension": "DATETIME",
"value": "2024-06-01T00:00:00"
},
{
"dimension": "OFFER_ID",
"value": "offer_67890"
}
],
"theyGet": 2.50,
"theyGetPoints": 250.0
},
{
"dimensions": [
{
"dimension": "DATETIME",
"value": "2024-06-01T00:00:00"
},
{
"dimension": "OFFER_ID",
"value": "offer_67891"
}
],
"theyGet": 1.00,
"theyGetPoints": 100.0
},
{
"dimensions": [
{
"dimension": "DATETIME",
"value": "2024-07-01T00:00:00"
},
{
"dimension": "OFFER_ID",
"value": "offer_67890"
}
],
"theyGet": 1.75,
"theyGetPoints": 175.0
}
]
}
}
}
}Integration Best Practices
Pagination
Always use pagination for list queries to manage performance:
pagination: {
offset: 0,
limit: 20
}Offer Filtering
Use appropriate filters to show relevant offers:
Set
excludeCompleted: trueto hide already completed offersUse
autoFilter: trueto apply platform-based filteringAlternatively if
autoFilteris not used you can filter bycountryandosfor targeted offers
Tracking Implementation
Fire the `impressionUrl` when displaying offers to users
Use the `trackingUrl` to direct users to the offer
Monitor completion events to update reward balances
Error Handling
Implement proper error handling for network issues and GraphQL errors:
try {
const result = await graphqlClient.query({
query: GET_CURRENT_USER_OFFERS,
variables: {},
headers: {
'Authorization': `Bearer ${accessToken}`
}
});
return result.data;
} catch (error) {
console.error('API Error:', error.graphQLErrors);
// Handle error appropriately
} Custom Fields
Utilize custom fields to store additional user information that your app needs:
customFields: [
{ name: "preferred_category", value: "gaming" },
{ name: "user_level", value: "premium" },
{ name: "last_login_device", value: "ios" }
]
NOTE: Custom fields allow you to store any extra information about users that you want to display or use within your app, such as preferences, app-specific metadata, or user behavior data.
Status Management
User Status
ACTIVE: User can receive and complete offersPENDING: User registration is complete but requires manual approval in the backendINACTIVE: User is disabled
Offer Status
ACTIVE: Offer is available for completionINACTIVE: Offer is no longer available
Creative Assets
Offers include creative packs with various media assets:
Images, videos, and other promotional materials
Multiple creative options for A/B testing
Thumbnail URLs for quick loading
Rate Limiting and Performance
Use pagination to limit response sizes
Consider implementing local caching for frequently accessed user data
Support and Troubleshooting
When integrating the API:
Verify tracking URLs are firing correctly
Ensure reward calculations match expected values
Monitor completion events for accuracy
Implement logging for debugging purposes
During implementation, please ask your Swaarm account manager to create a communication channel with one of Swaarm's integration engineers. They will help you with any technical questions.
During development, we can implement certain queries for your app to ensure that the needed functionality is achieved. Please ask your Swaarm account manager or partner developer for more information.
