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 behaviour 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
Mandatory
Description

eventType

string

Yes

Enum that describes the type of the event (check core events).

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 | ISO 8601 string

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 a purchase is made within the game.

Name
Type
Mandatory
Description

productId

string

No

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

meticaAttributes

object

No

Object provided by Metica, takes priority over productId. This object will be generated by the Personalized Offer endpoint

currencyCode

ISO 4217 string

Yes

Currency of the purchase; if undefined, totalAmount is considered in dollars ("USD").

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
Mandatory
Description

productId

string

No

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

meticaAttributes

object

No

This object will be generated by the Personalized Offer endpoint

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

This object will be generated by the Personalized Offer endpoint

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",
  "productId": "12345",
  "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",
  "meticaAttributes": {
    "placementId": "placement001",
    "offer": {
      "offerId": "offer123",
      "variantId": "variant456",
      "bundleId": "bundle789"
    },
    "interactionType": "click"
  }
}

Full User State Update

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

Name
Type
Mandatory
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
Mandatory
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
Mandatory
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
Mandatory
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.

Endpoint

/offers/v1/apps/<APP_ID>


Request Parameters

Name
Type
Description
Example

placements

string

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

?placements=main,shop


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": "America/Denver",
    "appVersion": "1.4.5",
    "locale": "en-US"
  },
  "userData": {
    "level": 10,
    "inventory": {
      "potion": { "quantity": 30 }
    },
    "gemBalance": 51
  }
}'

Response Example

{
  "placements": {
    "p1": [
      {
        "offerId": "offer_abc",
        "creativeId": "creative_large_bundle_94",
        "items": [
          {
            "id": "potion",
            "quantity": 1
          }
        ],
        "price": 50,
        "discount": 0.23,
        "currencyId": "gems"
      }
    ],
    "p2": []
  }
}

Smart Config

Description

The Smart Config endpoint allows you to fetch dynamic and personalized configurations.

  • The set of configuration keys can be restricted through the keys parameter.

  • If no keys are provided, the entire configuration will be returned.

In a similar manner to the Personalized Offers endpoint, the request payload can include user attributes that influence the choice of configurations.

Endpoint

/config/v1/apps/<APP_ID>


Request Headers

Header Name
Expected Value

X-API-KEY

Your unique API key.

Content-Type

application/json; charset=utf-8


Request Parameters

Name
Type
Description
Example

keys

string

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

?keys=cfg1,cfg2


Example Request Using curl

curl -X POST 'https://api-gateway.prod-eu.metica.com/config/v1/apps/<APP_ID>?keys=cfg1,cfg2' \
--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 Example

{
  "cfg1": 1.23,
  "cfg2": [
    "a",
    "b",
    "c"
  ]
}

Last updated