Creates a new Multitenant Mobile App Identifier with an initial version.

POST /api/configuration/multitenant-mobile-app-identifier

Success: 201 Created

Overview

Registers a multi-tenant mobile app — one app binary in the App Store or Play Store that many Gladstone operators share — and creates its first version in the same call. Each version is issued a secret that the app uses to sign requests, so this call is how an app build gets the credential it needs before it can look up which operator's environment a user belongs to.

Two records are created together, all-or-nothing: the identifier, keyed on the app's bundle id, and one version under it holding the version string and a generated appSecret. If either cannot be saved, neither is kept and you get a 500 — there is no partially created identifier to clean up.

You do not choose either identifier. The response is 201 Created carrying the identifier id, the values you sent, and a one-element versions array containing the new version's id and its appSecret. There is no usable Location header; read the ids from the body.

appBundleId is unique across the whole system, compared case-insensitively. A second call with the same bundle id — in any casing — returns 409 Conflict rather than creating a duplicate or overwriting the first, so a blind retry after a timeout is safe but tells you nothing about whether the original succeeded. Confirm with Retrieve all multitenant mobile app identifiers, which also returns the secrets, so a secret lost in a dropped response can be recovered rather than rotated.

Note what this call does not do. It creates the app registration only; it does not connect it to any operator environment — for that, use Update an environment's multitenant mobile app identifier versions. Adding a second version to an existing identifier is a different endpoint (POST /api/configuration/multitenant-mobile-app-identifier/{id}/version) that accepts only the api scope, so partner integrations can create identifiers and read them back but cannot add versions to, update or delete them afterwards.

Endpoint

POST {base_url}/api/configuration/multitenant-mobile-app-identifier

{base_url} is the environment URL issued to your integration. See Authenticating with Gladstone APIs.

Request body

FieldTypeRequiredDescription
appBundleIdstringYesThe mobile app's platform bundle identifier — the iOS bundle id or Android application id, such as com.example.leisure. This is the natural key: it is what a running app sends when it asks which environment a PIN or company name belongs to, and how the platform finds the secrets to check the signature. Maximum 255 characters, must not be blank (AppBundleId is required.) and must contain no whitespace anywhere (AppBundleId cannot contain whitespace.). Unique across all identifiers, compared case-insensitively, so com.example.app clashes with COM.EXAMPLE.APP. The casing you send is the casing stored.
oneSignalAppIdstringYesThe app's OneSignal application id, used to address push notifications to installs of this app. Required — there is no way to register an identifier without one — and maximum 50 characters. Stored and returned as sent; not validated against OneSignal, so a typo surfaces only when notifications fail to arrive.
appVersionstringYesThe version string of the first app build being registered, in dotted numeric form: major.minor, optionally with .build and .revision, for example 1.0 or 2.4.1.3. Numeric parts only — anything else, including v1.0, 1.0.0-beta and a bare 1, fails with AppVersion must be in a valid format (major.minor[.build[.revision]]). Provided: {value}. Maximum 50 characters, must not be blank and must contain no whitespace. This matters beyond bookkeeping: when an app signs a request it sends its own version, and the platform accepts signatures made with the secret of any registered version less than or equal to that version — so older builds keep working while newer ones get their own secret. Register each shipped build as its own version.

Sample request

cURL
curl -X POST '{base_url}/api/configuration/multitenant-mobile-app-identifier' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "appBundleId": "com.example.leisure",
  "oneSignalAppId": "b2f7f966-d8cc-11e4-bed1-df8f05be55ba",
  "appVersion": "1.0"
}'

Response fields

FieldTypeDescription
idinteger (int32)The identifier's system-generated id. Use it in the per-identifier routes — adding a version, updating and deleting all address the identifier as {id}, not by bundle id.
appBundleIdstringThe bundle id as stored, echoed back unchanged from the request.
oneSignalAppIdstringThe OneSignal application id as stored, echoed back unchanged from the request.
versionsarray of objectThe identifier's versions. On this call it always contains exactly one entry — the initial version built from appVersion. Later calls to the add-version endpoint extend it, and Retrieve all multitenant mobile app identifiers returns the full set when asked with includeVersions=true.
versions[].idinteger (int32)The version's system-generated id, separate from the identifier's id. It is the {id} used by the version update and delete routes.
versions[].appVersionstringThe version string as stored, echoed back unchanged from the request.
versions[].appSecretstringThe HMAC signing secret generated for this version — 256 cryptographically random characters drawn from A–Z, a–z, 0–9, - and _. You cannot supply or choose it, and there is no rotate operation: to change it, delete the version and create it again. Embed it in the matching app build; the app signs the raw JSON body of an environment-search request with HMAC-SHA256 and sends the result Base64-encoded in the X-HMAC-Signature header. Treat it as a credential — it is returned in full by the identifier GET endpoints, so anyone who can call those can sign as the app.

Sample response

201 Created
{
  "id": 12,
  "appBundleId": "com.example.leisure",
  "oneSignalAppId": "b2f7f966-d8cc-11e4-bed1-df8f05be55ba",
  "versions": [
    {
      "id": 34,
      "appVersion": "1.0",
      "appSecret": "qX3n_Tk9…"
    }
  ]
}

Errors

Checks run in a fixed order: request validation, then the whitespace checks, then the duplicate bundle id check, and only then the version format check. A request that is both a duplicate and badly versioned therefore returns 409, not 400.

StatusMeaningWhen
400Required field missingAppBundleId is required., OneSignalAppId is required. or AppVersion is required.. A missing or null field is caught by request validation and returned as a validation problem document (application/problem+json) with an errors map keyed by field name, before any other check.
400Field too longAppBundleId cannot exceed 255 characters., OneSignalAppId cannot exceed 50 characters. or AppVersion cannot exceed 50 characters.. Also returned as a validation problem document.
400Whitespace in appBundleIdAppBundleId cannot contain whitespace. — any whitespace character anywhere in the value, not just leading or trailing. The value is not trimmed for you.
400Whitespace in appVersionAppVersion cannot contain whitespace. — same rule as above.
400Version string not parseableAppVersion must be in a valid format (major.minor[.build[.revision]]). Provided: {value} — the value is not a dotted numeric version. A bare major number such as 1 fails this check.
409Bundle id already registeredAn identifier already exists with AppBundleId '{value}'. — matched case-insensitively against every existing identifier. Fetch the existing record instead of retrying.
403ForbiddenThe access token does not satisfy this endpoint's requirements — the ADMIN product and the cr.co permission — or its scope is neither api nor partner.
500Internal server errorThe identifier and its first version could not be saved, so nothing was created; or another unexpected server-side failure. The response body is empty.

This page as markdown · All pages · llms.txt