> For the complete documentation index, see [llms.txt](https://help.smartico.ai/welcome/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://help.smartico.ai/welcome/technical-guides/communication-gateways/custom-push-gateways.md).

# Custom push gateways

Smartico is integrated with Google Firebase to deliver push notifications for Android and iOS setups, and with Huawei Push Kit for Huawei phones without Google services (see [Push configurations](https://help.smartico.ai/welcome/technical-guides/front-end-integration/push-configurations)). Firebase is a free service and doesn't require additional contract signing or complex configurations.

However, there may be instances where push notifications need to be delivered through different services or gateways. For these specific scenarios, Smartico offers two alternative integration methods:

* "smartico-by-token" - In such a scenario, Smartico's front-end still collects push tokens from the browsers and native applications and handles their life-cycle (associating token with the user, invalidating in case of token expiration)
* "smartico-by-user" - in such a scenario, the Operator should take care about managing push tokens. Smartico will address push notifications using "user id"

For setups with multiple mobile applications (such as separate iOS and Android native apps), the server configuration JSON can be structured as a dictionary keyed by application package ID (such as "com.operator.app") with an optional "default" fallback, routing each app to its own gateway URL or Firebase project.

To enable these configurations, the push gateway has to be configured in the following way in Smartico BackOffice.

In the BackOffice, navigate to Settings → Label Settings (or Brand Settings for a specific brand) → Push notifications, and locate the "Firebase / Huawei server keys for push notifications" field. Replace any existing Firebase service account JSON in this field with your custom gateway JSON configuration.

```json
{
    // type of the integration - "smartico-by-token" or "smartico-by-user"
    "gateway-type": "smartico-by-token",
    // URL of the custom gateway that will be called by smartico to deliver the push token
    "URL": "https://some.com/post_handler",
    // auth key that will be sent in the HTTP-header: 'Authorization'
    "auth_key": "some_secret_key"
}
```

The provided URL should expect the following POST message.

### Optional Gateway Configuration Parameters

You can include optional parameters in the configuration JSON:

* Custom HTTP headers: Supply additional key-value header pairs to send with every dispatch request. Dynamic placeholders for brand ID and user wallet currency are supported.
* Custom payload properties: Provide additional static key-value pairs to merge directly into the root level of the outgoing JSON request body.
* Time-to-live: Specify an expiration time in seconds for the push notification.

```json
{
  // ID of the user in the smartico system
  "user_id": 123123123,
  // ID of the user on operator side
  "user_ext_id": "1123123",
  // ID of the brand, relevant for the multi-brand setups
  "ext_brand_id": "mybrand1",
  // push token for the type of integration "smartico-by-token"
  "push_token": "e311mfDpNx4:APA91bFzTRPjTNMHGBIyrqF46zHQmOk0l77GHHDNlX7MX-PbxDlixbyZWBEDkFlN817RdvQM4AG5Ncspg8Tvy2ab1mj3IbFqERepXWBcCqRVp6y1GwjR7vCFSY6SKNXRNtmpd0rKDGe4",
  // type of device to which this token is assigned - DESKTOP/MOBILE/IOS/ANDROID
  "device_type": "DESKTOP",
  // message content of the push notification
  "message": {
    // smartico internal message id, should be used also to report impressions/clicks
    "message_id": 123456,
    "body": "some body",
    "title": "short title",
    "button1": "button1", // optional
    "button2": "button2", // optional
    "button3": "button3", // optional
    "action": "https://mysite.com/link.html", // optional
    "action2": "https://mysite.com/link2.html", // optional
    "action3": "https://mysite.com/link3.html", // optional
    "iconUrl": "icon", // optional
    "badgeUrl": "badge", // optional
    "imageUrl": "image", // optional
    "huawei_action_type": "2", //only for Huawei
    "huawei_action": "https://google.com", //only for Huawei
    // ID of the user on operators side prefixed with a unique brand ID, needed for reporting
    "user_ext_id": "684:f21aaf49-54cf-4ff4-b3ce-146bd2535004",
    // Unique ID of the notification
    "engagement_uid": "f56883c4-2898-4388-a033-6205bbc41d8d",
    // URL to the site of the domain for this user, used for Deep links
    // you need to replace {action} parameter with the action that user is clicked and 
    // navigate user with the final link
    // you can also skip this part, if your action is always a final URL
    "_WEB_SITE_DP_HANDLER": "https://demo.smartico.ai/demo.html#_smartico_dp={action}"
  }
}
```

Service should respond with HTTP status code 200 and body in JSON format:<br>

```
{
  "error_code": 0
}
```

In case of an error, report HTTP code 500 and the error message and code (the messages and codes are according to the operator's gateway logic). Example:

Smartico applies a 9-second timeout for HTTP connection, request, and socket operations. Requests that encounter network transport failures (such as socket timeouts or connection resets) or temporary HTTP status codes (HTTP 408, HTTP 429, or HTTP 5xx without an error\_code body) are automatically retried once. HTTP 5xx responses containing a structured JSON error\_code are treated as final rejections and not retried.

```
{
  "error_code": 1,
  "error_message": "User was not found"
}
```

### Reporting push message status back to Smartico

The gateway can report the fail, delivery, impression (when the push was shown to the end-user) and click on the notification to the Smartico system.

This should be done with a simple HTTP-GET request to one of the following end-points (depending on which environment your label is set):

* <https://papi.smartico.ai/services/public>
* <https://papi3.smartico.ai/services/public>
* <https://papi4.smartico.ai/services/public>
* <https://papi5.smartico.ai/services/public>
* etc.

The format of the request should be

For more details on reverse integration and reporting callbacks, see Communication gateways and Reverse integration: messaging.

<https://papi.smartico.ai/services/public?api\\_key={label\\_key}\\&brand\\_key={brand\\_key}\\&version=1.2.25\\&event={event\\_body}>

* The version may represent the version of the application and be used only for debugging purposes.
* label\_key - is your label public key, the same as used in the front-end integration on the site
* brand\_key - is your brand public key, the same as used in the front-end integration on the site

{% hint style="info" %}
**Multi-Brand Environments:**

If your setup includes multiple brands, the `brand_key` parameter is **required** for every status callback. It cannot be omitted or shared across brands.

Smartico provides the brand identifier in two places within the outbound push request:

* `ext_brand_id` at the root of the JSON payload.
* As a prefix in `message.user_ext_id`, such as `684:f21aaf49-...`, where `684` is the brand ID.

Your gateway server must use this identifier to look up and supply the corresponding brand's public key (`brand_key`) in the status callback URL.
{% endhint %}

**Reporting fail**

Whenever a fail is reported we will invalidate the user token if the custom gateway is using "smartico-by-token".\
The event\_body for fail should be built in the following way:

```json
{
	// unique uuid for each event
	"uuid": "d404d654-2ef9-44b3-a6e4-4b8934392239", 
	// timestamp of the event with milliseconds
	"ts": 1712570445333,
	"event_type": "engagement_failed",
	// user ext id prefixed with brand id
	"user_ext_id": "684:f21aaf49-54cf-4ff4-b3ce-146bd2535004", 
	"payload": {
		// Unique ID of the notification
		"engagement_uid": "f56883c4-2898-4388-a033-6205bbc41d8d",
		// smartico internal message_id 
		"message_id": 123456,
		// description of error
		"error_message": "error description",
		// fixed constant for the 'Push' type of the communication
		"activity_type": 40
	}
}
```

**Reporting delivery**

The event\_body for delivery should be built in the following way:

```json
{
	// unique uuid for each event
	"uuid": "d404d654-2ef9-44b3-a6e4-4b8934392239", 
	// timestamp of the event with milliseconds
	"ts": 1712570445333,
	"event_type": "engagement_delivered",
	// user ext id prefixed with brand id
	"user_ext_id": "684:f21aaf49-54cf-4ff4-b3ce-146bd2535004", 
	"payload": {
		// Unique ID of the notification
		"engagement_uid": "f56883c4-2898-4388-a033-6205bbc41d8d",
		// smartico internal message_id 
		"message_id": 123456,
		// fixed constant for the 'Push' type of the communication
		"activity_type": 40
	}
}
```

**Reporting Impression**

The event\_body for impression should be built in the following way:

```json
{
	// unique uuid for each event
	"uuid": "d404d654-2ef9-44b3-a6e4-4b8934392239", 
	// timestamp of the event with milliseconds
	"ts": 1712570445333,
	"event_type": "engagement_impression",
	// user ext id prefixed with brand id
	"user_ext_id": "684:f21aaf49-54cf-4ff4-b3ce-146bd2535004", 
	"payload": {
		// Unique ID of the notification
		"engagement_uid": "f56883c4-2898-4388-a033-6205bbc41d8d",
		// smartico internal message_id 
		"message_id": 123456,
		// fixed constant for the 'Push' type of the communication
		"activity_type": 40
	}
}
```

**Reporting action (click)**

The event\_body for the click should be built in the following way:

```json
{
	// unique uuid for each event
	"uuid": "d404d654-2ef9-44b3-a6e4-4b8934392239", 
	// timestamp of the event with milliseconds
	"ts": 1712570445333,
	"event_type": "engagement_action",
	// user ext id prefixed with brand id
	"user_ext_id": "684:f21aaf49-54cf-4ff4-b3ce-146bd2535004", 
	"payload": {
		// Unique ID of the notification
		"engagement_uid": "f56883c4-2898-4388-a033-6205bbc41d8d",
		// smartico internal message_id 
		"message_id": 123456,
		// fixed constant for the 'Push' type of the communication
		"activity_type": 40,
		// link that user clicked
		"action": "https://mysite.com/link.html"
	}
}
```

### Frequently Asked Questions

**Where in the BackOffice do I enter the custom gateway configuration?**

Navigate to Settings → Label Settings (or Brand Settings) → Push notifications, and open the "Firebase / Huawei server keys for push notifications" field. Paste your custom gateway JSON here. Even though the field name references Firebase, Smartico inspects the gateway-type property and routes delivery to your custom URL.

**Why are push impressions and clicks showing zero in reports and analytics?**

With custom push gateways, Smartico does not receive automatic impression or click events from the operating system. You must report engagement\_impression and engagement\_action callbacks back to the Smartico Public API endpoint for impressions and clicks to appear in BackOffice reports and Data Studio.

**Why does the payload contain device\_type: "DESKTOP" when using smartico-by-user?**

In smartico-by-user mode, Smartico does not manage or store device tokens and addresses the user at an account level. The device\_type field defaults to "DESKTOP" as a placeholder, and your gateway is responsible for determining the player's active devices and delivering the push accordingly.

**Does the event payload in HTTP GET callback requests need to be URL-encoded?**

Yes. When submitting callbacks via HTTP GET, the event query parameter containing the JSON payload must be URL-encoded (for example, replacing braces and quotation marks with percent-encoded characters) to prevent HTTP parsing errors.

<br>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://help.smartico.ai/welcome/technical-guides/communication-gateways/custom-push-gateways.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
