---
title: "Save Google Play Configuration"
method: PUT
path: "/v2/projects/{id}/applications/{application_id}/integrations/google-play/configuration"
tags: ["Google Play V2"]
---

# Save Google Play Configuration

`PUT /v2/projects/{id}/applications/{application_id}/integrations/google-play/configuration`

Validates the service-account key and package name against Google and, only when every check passes, persists them with the key sealed at rest. When a check fails the response is `{ valid: false, saved: false, checks }` and the stored configuration is left untouched. Set `configure_pubsub` to also create the default notifications topic and the Superwall push subscription in the same call. Requires applications:write scope.

## Path parameters

- `id` string, required — Project ID
- `application_id` string, required — Application ID

## Request body

- object
  - `package_name` string, required — Android package name (application ID), e.g. `com.acme.app`
  - `service_account_json` string — Key to validate and store. Omit to change only the package name, re-validating against the key already stored
  - `configure_pubsub` boolean — When true, also create the default notifications topic (with the Google Play publisher binding) and the Superwall push subscription in the same call. Defaults to false so a stepped setup flow can drive those explicitly

## Response `200`

Success

- object
  - `object` 'google_play_configuration_save_result', required — Object type, always `google_play_configuration_save_result`
  - `valid` boolean, required — True when no check failed. Warnings do not make the result invalid
  - `error` string, nullable, required — Message from the first failing check, for callers that only want one line
  - `failed_check` 'key_format' | 'credentials' | 'androidpublisher_api' | 'package_access' | 'pubsub_api' | 'pubsub_topic' | 'pubsub_subscription', nullable, required — Which check failed first; `null` when valid
  - `checks` object[], required — The full ladder, in order, including passed / warning / skipped rungs
    - `id` 'key_format' | 'credentials' | 'androidpublisher_api' | 'package_access' | 'pubsub_api' | 'pubsub_topic' | 'pubsub_subscription', required — Which stage of the ladder this result is for
    - `status` 'passed' | 'failed' | 'warning' | 'skipped', required — Outcome of this check
    - `title` string, required — Short human-readable label for the check, e.g. `Service account can read com.acme.app`
    - `code` 'key_invalid_json' | 'key_not_service_account' | 'key_missing_client_email' | 'key_missing_private_key' | 'key_missing_project_id' | 'key_invalid_private_key_pem' | 'credentials_revoked' | 'credentials_rejected' | 'token_exchange_failed' | 'androidpublisher_api_disabled' | 'service_account_not_invited' | 'package_name_not_found' | 'androidpublisher_request_failed' | 'pubsub_api_disabled' | 'pubsub_permission_denied' | 'no_topics' | 'no_topic_with_play_binding' | 'topic_iam_unreadable' | 'topic_iam_write_denied' | 'topic_create_failed' | 'subscription_topic_not_found' | 'subscription_create_failed', nullable, required — Machine-readable reason the check did not pass; `null` when it passed
    - `message` string, nullable, required — Human-readable remediation guidance; `null` when the check passed
    - `resolution_link` string, nullable, required — URL that takes the operator straight to the page that fixes this failure (Google Cloud enable-API page, Play Console users page); `null` when there is no single such page
  - `saved` boolean, required — Whether the configuration was persisted. False whenever a check failed
  - `configuration` object, nullable, required — The stored configuration after a successful save; `null` when nothing was written
    - `object` 'google_play_configuration', required — Object type, always `google_play_configuration`
    - `configured` boolean, required — Whether the application has a stored Google Play configuration at all
    - `package_name` string, nullable, required — Android package name (application ID) the credentials are scoped to
    - `has_service_account_key` boolean, required — Whether a sealed service-account key is stored
    - `service_account_email` string, nullable, required — `client_email` from the stored key — the address to invite in the Play Console
    - `project_id` string, nullable, required — Google Cloud project the service account belongs to
    - `pubsub_topic_name` string, nullable, required — Fully qualified Pub/Sub topic receiving Real-Time Developer Notifications
    - `pubsub_subscription_id` string, nullable, required — Fully qualified Pub/Sub push subscription delivering notifications to Superwall
    - `push_endpoint` string, nullable, required — Superwall ingestion URL for this application's notifications. Paste into the Play Console when configuring RTDNs manually
    - `created_at` string, nullable, required — ISO 8601 timestamp of when the configuration was first saved
    - `updated_at` string, nullable, required — ISO 8601 timestamp of the last configuration change

## Other responses

- `400` — The request did not match the expected schema
- `401` — No API key was provided in the request
- `403` — The API key does not have permission to perform this action
- `404` — The requested resource was not found
- `429` — Too many requests have been made in a short period
- `500` — An unexpected error occurred on the server

---

[API](https://skmtc.dev/superwall/apis/superwall-api-v2.md) · [All operations](https://skmtc.dev/superwall/apis/superwall-api-v2/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/superwall/superwall-api-v2/revisions/44900ad77d2c/schema)
