REST API Integration

Overview

This document provides a comprehensive guide for integrating with Metica's REST API. It covers prerequisites, endpoints, request headers, authentication, payload structure, and advanced usage examples for event ingestion, personalized offers, smart configurations, and useful event data.


Prerequisites

Before initiating API requests, the Metica onboarding team will provide the following:

  • API Key: Used to authenticate requests.

  • Application ID: Used to identify the target application.

These credentials will be referred to as API_KEY and APP_ID throughout this document.


API Conventions

Base Endpoint

All API requests should be directed to the following base endpoint:

https://api-gateway.prod-eu.metica.com


Request Headers

Metica's API uses JSON for both request and response payloads. Additionally, some GET endpoints may use parameters formatted as application/x-www-form-urlencoded query strings in the URL.

Header Name
Expected Value

Content-Type

application/json; charset=utf-8


Authentication

Metica's API uses API keys for authentication and authorization. Include your API key in the X-API-KEY header for all API requests.

Example Using curl

curl --url https://api-gateway.prod-eu.metica.com/... \
  --header 'X-API-KEY: <API_KEY>'

HTTP Status Codes

Metica's API utilises standard HTTP status codes to indicate the outcome of an operation.

Code
Description

200

Successful Request - The request was processed successfully.

202

Accepted - The payload was accepted, and the request was completed successfully.

400

Bad Request - The request is invalid (e.g., malformed syntax or missing parameters).

401

Unauthorized - The request lacks valid authentication credentials.

403

Forbidden - The API key does not have sufficient permissions for the requested operation.

404

Not Found - The requested resource could not be located.

429

Too Many Requests - The rate limit has been exceeded; retry after a delay.

5xx

Internal Server Error - The server encountered an unexpected condition that prevented it from completing the request.

In cases of client errors (e.g., 400), responses may include a payload describing the invalid part of the request to assist in troubleshooting.


Event Ingestion

The event ingestion endpoint is the primary method for submitting user in-app behavior data to Metica.

Endpoint

/ingest/v1/events


Request Headers

Header Name
Expected Value

X-API-KEY

Your unique API key.

Content-Type

application/json; charset=utf-8


Request Payload

The payload should include a list of events, with each event containing key-value pairs representing individual user actions.

Example Payload

{
  "events": [
    {
      "userId": "u1",
      "appId": "<APP_ID>",
      "eventTime": "2024-11-28T15:19:07.458Z",
      "eventType": "purchase",
      "offerId": "a",
      "totalAmount": 1
    },
    {
      "userId": "u2",
      "appId": "<APP_ID>",
      "eventTime": "2024-11-28T15:24:07.000Z",
      "eventType": "login"
    }
  ]
}

Example Request Using curl

curl --request POST \
  --url https://api-gateway.prod-eu.metica.com/ingest/v1/events \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: <API_KEY>' \
  --data '{
    "events": [
      {
        "userId": "u1",
        "appId": "<APP_ID>",
        "eventTime": "2024-11-28T15:19:07.458Z",
        "eventType": "purchase",
        "offerId": "a",
        "totalAmount": 1
      },
      {
        "userId": "u2",
        "appId": "<APP_ID>",
        "eventTime": "2024-11-28T15:24:07.000Z",
        "eventType": "login"
      }
    ]
  }'

Response Codes

Code
Description

202

The request was processed successfully. Note A 202 response indicates the request was accepted but does not guarantee the validity of the payload content.

4xx

Client error; refer to the HTTP Status Codes section for details.

5xx

Server error; refer to the HTTP Status Codes section for details.


Event Schema

This section lists the schema for core events that Metica can ingest. Each core event requires specific properties to be included in the event payload, as described below.

Base Fields

The base fields are common to all core events and must be included in every event payload.

Name
Type
Required
Description

eventType

string

Yes

eventId

string

No

Uniquely identifies the event; if undefined, it will be created at ingestion time by Metica.

appId

string

Yes

Refers to the external application ID defined during onboarding.

eventTime

bigint |

Yes

UTC timestamp of when the event occurred.

userId

string

Yes

Uniquely identifies the user within this application.

customPayload

object

No

Represents a custom object defined by each client


Core Events

Purchase

An event triggered every time an in-app purchase is made within the game.

Name
Type
Required
Description

productId

string

No

Unique ID of an in-game product. Only one between productId and meticaAttributes should be populated.

meticaAttributes

object

No

currencyCode

Yes

Currency of the purchase

totalAmount

number

Yes

Total amount of the purchase expressed as double.

Example Payload:

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "appId": "<APP_ID>",
  "eventTime": "2024-11-01T10:00:00Z",
  "userId": "d8973ecd-c2b5-4efb-8b91-935ae4c5b201",
  "eventType": "purchase",
  "meticaAttributes": {
    "offer": {
      "offerId": "offer123",
      "variantId": "variant456",
      "bundleId": "bundle789"
    },
    "placementId": "placement001"
  },
  "currencyCode": "EUR",
  "totalAmount": 25.00
}

or

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "appId": "<APP_ID>",
  "eventTime": "2024-11-01T10:00:00Z",
  "userId": "d8973ecd-c2b5-4efb-8b91-935ae4c5b201",
  "eventType": "purchase",
  "productId": "12345",
  "currencyCode": "EUR",
  "totalAmount": 25.50
}

Offer Impression

This event triggers every time an offer is displayed.

Name
Type
Required
Description

productId

string

No

Unique ID of an in-game product. Only one between productId and meticaAttributes should be populated.

meticaAttributes

object

No

Example Payload:

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "appId": "<APP_ID>",
  "eventTime": "2024-11-01T10:00:00Z",
  "userId": "d8973ecd-c2b5-4efb-8b91-935ae4c5b201",
  "eventType": "impression",
  "meticaAttributes": {
    "placementId": "placement001",
    "offer": {
      "offerId": "offer123",
      "variantId": "variant456",
      "bundleId": "bundle789"
    }
  }
}

or

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "appId": "<APP_ID>",
  "eventTime": "2024-11-01T10:00:00Z",
  "userId": "d8973ecd-c2b5-4efb-8b91-935ae4c5b201",
  "eventType": "impression",
  "productId": "12345"
}

Offer Interaction

Event triggers every time an interaction is made with an offer (e.g., click, dismiss).

Name
Type
Required
Description

productId

string

No

Unique ID of an in-game product. Mandatory if meticaAttributes is missing.

interactionType

string

No

String that defines the type of interaction, i.e. click, rejected, etc...; mandatory if meticaAttributes is missing.

meticaAttributes

object

No

Example Payload:

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "appId": "<APP_ID>",
  "eventTime": "2024-11-01T10:00:00Z",
  "userId": "d8973ecd-c2b5-4efb-8b91-935ae4c5b201",
  "eventType": "interaction",
  "meticaAttributes": {
    "placementId": "placement001",
    "offer": {
      "offerId": "offer123",
      "variantId": "variant456",
      "bundleId": "bundle789"
    },
    "interactionType": "click"
  }
}

or

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "appId": "<APP_ID>",
  "eventTime": "2024-11-01T10:00:00Z",
  "userId": "d8973ecd-c2b5-4efb-8b91-935ae4c5b201",
  "eventType": "interaction",
  "productId": "12345",
  "interactionType": "click"
}

AdRevenue

An event triggered every time revenue is generated by an ad within the game.

Name
Type
Required
Description

currencyCode

Yes

Currency of the total amount

totalAmount

number

Yes

Total amount generated by the ad expressed as double.

placement

string

No

String that represents the place where the ad has been displayed inside the game, i.e. shop_daily_reward

type

string

No

Type of ad that has been displayed, i.e. video, banner, etc...

source

string

No

Source of the ad, i.e. apploving, unity, etc...

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "appId": "<APP_ID>",
  "eventTime": "2024-11-01T10:00:00Z",
  "userId": "d8973ecd-c2b5-4efb-8b91-935ae4c5b201",
  "eventType": "adRevenue",
  "currencyCode": "EUR",
  "totalAmount": 0.00123373762,
  "placement": "shop_daily_reward_double",
  "type": "video",
  "source": "unity"
}

Full User State Update

Event triggers at regular intervals, indicating the user’s current state.

Name
Type
Required
Description

userStateAttributes

object

Yes

Attributes that represent the user's current state.

Example Payload:

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "appId": "<APP_ID>",
  "eventTime": "2024-11-01T10:00:00Z",
  "userId": "d8973ecd-c2b5-4efb-8b91-935ae4c5b201",
  "eventType": "fullStateUpdate",
  "userStateAttributes": {
    "level": 5,
    "inventoryBalance": 100,
    "isActive": true
  }
}

Partial User State Update

Triggers when the user state changes, updating only the affected properties.

Name
Type
Required
Description

userStateAttributes

object

Yes

Attributes that have changed values in the user's state.

Example Payload:

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "appId": "<APP_ID>",
  "eventTime": "2024-11-01T10:00:00Z",
  "userId": "d8973ecd-c2b5-4efb-8b91-935ae4c5b201",
  "eventType": "partialStateUpdate",
  "userStateAttributes": {
    "level": 6
  }
}

Login

Event triggers when the user enters the app, one event per session.

Name
Type
Required
Description

(No Fields)

Yes

No additional fields required.

Example Payload:

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "appId": "<APP_ID>",
  "eventTime": "2024-11-01T10:00:00Z",
  "userId": "d8973ecd-c2b5-4efb-8b91-935ae4c5b201",
  "eventType": "login"
}

Install

Event triggers when the user installs the app.

Name
Type
Required
Description

(No Fields)

Yes

No additional fields required.

Example Payload:

{
  "eventId": "550e8400-e29b-41d4-a716-446655440000",
  "appId": "<APP_ID>",
  "eventTime": "2024-11-01T10:00:00Z",
  "userId": "d8973ecd-c2b5-4efb-8b91-935ae4c5b201",
  "eventType": "install"
}

Personalized Offers

The personalized offers endpoint enables you to fetch offers tailored to specific users based on their attributes or device information. These offers are returned grouped by placements. Each placement can contain one or more offers.


Endpoint

POST /offers/v1/apps/<APP_ID>

Use this endpoint to retrieve personalized offers for specific placements within your app.


Request Headers

Header Name
Expected Value

X-API-KEY

Your unique API key.

Content-Type

application/json; charset=utf-8


Request Parameters

Name
Type
Required
Description
Example

placements

string

No

A comma-separated list of placements for which offers should be returned. If not provided, offers for all placements will be returned.

?placements=main,shop


Request Body Schema

A JSON-encoded body must be included in the request. The request body should adhere to the following schema:

Field Name
Type
Required
Description
Example

userId

string

Yes

Unique identifier for the user.

"abc"

deviceInfo

object

No

Information about the user's device. Can be partially filled.

See fields below.

deviceInfo.store

string

No

The platform's app store (AppStore or GooglePlayStore)

"AppStore"

deviceInfo.timezone

string

No

Device timezone as an IANA identifier or UTC offset.

"Europe/London"

deviceInfo.appVersion

string

No

The app version, following the Semantic Versioning format.

"1.4.5"

deviceInfo.locale

string

No

The user's locale, formatted according to IETF BCP 47.

"en-US"

userData

object

No

See example below.

Example Request Body:

{
  "userId": "abc",
  "deviceInfo": {
    "store": "AppStore",
    "timezone": "Europe/London",
    "appVersion": "1.4.5",
    "locale": "en-US"
  },
  "userData": {
    "level": 10,
    "inventory": {
      "potion": {
        "quantity": 30
      }
    },
    "gemBalance": 51
  }
}

Response Schema

The response includes a list of offers for each placement, sorted from the most important to the least important. Each offer contains details about the offer's ID, items, pricing, and additional metadata.

Field Name
Type
Description
Example

placements

object

A mapping of placement IDs to their corresponding offers.

See example below.

offerId

string

Unique identifier for the offer.

"offer_abc"

creativeId

string | undefined

Reference to the creative ID associated with the offer.

"creative_large"

creativeOverride

string | undefined

Override for the creative associated with the offer.

"override_123"

items

array

List of items included in the offer, each with an ID and quantity.

See below.

items[].id

string

The external ID of the item.

"potion"

items[].quantity

number

The quantity of the item included in the offer.

1

expirationTime

string | undefined

Expiration time of the offer in ISO 8601 format.

"2025-01-16T12:00:00Z"

iap

string | undefined

IAP product ID associated with the offer.

"iap_product_45"

price

number | undefined

Price of the offer.

50

discount

number | undefined

Discount applied to the offer, expressed as a value between 0 and 1 (e.g., 0.23 = 23%).

0.23

currencyId

string | undefined

Currency used for the offer price (e.g., fiat or in-game currency).

"gems"

customPayload

object | undefined

Custom object defined by the client.

{...}

metrics

object

{...}


Example Response

{
  "placements": {
    "p1": [
      {
        "offerId": "offer_abc",
        "creativeId": "creative_large_bundle_94",
        "items": [
          {
            "id": "potion",
            "quantity": 1
          }
        ],
        "expirationTime": "2025-01-16T12:00:00Z",
        "iap": "iap_potion_bundle",
        "price": 50,
        "discount": 0.23,
        "currencyId": "gems",
        "customPayload": {
          "additionalInfo": "special offer"
        },
        "metrics": {
          "purchase": {
            "userId": "abc",
            "appId": "<APP_ID>",
            "meticaAttributes": {
              "offer": {
                "offerId": "11655",
                "variantId": "14554",
                "bundleId": "14904"
              },
              "placementId": "6200"
            },
            "eventType": "meticaOfferInAppPurchase"
          },
          "display": {
            "userId": "abc",
            "appId": "<APP_ID>",
            "meticaAttributes": {
              "offer": {
                "offerId": "11655",
                "variantId": "14554",
                "bundleId": "14904"
              },
              "placementId": "6200"
            },
            "eventType": "meticaOfferImpression"
          },
          "interaction": {
            "userId": "abc",
            "appId": "<APP_ID>",
            "meticaAttributes": {
              "offer": {
                "offerId": "11655",
                "variantId": "14554",
                "bundleId": "14904"
              },
              "placementId": "6200"
            },
            "eventType": "meticaOfferInteraction"
          }
        },
      }
    ],
    "p2": []
  }
}

Example Request Using curl

curl -X POST 'https://api-gateway.prod-eu.metica.com/offers/v1/apps/<APP_ID>?placements=p1,p2' \
--header 'Content-Type: application/json; charset=utf-8' \
--header 'X-API-KEY: <API_KEY>' \
--data '{
  "userId": "abc",
  "deviceInfo": {
    "store": "AppStore",
    "timezone": "Europe/London",
    "appVersion": "1.4.5",
    "locale": "en-US"
  },
  "userData": {
    "level": 10,
    "inventory": {
      "potion": { "quantity": 30 }
    },
    "gemBalance": 51
  }
}'

Notes

  • The placements parameter is optional. If omitted, the response will include offers for all available placements.

  • Only userId is mandatory in the request body; other fields are optional and can be partially filled.

  • The metrics field in the response payload contains lifecycle event tracking data that should be reported back to Metica when corresponding events occur.

  • Replace <APP_ID> and <API_KEY> with your application's unique identifiers.


Smart Config

The Smart Config endpoint allows you to fetch dynamic and personalized configurations tailored to specific users based on their attributes or device information. The set of configuration keys can be restricted using the keys parameter. If no keys are specified, all the configurations will be returned.


Endpoint

POST /configs/v1/apps/<APP_ID>

Use this endpoint to retrieve personalized configurations for a specific application.


Request Headers

Header Name
Expected Value

X-API-KEY

Your unique API key.

Content-Type

application/json; charset=utf-8


Request Parameters

Name
Type
Required
Description
Example

keys

string

No

A comma-separated list of configuration keys to fetch. If not provided, all configuration keys will be returned.

?keys=difficulty,suggested_prices


Request Body Schema

Field Name
Type
Required
Description
Example

userId

string

Yes

Unique identifier for the user.

"abc"

deviceInfo

object

No

Information about the user's device. Can be partially filled.

See fields below.

deviceInfo.store

string

No

The platform's app store (AppStore or GooglePlayStore).

"AppStore"

deviceInfo.timezone

string

No

Device timezone as an IANA identifier or UTC offset.

"Europe/London"

deviceInfo.appVersion

string

No

The app version, following the Semantic Versioning format.

"1.4.5"

deviceInfo.locale

string

No

The user's locale, formatted according to IETF BCP 47.

"en-US"

userData

object

No

See example below.

Example Request Body:

{
  "userId": "abc",
  "deviceInfo": {
    "store": "AppStore",
    "timezone": "Europe/London",
    "appVersion": "1.4.5",
    "locale": "en-US"
  },
  "userData": {
    "level": 10,
    "inventory": {
      "potion": {
        "quantity": 30
      }
    },
    "gemBalance": 51
  }
}

Example Request Using curl

curl -X POST 'https://api-gateway.prod-eu.metica.com/configs/v1/apps/<APP_ID>?keys=difficulty,suggested_prices' \
--header 'Content-Type: application/json; charset=utf-8' \
--header 'X-API-KEY: <API_KEY>' \
--data '{
  "userId": "abc",
  "deviceInfo": {
    "store": "AppStore",
    "timezone": "America/Denver",
    "appVersion": "1.4.5",
    "locale": "en-US"
  },
  "userData": {
    "level": 10,
    "inventory": {
      "potion": { "quantity": 30 }
    },
    "gemBalance": 51
  }
}'

Response Schema

The response includes a mapping of configuration keys to their respective values defined inside the Metica platform. Each configuration key can return various types of data, such as numbers, strings, arrays, or objects.

Example response body of two configured keys:

{
  "difficulty": "hard",
  "suggested_prices": [
    4.99,
    9.99,
    12.99
  ]
}

Notes

  • The keys parameter is optional. If omitted, the response will include all available configuration keys.

  • Only userId is mandatory in the request body; other fields are optional and can be partially filled.

  • The returned configurations are dynamically generated based on the provided user attributes.

  • Replace <APP_ID> and <API_KEY> with your application's unique identifiers.

Last updated

Was this helpful?