Skip to main content

Rewarded App Development Guide - How to use the Swaarm Rewarded API

End-to-end Rewarded API guide for integrating Swaarm as a Rewarded Management Platform

Updated over a week ago

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 Swaarm

  • email: User's email address (required)

  • nickName: Display name for the user

  • firstName, lastName: Optional personal information

  • customFields: 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 activity

  • internalId: User's id given by the app if one exists

  • referralId: Id of the user that referred this user


Creating and Updating Users

  • Create User - Use the RewardedUserInput to 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 RewardedUserUpdateInput to 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

  1. The rewarded user earns rewards in the app

  2. Rewards accumulate as available balance

  3. The user requests a payment via the Rewarded API

  4. The payment request appears in the Swaarm platform

  5. Once a payment request is made, the requested funds move to pending balance

  6. An admin approves or denies the request

  7. 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

  1. Ensure the payment status is PAID

  2. Check for a url in paymentProcessorResponse

  3. 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: true to hide already completed offers

  • Use autoFilter: true to apply platform-based filtering

  • Alternatively if autoFilter is not used you can filter by country and os for 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 offers

  • PENDING: User registration is complete but requires manual approval in the backend

  • INACTIVE: User is disabled

Offer Status

  • ACTIVE: Offer is available for completion

  • INACTIVE: 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:

  1. Verify tracking URLs are firing correctly

  2. Ensure reward calculations match expected values

  3. Monitor completion events for accuracy

  4. 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.

Did this answer your question?