DocsIntegration
Reporting API
Pull your clicks, conversions, and earnings into your own dashboards, and check every transaction against the postbacks you received.
The Reporting API gives you the numbers from your dashboard as JSON: statistics for any period, grouped the way you need, and the full list of transactions. Use it to build your own reports, to compare traffic sources, and to check that you received a postback for every transaction.
Authentication
Use the same API key as for the Offers API. You find it in your dashboard under Apps, your app, Integration. Send it in the Authorization header:
Authorization: Bearer shk_your_api_key
Call the API from your server only. Each key only returns data of its own app. Reports work for apps that are live, paused, or still in testing.
Dates and time zone
All dates and times are in Budapest time (Europe/Budapest, CET or CEST), the same as in your dashboard. from and to are whole days in YYYY-MM-DD format, and both are included. Without them you get the last 30 days up to today. One request can cover up to 92 days: split longer periods into several requests.
A transaction belongs to the day it was created, even if it was credited or reversed later. Timestamps in responses are ISO 8601 with the offset, for example 2026-09-23T23:59:49+02:00.
Statistics
https://api.sharklio.com/v1/stats| Query parameter | Description |
|---|---|
fromoptionaldate, YYYY-MM-DD | First day, in Budapest time. Defaults to 29 days before to. |
tooptionaldate, YYYY-MM-DD | Last day, in Budapest time. Defaults to today. |
group_byoptionalstring | day (default), country, offer, integration, or sub1 to sub5. integration is embed, button, link, or api: how the user reached the offer. With day, every day of the period has a row, even without activity. Other groups are sorted by earnings, highest first. |
Every row has these fields. The totals object has only the counts (clicks, credited, pending, rejected, reversed), payout_usd, and reward.
| Field | Description |
|---|---|
day, country, offer, integration, or sub1 to sub5 | The group of the row, named after group_by. It is null for traffic without a value, for example clicks without sub1. With offer, the row also has offer_name. |
clicks | Offers your users started. |
credited, pending, rejected, reversed | Transactions in each state right now. A transaction that was credited and later reversed counts as reversed. |
payout_usd | Your earnings from credited transactions, in US dollars. |
reward | What your users received from credited transactions, in your currency. |
conversion_rate | Out of 100 clicks, how many led to at least one credited transaction, or null without clicks. A multi-step offer counts once, however many of its steps were credited, so this never goes above 100. credited still counts every credited step. |
epc_usd | Earnings per click in US dollars, or null without clicks. |
Conversions
https://api.sharklio.com/v1/conversionsEvery transaction of the period, oldest first, with the same values you receive in postbacks.
| Query parameter | Description |
|---|---|
from, tooptionaldate, YYYY-MM-DD | The period, in Budapest time, as for statistics. |
statusoptionalstring | credited, pending, rejected, or reversed. Leave it out to get all of them. |
user_idoptionalstring | Only transactions of this user, for example to answer a support request. |
limitoptionalinteger, 1 to 500 | Transactions per page. Defaults to 100. |
afteroptionalstring | The next_cursor of the previous page. Leave it out for the first page. |
{
"ok": true,
"from": "2026-09-01",
"to": "2026-09-07",
"timezone": "Europe/Budapest",
"currency": "Coins",
"count": 1,
"next_cursor": "1103",
"conversions": [
{
"transaction_id": "9ca45437948f42022b8118b0",
"user_id": "user_1234",
"status": "credited",
"offer_id": 120,
"offer_name": "Coin Quest - Install and open the app",
"offer_type": "offer",
"reward": 146,
"payout_usd": 0.225,
"country": "DE",
"device": "android",
"sub1": "homepage", "sub2": null, "sub3": null, "sub4": null, "sub5": null,
"created_at": "2026-09-03T23:59:49+02:00",
"decided_at": "2026-09-03T23:59:49+02:00",
"reversed_at": null
}
]
}
When next_cursor is not null, there are more transactions: send the same request again with after set to that value.
Check that you received every postback
Postbacks are retried for hours, but a server outage on your side can still make you miss one. Once a day, compare your records with the API:
- Request yesterday with
status=credited, and page through all results. - For every
transaction_idyou have not credited yet, credit the user withreward. - Do the same with
status=reversedfor transactions you credited but have not taken back.
Use transaction_id as the unique key, exactly as in your postback handler, so a transaction is never credited twice. You can also resend a failed postback from your dashboard under Logs.
Errors
Errors come as JSON with "ok": false, a stable error code, and a message for your logs.
| HTTP | error | What to do |
|---|---|---|
| 400 | invalid_date, invalid_range, range_too_long, invalid_group_by, invalid_status, invalid_limit, invalid_after, invalid_user_id | Fix the parameter named in the code. |
| 401 | invalid_api_key | Send the key in the Authorization header, and copy it again if you replaced it. |
| 403 | app_not_available | Reports are not available for rejected apps or suspended accounts. |
| 405 | method_not_allowed | Use GET. |
| 429 | rate_limited | Wait for the number of seconds in the Retry-After header. |
Limits
- Each app can make 60 reporting requests per minute. This limit is separate from the Offers API.
- Numbers for today change as users complete offers and advertisers review them. Figures for past days settle once pending transactions are decided.