---
id: config-configure-push-notification
title: "Configure push notification"
description: "Saves the Google service account that the service uses to send Firebase Cloud Messaging push notifications to the devices of your individuals (the `pushNotificationToken` and `deviceType` of an individual), for example when you issue a credential to an individual or send a verification request to it. Send the JSON key of the service account as it is. The service checks the key and makes no network call. It replaces a saved service account, so this operation and Update push notification do the same."
sidebar_label: "Configure push notification"
hide_title: true
hide_table_of_contents: true
api: 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
sidebar_class_name: "post api-method"
info_path: docs/consent-management-admin-api/igrant-io-api-documentation
custom_edit_url: null
---

> **Build this with an AI coding agent.** Install the iGrant.io Agent Skills, then ask your agent to build the integration:
>
> ```bash
> npx skills add L3-iGrant/skills
> ```


import ApiTabs from "@theme/ApiTabs";
import DiscriminatorTabs from "@theme/DiscriminatorTabs";
import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";
import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes";
import MimeTabs from "@theme/MimeTabs";
import ParamsItem from "@theme/ParamsItem";
import ResponseSamples from "@theme/ResponseSamples";
import SchemaItem from "@theme/SchemaItem";
import SchemaTabs from "@theme/SchemaTabs";
import Markdown from "@theme/Markdown";
import OperationTabs from "@theme/OperationTabs";
import TabItem from "@theme/TabItem";

<h1 className={"openapi__heading"}>Configure push notification</h1>

<MethodEndpoint method={"post"} path={"/v4/config/platform/push-notification"}></MethodEndpoint>



Saves the Google service account that the service uses to send Firebase Cloud Messaging push notifications to the devices of your individuals (the `pushNotificationToken` and `deviceType` of an individual), for example when you issue a credential to an individual or send a verification request to it. Send the JSON key of the service account as it is. The service checks the key and makes no network call. It replaces a saved service account, so this operation and Update push notification do the same.

## Request

<MimeTabs className={"openapi-tabs__mime"}><TabItem label={"application/json"} value={"application/json-schema"}><details style={{}} className={"openapi-markdown__details mime"} data-collapsed={false} open={true}><summary style={{}} className={"openapi-markdown__details-summary-mime"}><h3 className={"openapi-markdown__details-summary-header-body"}>Body</h3><strong className={"openapi-schema__required"}>required</strong></summary><div style={{"textAlign":"left","marginLeft":"1rem"}}></div><ul style={{"marginLeft":"1rem"}}><SchemaItem collapsible={true} className={"schemaItem"}><details style={{}} className={"openapi-markdown__details"}><summary style={{}}><span className={"openapi-schema__container"}><strong className={"openapi-schema__property"}>serviceAccountCredential</strong><span className={"openapi-schema__name"}> object</span><span className={"openapi-schema__divider"}></span><span className={"openapi-schema__required"}>required</span></span></summary><div style={{"marginLeft":"1rem"}}><div style={{"marginTop":".5rem","marginBottom":".5rem"}}>

The JSON key of a Google service account that can send Firebase Cloud Messaging push notifications: the file that you download from the Google Cloud console, with its member names as they are. The service sends the push notifications to your individuals with it.

</div><SchemaItem collapsible={false} name={"type"} required={true} schemaName={"string"} qualifierMessage={"**Possible values:** [`service_account`]"} schema={{"type":"string","description":"Must be `service_account`.","enum":["service_account"],"example":"service_account"}}></SchemaItem><SchemaItem collapsible={false} name={"project_id"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"ID of the Google Cloud project.","example":"acme-mobile-app"}}></SchemaItem><SchemaItem collapsible={false} name={"private_key_id"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"ID of the private key.","example":"<private-key-id>"}}></SchemaItem><SchemaItem collapsible={false} name={"private_key"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"The private key, a PEM RSA key (PKCS","example":"<private-key>"}}></SchemaItem><SchemaItem collapsible={false} name={"client_email"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"Email address of the service account.","example":"push@acme-mobile-app.iam.gserviceaccount.com"}}></SchemaItem><SchemaItem collapsible={false} name={"client_id"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"Client ID of the service account.","example":"<client-id>"}}></SchemaItem><SchemaItem collapsible={false} name={"auth_uri"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"https://accounts.google.com/o/oauth2/auth"}}></SchemaItem><SchemaItem collapsible={false} name={"token_uri"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"https://oauth2.googleapis.com/token"}}></SchemaItem><SchemaItem collapsible={false} name={"auth_provider_x509_cert_url"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"https://www.googleapis.com/oauth2/v1/certs"}}></SchemaItem><SchemaItem collapsible={false} name={"client_x509_cert_url"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"https://www.googleapis.com/robot/v1/metadata/x509/push%40acme-mobile-app.iam.gserviceaccount.com"}}></SchemaItem><SchemaItem collapsible={false} name={"universe_domain"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"googleapis.com"}}></SchemaItem></div></details></SchemaItem></ul></details></TabItem></MimeTabs><div><div><ApiTabs label={undefined} id={undefined}><TabItem label={"200"} value={"200"}><div>

The service account is saved. The response has no body.

</div><div></div></TabItem><TabItem label={"400"} value={"400"}><div>

The body is not valid JSON or has an unknown member, `serviceAccountCredential` is missing, `type` is not `service_account`, `project_id`, `private_key` or `client_email` is empty, the private key is not a PEM RSA key, or the key is not a valid Google service account (for example `field serviceAccountCredential.private_key is invalid: not a PEM block`).

</div><div><MimeTabs className={"openapi-tabs__mime"} schemaType={"response"}><TabItem label={"application/json"} value={"application/json"}><SchemaTabs className={"openapi-tabs__schema"}><TabItem label={"Schema"} value={"Schema"}><details style={{}} className={"openapi-markdown__details response"} data-collapsed={false} open={true}><summary style={{}} className={"openapi-markdown__details-summary-response"}><strong>Schema</strong></summary><div style={{"textAlign":"left","marginLeft":"1rem"}}></div><ul style={{"marginLeft":"1rem"}}><SchemaItem collapsible={false} name={"errorCode"} required={true} schemaName={"integer"} qualifierMessage={undefined} schema={{"type":"integer","example":400}}></SchemaItem><SchemaItem collapsible={false} name={"errorDescription"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"Bad input parameter"}}></SchemaItem><SchemaItem collapsible={false} name={"errorKey"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"A text code of the refusal that does not change when the text changes. Only some refusals have it, for example `organisation_suspended`, `feature_disabled` or `purpose_exists`."}}></SchemaItem></ul></details></TabItem><TabItem label={"Example (from schema)"} value={"Example (from schema)"}><ResponseSamples responseExample={"{\n  \"errorCode\": 400,\n  \"errorDescription\": \"Bad input parameter\",\n  \"errorKey\": \"string\"\n}"} language={"json"}></ResponseSamples></TabItem></SchemaTabs></TabItem></MimeTabs></div></TabItem><TabItem label={"401"} value={"401"}><div>

The API key or the token is missing or not valid.

</div><div><MimeTabs className={"openapi-tabs__mime"} schemaType={"response"}><TabItem label={"application/json"} value={"application/json"}><SchemaTabs className={"openapi-tabs__schema"}><TabItem label={"Schema"} value={"Schema"}><details style={{}} className={"openapi-markdown__details response"} data-collapsed={false} open={true}><summary style={{}} className={"openapi-markdown__details-summary-response"}><strong>Schema</strong></summary><div style={{"textAlign":"left","marginLeft":"1rem"}}></div><ul style={{"marginLeft":"1rem"}}><SchemaItem collapsible={false} name={"errorCode"} required={true} schemaName={"integer"} qualifierMessage={undefined} schema={{"type":"integer","example":400}}></SchemaItem><SchemaItem collapsible={false} name={"errorDescription"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"Bad input parameter"}}></SchemaItem><SchemaItem collapsible={false} name={"errorKey"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"A text code of the refusal that does not change when the text changes. Only some refusals have it, for example `organisation_suspended`, `feature_disabled` or `purpose_exists`."}}></SchemaItem></ul></details></TabItem><TabItem label={"Example (from schema)"} value={"Example (from schema)"}><ResponseSamples responseExample={"{\n  \"errorCode\": 400,\n  \"errorDescription\": \"Bad input parameter\",\n  \"errorKey\": \"string\"\n}"} language={"json"}></ResponseSamples></TabItem></SchemaTabs></TabItem></MimeTabs></div></TabItem><TabItem label={"403"} value={"403"}><div>

The API key or token does not allow this call. An API key without the scope of the operation gets the older body `{"Code", "Message"}`. An `X-SandboxOrgId` header that names another sandbox organisation than the one of the API key gets `{"errorCode", "errorDescription"}`. When a platform admin has turned off the feature of the operation for the organisation, the answer has `errorKey` `feature_disabled` and the member `feature` (the name of the feature).

</div><details style={{"textAlign":"left","marginBottom":"1rem"}} className={"openapi-markdown__details"} data-collaposed={true} open={false}><summary style={{}}><strong>Response Headers</strong></summary><ul style={{"marginLeft":"1rem"}}></ul></details><div><MimeTabs className={"openapi-tabs__mime"} schemaType={"response"}><TabItem label={"application/json"} value={"application/json"}><SchemaTabs className={"openapi-tabs__schema"}><TabItem label={"Schema"} value={"Schema"}><details style={{}} className={"openapi-markdown__details response"} data-collapsed={false} open={true}><summary style={{}} className={"openapi-markdown__details-summary-response"}><strong>Schema</strong></summary><div style={{"textAlign":"left","marginLeft":"1rem"}}></div><ul style={{"marginLeft":"1rem"}}><div><span className={"badge badge--info"}>anyOf</span><SchemaTabs><TabItem label={"MOD1"} value={"0-item-properties"}><SchemaItem collapsible={false} name={"errorCode"} required={true} schemaName={"integer"} qualifierMessage={undefined} schema={{"type":"integer","example":400}}></SchemaItem><SchemaItem collapsible={false} name={"errorDescription"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"Bad input parameter"}}></SchemaItem><SchemaItem collapsible={false} name={"errorKey"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"A text code of the refusal that does not change when the text changes. Only some refusals have it, for example `organisation_suspended`, `feature_disabled` or `purpose_exists`."}}></SchemaItem></TabItem><TabItem label={"Older error body"} value={"1-item-properties"}><SchemaItem collapsible={false} name={"Code"} required={true} schemaName={"integer"} qualifierMessage={undefined} schema={{"type":"integer","description":"The HTTP status.","example":403}}></SchemaItem><SchemaItem collapsible={false} name={"Message"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"What went wrong.","example":"Unauthorized access;User doesn't have enough permissions;"}}></SchemaItem></TabItem></SchemaTabs></div></ul></details></TabItem><TabItem label={"Example (from schema)"} value={"Example (from schema)"}><ResponseSamples responseExample={"{}"} language={"json"}></ResponseSamples></TabItem><TabItem label={"Example"} value={"Example"}><ResponseSamples responseExample={"{\n  \"Code\": 403,\n  \"Message\": \"Unauthorized access;User doesn't have enough permissions;\"\n}"} language={"json"}></ResponseSamples></TabItem></SchemaTabs></TabItem></MimeTabs></div></TabItem><TabItem label={"500"} value={"500"}><div>

The organisation cannot be read, or the server could not save the service account.

</div><div><MimeTabs className={"openapi-tabs__mime"} schemaType={"response"}><TabItem label={"application/json"} value={"application/json"}><SchemaTabs className={"openapi-tabs__schema"}><TabItem label={"Schema"} value={"Schema"}><details style={{}} className={"openapi-markdown__details response"} data-collapsed={false} open={true}><summary style={{}} className={"openapi-markdown__details-summary-response"}><strong>Schema</strong></summary><div style={{"textAlign":"left","marginLeft":"1rem"}}></div><ul style={{"marginLeft":"1rem"}}><SchemaItem collapsible={false} name={"errorCode"} required={true} schemaName={"integer"} qualifierMessage={undefined} schema={{"type":"integer","example":400}}></SchemaItem><SchemaItem collapsible={false} name={"errorDescription"} required={true} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","example":"Bad input parameter"}}></SchemaItem><SchemaItem collapsible={false} name={"errorKey"} required={false} schemaName={"string"} qualifierMessage={undefined} schema={{"type":"string","description":"A text code of the refusal that does not change when the text changes. Only some refusals have it, for example `organisation_suspended`, `feature_disabled` or `purpose_exists`."}}></SchemaItem></ul></details></TabItem><TabItem label={"Example (from schema)"} value={"Example (from schema)"}><ResponseSamples responseExample={"{\n  \"errorCode\": 400,\n  \"errorDescription\": \"Bad input parameter\",\n  \"errorKey\": \"string\"\n}"} language={"json"}></ResponseSamples></TabItem></SchemaTabs></TabItem></MimeTabs></div></TabItem></ApiTabs></div></div>
      