InCost API for ad networks

At a glance: InCost API, part of AppsFlyer ROI360, lets ad network partners programmatically send advertising cost data to AppsFlyer. Doing so provides advertisers with aggregate cost data from all their ad networks in one place.

InCost API 

Ad network partners send detailed advertising cost using InCost API. AppsFlyer ingests the data making it available to advertisers and partners via reports, analytics, and an AWS S3 bucket.

Related reading: Cost-sharing options for ad networks

Implementation requirements for ad networks

Complete the steps in the sequence listed.

# Action 
1 Fill out the InCost onboarding form.
2 Reach out to your AppsFlyer PDM and let them know you want to integrate InCost.
3 Make sure campaign hierarchies (campaign ID, adset ID, and ad ID) are included on your attribution links for more than 90% of your traffic.

The ad network admin gets the AppsFlyer V2.0 API token in the AppsFlyer dashboard. 


Complete InCost integration and testing as described in this article.

  • Notify your AppsFlyer PDM that you have completed the testing.
  • Wait for the PDM to confirm that your integration is operational.

Request advertisers to enable get cost data in the cost tab of your AppsFlyer integrated partner page. 

Process for sending and verifying data


  • Prepare cost data for submission in a JSON as detailed in this article. 
  • Take into consideration the app time zone to align cost data dates with that of the app. 
  • Use InCost uploader to send the cost. 
  • Collect and store the job ID that InCost returns.
  • After 2 minutes, use the job status method to verify the job has completed successfully.
  • Jobs that complete successfully have an applied status. It can take up to 5 hours for data to appear in the AppsFlyer dashboard.

InCost API methods

Method Description Method
Get app permission list
  • List of apps (app IDs) for which advertisers have enabled InCost integration with you. 
  • Frequently check the list programmatically to update the list of apps for whom you send data. Remember: advertisers add apps regularly. 
  • The API returns the app ID, name, time zone, and app-selected currency.
InCost upload
  • Send cost data in a JSON.
  • InCost uploader returns a job ID.
  • Use it to check the job status.
Get job status
  • Query job status using the job ID.
  • Verify that the submitted job has an applied status.
  • If this is not the case, correct errors and resubmit.
  • A matched record score of less than 100(%) can indicate erroneous data.   
  • Matching occurs when campaign attribution data, like clicks, matches campaign cost data.

InCost API basics


Path parameters (mandatory)
  • app_id: Is the app identifier as found in the AppsFlyer dashboard. Insert it exactly as it appears in the dashboard.
  • Ensure to prefix iOS apps with id.
  • Accepted content type: application/json
  • Authorization: Bearer token 
  • Accept: application/json


  • The AppsFlyer V2.0 API token is available to the admin in the AppsFlyer dashboard. The same token is used irrespective of the app or advertiser.
Date limitations
  • Earliest date allowed: Previous 90 days relative to the current date.
  • Most recent date allowed: The current date.
Rate limitation

API call-rate limited per ad network account (token):

  • 150 calls per minute
  • 1000 calls per day 
  • File size limit: 1 MB

InCost upload method 

Use the InCost upload method to report cost.  

API requests must comply with the following: 

  • One app per API call. 
  • Data format is JSON as depicted in the Curl example.
  • Each JSON contains the campaign cost details for a specified date.
  • Mandatory fields must be populated. Meaning, don't send empty fields. 
  • Media source is restricted to media sources associated (registered under) your ad network account. Get the list from your partner development manager.
  • If there are fields that are not part of your campaign cost reporting hierarchy, don’t include them in your request. For example, adset ID, asset name, ad ID, ad name.


Path parameters  (mandatory)
  • app_id: Is the app identifier as found in the AppsFlyer dashboard. Insert it exactly as it appears in the dashboard.
  • Ensure to prefix iOS apps with id.
Response Provided

Cost fields in the JSON






  • Spend date
  • Format: YYYY-MM-DD
  • Example:2019-12-30


  • The app ID as it appears in the AppsFlyer platform
  • Format: String up to 250 characters
  • Example: id123456789



  • Network name (ID) displaying the ad associated with your ad network partner account in AppsFlyer
  • Format: String 50 characters
  • Example: network_int



  • Required for agency attribution and cost data.
  • Agency name as it displays on the attribution link and is associated with the agency account in AppsFlyer.
  • Format: String 50 characters
  • Example: agencya



  • Must be identical to the af_c_id param sent on the attribution link
  • Empty string not permitted
  • Format: String 24 characters
  • Example: 123abc



  • Format: String 100 characters
  • Example: my_campagin123


  • Required if you send adset_name 
  • Must be identical to the af_adset_id param sent on the attribution link
  • If your cost reporting does not support adset_id, never send it
  • Format: String 24 characters
  • Example: 123A



  • If you send this field, you must also send adset_id
  • Format: String 100 characters
  • Example:my_adset_name



  • Required if you send ad_name.
  • This field must be identical to the af_ad_id param sent on the attribution link
  • If your cost reporting does not support adset_id, never send it
  • Format: String 24 characters
  • Example:123AB



  • Unique ID that identifies the publisher that displays the ad.
  • Format: String 24 characters.



  • If you send this field, you must also send ad_id
  • Format: String 100 characters
  • Example:Ad-name



  • The country you recorded as associated with the cost
  • Where possible, this should represent the country where the ad was displayed
  • Format: ISO 3166 2 character country code
  • Example:US, CN, ZA


  • Spend currency type
  • Format: ISO 4217 3-character currency code
  • Example: USD, EUR, ZAR
spend  Yes
  • Spend amount using the specified currency 
  • Five digits allowed after the decimal point
  • The value 0 (zero) is permitted
  • Negative values are NOT permitted
  • Don't send , delimiters
  • Don't send values in quotation marks. 
  • Format: Decimal number
  • Example values: 1 1.2 1234.20
channel No
  • Must be identical to the af_channel param sent on the attribution link
  • Format: String 20 chars
  • Example:my_channel
keywords No
  • Format: String 100 chars
  • Example:abc app

* See the remarks column, as in some cases you must send this field.

InCost upload Curl example

curl --location --request POST '' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer ' \
    "date": "2020-02-28",
    "app_id": "",
    "media_source": "example_int",
    "campaign_id": "1236678",
    "campaign_name": "example_campaign",
    "geo": "ZA",
    "currency": "ZAR",
    "spend": 123.12
    "date": "2020-02-29",
    "app_id": "",
    "media_source": "exmaple_int",
    "campaign_id": "123",
    "campaign_name": "Campaign123",
    "geo": "IL",
    "currency": "USD",
    //make sure the value for "spend" does NOT have quotation marks, as indicated below.
    "spend": 2400 

Get job status method

The method returns the status/error message of a previously submitted send cost data call in a JSON.



Make sure to set the method to GET .

Path parameters (mandatory)
  • app_id: The app identifier as found in the AppsFlyer dashboard. Insert it exactly as it displays in the dashboard.
  • job_id: The job identifier returned by the send cost data call. 


Status Description
  • Job submission completed successfully.
  • Dashboards and reports on the platform will update within 5 hours.
Job in progress Job is not yet complete.
Validation error
  • Data validation error.
  • See the specific error message.
  • Make corrections and submit the request again.
Error processing data AppsFlyer system problem. Wait 15 minutes and try again. If the error persists, contact AppsFlyer technical support. 
Get job status Curl example 
curl --location --request GET '<app_id_placeholder>/job/<job_id placeholder>' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer '<api_token_placeholder. Note the token has more than 700 characters.>'

get job status responses examples

Status Description


    "date_from": "2020-02-21",
    "date_to": "2020-02-28",    
    "matched_records_percentage" : 85,
    "app_id": "",
    "status": "Applied",
    "Uploaded request url": "https://domain/file.json"
Invalid date
      "id": "",
"status": "Failed",
"Uploaded request url": "https://domain/file2.json",
"error" : [ {
"af_error_code": “ic211”,
"error_message" : "Incorrect date format. Use the format yyyy-mm-dd."

Testing InCost integration

The following apps are available in your dashboard for testing:

  • Android:
  • iOS: id888123456

To test cost integration:

  1. [Optional] End-to-end-attribution test:
    1. Prepare attribution links for the test applications using the attribution-link template configured for your integration. 
    2. Generate attribution traffic for clicks, including campaign, adset, ad ID so that the cost data can match with the click data.
    3. Generate a click for the test applications, using the attribution-link template configured in your integration. Make sure to populate macros, as if this was real traffic.
  2. [Mandatory] Basic cost integration:
    1. Prepare test data.
    2. Submit the data, use InCost uploader.
    3. Record the job ID that returns.
    4. Wait 2 minutes.
    5. Verify that no errors were found. Use get job status.
      Note: Because there is no attribution traffic (clicks), the matched row score will be less than 100. 
    6. If errors are found, make corrections, and submit again.
    7. Cost data will display in the dashboard within 5 hours, verify that the data is correct.

Error messages

The following error codes and message return.

Category InCost error code Error message
Rate Limit ic111 Exceeded API-rate limit. Wait one minute and try again.
Data Validation ic211 Incorrect date format. Use the format yyyy-mm-dd.
Data Validation ic212 XXX is in the future. Future dates are not allowed.
Data Validation ic213 media_source XXX was not found. Verify and resubmit.
Data Validation ic215 app_id was not found. Verify and resubmit.
Data Validation ic217 Insufficient cost amount. Spend amount must be greater than 0.
Data Validation ic218 Reserved
Data Validation ic219 Geo (country) code was not found. Use an ISO 3166 2-letter code.
Data Validation ic220 Currency code was not found. Use an ISO 4217 2-letter code.
Data Validation ic221 Request had 2 or more currencies. Send 1 currency per app per request.
Data Validation ic222 Request had 1 or more duplicate records. Remove file duplication/s.
Data Validation ic224 Job ID was not found. Verify and resubmit.
Data Validation ic225 Status was not found. Verify and resubmit.
Data Validation ic226 Incorrect count value. Use a number between 1-1000.
Data Validation ic227 Incorrect cursor. Use the cursor from the last response.
File Size ic311 File exceeds 25MB. Split the file into multiple requests.
Authentication ic414 Partner account lacks permissions. Partner account must be enabled to upload cost for this app.
Formatting ic416 Incorrect JSON format. Verify and resubmit.
General error ic300 There is a server issue. Try again in 10 minutes.
Authorization ic415 App and job IDs don't match. Verify and try again.
Data Validation ic228 Request had 2 or more app IDs; the maximum is 1 per request. Split the request and resubmit.
Data Validation ic229 Request and URL app IDs don't match. Verify the app IDs match and resubmit.
Data Validation ic230  
Data Validation ic231 Request included data of varying granularity; the data must be uniform. If varying granularity is required, split the request and resubmit.
Data Validation ic232 Some request data was outside the allowed time range; the data must be from the last 90 days. Verify the data and resubmit.
Data Validation ic241 Incorrect click values. Use positive numbers only. Verify and resubmit.
Data Validation ic242 Incorrect impression values. Use positive numbers only. Verify and resubmit.
Data Validation ic243 Incorrect time zone code. Use a valid AppsFlyer code per
Authorization ic301 Incorrect agency name. Use a valid agency name in the URL, then make an upload request.
Authorization ic302 App ID is not enabled for ROI360. The agency can only share cost data with an advertiser who has the ROI360 feature.
Authorization ic302 App ID is not enabled for cost integration. The agency must enable the cost toggle, then resend the data.
Data Validation ic244 Incorrect partner name. Enter a valid name in the partner field and resubmit.
Data Validation ic245 Campaign ID can't be sent in the request. Remove the campaign ID and resubmit.
Data Validation ic246 Campaign name was not found. Verify and resubmit.
Data Validation ic248 Request contain invalid field names, or missing mandatory fields.

Enabling get cost data by the advertiser

  • Advertisers enable Get Cost Data in the AppsFlyer dashboard using the procedure that follows. 
  • The advertiser must enable get cost data for each app individually. Verify that you are enabled by using get InCost enabled app list API.

To enable get cost data from the ad network: 

  1. In AppsFlyer, go to Integration > Active Integrations.
  2. Select the integrated partner (ad network name in AppsFlyer).
  3. Go to Cost tab.


  4. Enable Get Cost Data.
    AppsFlyer is permitted to record cost data from the partner. 
    For the avoidance of doubt, don't give your API token to the ad network. They don't need it.