openapi: 3.2.0 info: title: ROI360 Net Revenue API (v2.0) Tax rate rules API description: 'ROI360 automatically calculates net in-app-purchase (IAP) and subscription revenue by deducting store commissions and local taxes from the gross amount. The default settings cover standard App Store and Google Play fees and taxes. If your store commission differs (e.g. Apple Small Business Program at 15%) or you operate in a country with special tax treatment, use the Net Revenue API to override the defaults. ROI360 applies the following default store commissions: - **IAP (one-time purchases):** 30% on both iOS and Android. - **Subscriptions:** 30% on iOS during the first 12 months, dropping to 15% thereafter; 15% on Android from day one. Default tax rates can be found [here](https://docs.google.com/document/d/e/2PACX-1vSl3DwlK2Gt2aa5gmDzD3-K3CtnIM85oMNrqx3PCTamwCERWYU48GugNpD31BFjA2PJjZnqaXIVe2Hx/pub). > ⚠️ > **Deprecation Notice:** API v1.0 (`/api/stores-taxes/v1.0/`) is deprecated. Please migrate to v2.0 (`/api/net-revenue/v2.0/`). ' version: 2.0.0 servers: - url: https://hq1.appsflyer.com/api/net-revenue/v2.0/ description: v2.0 - use this for all integrations - url: https://hq1.appsflyer.com/api/stores-taxes/v1.0/ description: v1.0 (deprecated, will be removed in a future release) security: - bearerAuth: [] tags: - name: Tax rate rules paths: /tax_rates/app/{app_id}: get: tags: - Tax rate rules summary: Get a filtered list of taxes or the entire tax catalog if no filters are provided description: Obtain tax catalog data for all available taxes or apply filters to narrow down the search based on specific tax attributes. parameters: - name: app_id in: path required: true schema: type: string description: App ID of the app for which you are getting tax rate rule catalog example: id123456789 - in: query name: format required: false schema: type: string enum: - csv - json default: json description: The output format of the tax catalog data. Defaults to 'json'. example: json - in: query name: tax_name required: false schema: type: string description: Filter catalog by the name appearing in the customer invoice that describes the specific type of tax, such as sales, VAT, GST. example: Sales - in: query name: tax_rate required: false schema: type: number format: double minimum: 0 maximum: 100 pattern: ^\d+(.\d{1,4})?$ description: Filter catalog by the percentage rate of the tax, specified up to 4 decimal places. example: 7.25 - in: query name: country required: false schema: type: string enum: - AF - AX - AL - DZ - AS - AD - AO - AI - AQ - AG - AR - AM - AW - AU - AT - AZ - BS - BH - BD - BB - BY - BE - BZ - BJ - BM - BT - BO - BA - BW - BV - BR - IO - BN - BG - BF - BI - KH - CM - CA - CV - KY - CF - TD - CL - CN - CX - CC - CO - KM - CG - CD - CK - CR - CI - HR - CU - CY - CZ - DK - DJ - DM - DO - EC - EG - SV - GQ - ER - EE - ET - FK - FO - FJ - FI - FR - GF - PF - TF - GA - GM - GE - DE - GH - GI - GR - GL - GD - GP - GU - GT - GG - GN - GW - GY - HT - HM - VA - HN - HK - HU - IS - IN - ID - IR - IQ - IE - IM - IL - IT - JM - JP - JE - JO - KZ - KE - KI - KR - KP - KW - KG - LA - LV - LB - LS - LR - LY - LI - LT - LU - MO - MK - MG - MW - MY - MV - ML - MT - MH - MQ - MR - MU - YT - MX - FM - MD - MC - MN - ME - MS - MA - MZ - MM - NA - NR - NP - NL - NC - NZ - NI - NE - NG - NU - NF - MP - 'NO' - OM - PK - PW - PS - PA - PG - PY - PE - PH - PN - PL - PT - PR - QA - RE - RO - RU - RW - BL - SH - KN - LC - MF - PM - VC - WS - SM - ST - SA - SN - RS - SC - SL - SG - SK - SI - SB - SO - ZA - GS - ES - LK - SD - SR - SJ - SZ - SE - CH - SY - TW - TJ - TZ - TH - TL - TG - TK - TO - TT - TN - TR - TM - TC - TV - UG - UA - AE - GB - US - UM - UY - UZ - VU - VE - VN - VG - VI - WF - EH - YE - ZM - ZW description: Filter catalog by the two-letter ISO country code where the tax is applied. - in: query name: subdivision required: false schema: type: string description: Filter catalog by the ISO 3166-2 subdivision code within the specified country. example: US-CA - in: query name: postal_code required: false schema: type: string description: Filter catalog by postal code to identify area-specific tax rates. example: L4J8E3 - in: query name: tax_exclusive required: false schema: type: boolean description: Filter by whether the tax is exclusive of the price. False means tax is included in the overall revenue. True means tax is in addition to the overall stated revenue. For example, in the USA or Canada, where the sticker price doesn't include sales tax. - in: query name: deduction_order required: false schema: type: integer enum: - 0 - 1 - 2 description: 'Filter catalog by the order deductions are applied against gross revenue. The deduction_order is an enum that can be set to one of 0, 1, or 2. - 0: Store commission is deducted first from the gross revenue and tax is deducted from the remaining amount. - 1: Tax is deducted first from the gross revenue and store commission is deducted from the remaining amount. - 2: Both tax and store commission are deducted from the total revenue. ' responses: '200': description: Integration returned content: application/json: schema: type: object properties: taxes: type: array items: type: object $ref: '#/components/schemas/TaxRateRule' '401': description: Missing authorization token content: application/json: schema: $ref: '#/components/schemas/Error' examples: MissingAuthorizationToken: summary: Missing authorization token value: message: Please contact your CSM for further information request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 '404': description: Token unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' examples: TokenUnauthorized: summary: Method not allowed value: message: Method not allowed request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 '405': description: Method not allowed content: application/json: schema: $ref: '#/components/schemas/Error' examples: MethodNotAllowed: summary: Token unauthorized value: message: Token unauthorized request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 '429': description: Rate limit exceeded content: application/json: schema: $ref: '#/components/schemas/Error' examples: InternalError: summary: Rate limit exceeded value: message: The rate limit is XXX requests per minute, please try again later request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 '500': description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' examples: InternalError: summary: Internal Server Error value: message: Internal error. please try again later. request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 post: tags: - Tax rate rules summary: Create tax rate rule description: 'Create custom tax rate rules for a specific app. > ⚠️ > **Note:** After you set a tax rate for a specific app + country, ROI360 stops applying default tax updates for that combination. ' parameters: - name: app_id in: path required: true schema: type: string description: App ID of the app for which you are setting the tax rate rule example: id123456789 requestBody: content: application/json: schema: type: object properties: taxes: type: array minItems: 1 items: $ref: '#/components/schemas/TaxRateRule' example: taxes: - tax_name: Portugal (EUR) tax_rate: 20 country: PT subdivision: '' postal_code: '' tax_exclusive: false deduction_order: 1 - tax_name: Croatia (EUR) tax_rate: 20 country: HR subdivision: '' postal_code: '' tax_exclusive: false deduction_order: 1 required: true responses: '200': $ref: '#/components/responses/Success' '400': description: Various errors content: application/json: schema: $ref: '#/components/schemas/Error' examples: InvalidJson: summary: Invalid json description: Invalid json value: message: Incorrect JSON format. Please verify and resubmit request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 MissingAppId: summary: Missing app_id description: Missing app_id value: message: 'integration 0: missing mandatory field ''app_id' request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 InvalidCountry: summary: invalid country value: message: Geo (country) code not identified. Please use an ISO 3166-1 alpha 2 (2 letter code) request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 SubdivisioPostalNoCountry: summary: Subdivision or Postal code without country description: Subdivision or Postal code without country value: message: Country must be defined for the returned object TaxRateAlreadyExists: summary: Tax rate already exists description: Tax rate already exists value: message: A tax rate is already defined for the returned object TaxRateMissing: summary: Tax rate missing description: Tax rate missing value: message: The parameter tax_rate is missing for the returned object request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 MissingCountry: summary: Missing country description: Missing country value: message: The parameter country is missing for the returned object request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 TaxNameMissing: summary: Missing tax name description: Missing tax name value: message: The parameter tax_name is missing for the returned object InvalidSourceEvent: summary: invalid source_event description: invalid source_event value: message: 'integration 0, appID=''com.config_4.test'', network=''chartboosts2s_int'': invalid source event suffix ''something_monetized' '401': description: Missing authorization token content: application/json: schema: $ref: '#/components/schemas/Error' examples: MissingAuthorizationToken: summary: Missing authorization token value: message: Get the API V2 token from your AppsFlyer admin request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 '404': description: Token unauthorized content: application/json: schema: $ref: '#/components/schemas/Error' examples: TokenUnauthorized: summary: Method not allowed value: message: Method not allowed request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 '405': description: Method not allowed content: application/json: schema: $ref: '#/components/schemas/Error' examples: MethodNotAllowed: summary: Token unauthorized value: message: Token unauthorized request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 '429': description: Rate limit exceeded content: application/json: schema: $ref: '#/components/schemas/Error' examples: InternalError: summary: Rate limit exceeded value: message: The rate limit is XXX requests per minute, please try again later request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 '500': description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' examples: InternalError: summary: Internal Server Error value: message: Internal error. Please try again later. request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 components: schemas: Error: properties: message: type: string request_id: type: string TaxRateRule: type: object required: - tax_name - tax_rate properties: tax_name: type: string description: 'Name appearing in the customer invoice that describes the specific type of tax, such as sales, VAT, GST  ' example: Sales tax_rate: type: number format: float description: 'Number up to 4 decimal places representing the tax percentage to be collected ' example: 7.25 tax_exclusive: type: boolean default: false description: 'Boolean parameter, either true or false. False means tax is included in the overall revenue. True means tax is in addition to the overall stated revenue. For example, in the USA or Canada, where the sticker price doesn''t include sales tax. ' country: type: string minItems: 0 enum: - AF - AX - AL - DZ - AS - AD - AO - AI - AQ - AG - AR - AM - AW - AU - AT - AZ - BS - BH - BD - BB - BY - BE - BZ - BJ - BM - BT - BO - BA - BW - BV - BR - IO - BN - BG - BF - BI - KH - CM - CA - CV - KY - CF - TD - CL - CN - CX - CC - CO - KM - CG - CD - CK - CR - CI - HR - CU - CY - CZ - DK - DJ - DM - DO - EC - EG - SV - GQ - ER - EE - ET - FK - FO - FJ - FI - FR - GF - PF - TF - GA - GM - GE - DE - GH - GI - GR - GL - GD - GP - GU - GT - GG - GN - GW - GY - HT - HM - VA - HN - HK - HU - IS - IN - ID - IR - IQ - IE - IM - IL - IT - JM - JP - JE - JO - KZ - KE - KI - KR - KP - KW - KG - LA - LV - LB - LS - LR - LY - LI - LT - LU - MO - MK - MG - MW - MY - MV - ML - MT - MH - MQ - MR - MU - YT - MX - FM - MD - MC - MN - ME - MS - MA - MZ - MM - NA - NR - NP - NL - NC - NZ - NI - NE - NG - NU - NF - MP - 'NO' - OM - PK - PW - PS - PA - PG - PY - PE - PH - PN - PL - PT - PR - QA - RE - RO - RU - RW - BL - SH - KN - LC - MF - PM - VC - WS - SM - ST - SA - SN - RS - SC - SL - SG - SK - SI - SB - SO - ZA - GS - ES - LK - SD - SR - SJ - SZ - SE - CH - SY - TW - TJ - TZ - TH - TL - TG - TK - TO - TT - TN - TR - TM - TC - TV - UG - UA - AE - GB - US - UM - UY - UZ - VU - VE - VN - VG - VI - WF - EH - YE - ZM - ZW description: 'Two-letter ISO country code for which the tax is applied > ⚠️ > When country, subdivision, and postal code fields are left empty, and the remaining parameters are included and valid, the default tax rule is applied. ' subdivision: type: string description: '> ⚠️ > Subdivision is null by default. The granularity of the tax_rate is derived from the most granular breakdown available based on the following hierarchy: country | subdivision | postal code. > For some countries, there can be an additional state/subdivision. This is handled according to [ISO 3166-2 subdivision codes](https://service.unece.org/trade/locode/2022-2%20SubdivisionCodes.htm). This must include the country code and subdivision code. ' example: US-CA postal_code: type: string description: 'String of numbers and letters that represents a group of people in a geographic area > ⚠️ > Postal_code is null by default. The granularity of the tax_rate is derived from the most granular breakdown available based on the following hierarchy: country | subdivision | postal code. ' example: L4J8E3 deduction_order: type: integer enum: - 0 - 1 - 2 default: 0 description: 'The deduction_order is an enum that can be set to one of 0, 1, or 2. - 0 - Store commission is deducted first from the gross revenue and tax is deducted from the remaining amount. - 1 - Tax is deducted first from the gross revenue and store commission is deducted remaining amount. - 2 - Both tax and store commission are deducted from the total revenue. ' responses: Success: description: Valid request content: application/json: schema: type: object properties: message: type: string request_id: type: string example: message: Successfully processed request_id: f1c0af47-bb7a-4e25-a261-d94d07689bb8 securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT description: 'To call the API, get the API V2 authorization token from your AppsFlyer admin. They can retrieve it from the AppsFlyer platform (HQ) '