PlanyDocs
API reference

SecretService

api.plany.cloud:443Regional12 methods

Store credentials — database passwords, API keys, licence files — and reference them by name from everything that needs them. A secret holds versions: change its value by adding a version, and every reference to the secret picks up the latest enabled one. Reading a secret's value needs its own permission, separate from seeing that it exists, so a game server can be allowed to read one secret and nothing else. Secrets are regional; a project using the same credential in two regions holds a secret in each.

CreateSecret

plany.secret.v1.SecretService/CreateSecret

Creates a secret, optionally with its first version.

initial_payload is a deliberate departure from creating the container and the value in two calls. A secret with no version exists, holds its bindings, appears in every list, and fails every access — so the two-call shape has a window in which the customer's configuration is complete and broken, and a Terraform apply interrupted between the two leaves exactly that. One call has no such window.

Parameters

  • parentstringRequired

    projects/{project}/locations/{location}.

  • secretSecretRequired
    Show child attributes
    • namestringIdentifier

      projects/{project}/locations/{location}/secrets/{secret}.

      Regional: a secret lives in one region, and a project using the same credential in two regions holds a secret in each.

    • display_namestring

      What a person calls it. Free text.

    • descriptionstring

      What it is for, in the customer's own words. Worth having on a resource whose value nobody can look at to remind themselves.

    • labelsmap<string, string>
  • secret_idstringRequired

    The last segment of the name. AIP-122: lower case, digits and hyphens.

  • initial_payloadSecretPayloadInput only

    The first version's value.

    Optional but almost always wanted — see the method comment. Left out, the secret is created with no versions and latest_version empty.

    Show child attributes
    • databytes

      Bytes, not a string, because a secret is as often a private key or a keytab as it is a password.

      Environment injection needs valid UTF-8 and says so at the point of use — see plany.playpute.v1.SecretAttachment. Storing it as text here instead would make the platform unable to hold a certificate, which is the second thing anybody asks for.

Returns

Secret.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "projects//locations/",
"secret": {
"display_name": "My server"
},
"secret_id": "my-secret"
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/CreateSecret
Example response
{
"name": "projects//locations//secrets/",
"uid": "0b6f3c1e-8a2d-4f6e-9c1a-2f4b7d9e0a11",
"display_name": "My server",
"description": "",
"labels": {
"key": ""
},
"state": "STATE_ACTIVE",
"version_count": "0",
"latest_version": "projects//locations//secrets//versions/my-version",
"payload_fingerprint": "",
"managed_by": "",
"unmetered": false,
"last_access_time": "2026-10-04T12:00:00Z",
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

GetSecret

Read
plany.secret.v1.SecretService/GetSecret

Parameters

  • namestringRequired

Returns

Secret.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//secrets/"
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/GetSecret
Example response
{
"name": "projects//locations//secrets/",
"uid": "0b6f3c1e-8a2d-4f6e-9c1a-2f4b7d9e0a11",
"display_name": "My server",
"description": "",
"labels": {
"key": ""
},
"state": "STATE_ACTIVE",
"version_count": "0",
"latest_version": "projects//locations//secrets//versions/my-version",
"payload_fingerprint": "",
"managed_by": "",
"unmetered": false,
"last_access_time": "2026-10-04T12:00:00Z",
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

ListSecrets

Read
plany.secret.v1.SecretService/ListSecrets

Parameters

  • parentstringRequired
  • page_sizeint32
  • page_tokenstring
  • filterstring

    AIP-160, over display_name, labels, state and managed_by.

  • customer_onlybool

    Leave out the secrets Plany stored on your behalf for another product. Off by default, so the list shows every credential held in the project.

Returns

ListSecretsResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "projects//locations/",
"page_size": 50
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/ListSecrets
Example response
{
"secrets": [
{
"name": "projects//locations//secrets/",
"uid": "0b6f3c1e-8a2d-4f6e-9c1a-2f4b7d9e0a11",
"display_name": "My server",
"description": "",
"labels": {
"key": ""
},
"state": "STATE_ACTIVE",
"version_count": "0",
"latest_version": "projects//locations//secrets//versions/my-version",
"payload_fingerprint": "",
"managed_by": "",
"unmetered": false,
"last_access_time": "2026-10-04T12:00:00Z",
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}
],
"next_page_token": ""
}

UpdateSecret

plany.secret.v1.SecretService/UpdateSecret

Updates a secret's metadata. Never its value — see AddSecretVersion.

Parameters

  • secretSecretRequired
    Show child attributes
    • namestringIdentifier

      projects/{project}/locations/{location}/secrets/{secret}.

      Regional: a secret lives in one region, and a project using the same credential in two regions holds a secret in each.

    • display_namestring

      What a person calls it. Free text.

    • descriptionstring

      What it is for, in the customer's own words. Worth having on a resource whose value nobody can look at to remind themselves.

    • labelsmap<string, string>
  • update_maskFieldMaskRequired

    Which fields to write. Only display_name, description and labels can be updated; the value is not among them and never will be.

Returns

Secret.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"secret": {
"display_name": "My server"
},
"update_mask": "display_name"
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/UpdateSecret
Example response
{
"name": "projects//locations//secrets/",
"uid": "0b6f3c1e-8a2d-4f6e-9c1a-2f4b7d9e0a11",
"display_name": "My server",
"description": "",
"labels": {
"key": ""
},
"state": "STATE_ACTIVE",
"version_count": "0",
"latest_version": "projects//locations//secrets//versions/my-version",
"payload_fingerprint": "",
"managed_by": "",
"unmetered": false,
"last_access_time": "2026-10-04T12:00:00Z",
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\""
}

DeleteSecret

plany.secret.v1.SecretService/DeleteSecret

Deletes a secret and destroys every version it holds.

Refused for a secret Plany stored on your behalf for another product (managed_by is set): delete the resource that created it instead.

Refused, too, while something still references it, unless force is set — a delete that took the credential out from under a running fleet is an outage.

Parameters

  • namestringRequired
  • forcebool

    Delete it even though something still references it.

  • etagstring

    Refuse if the secret has changed since it was read.

Returns

Empty.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//secrets/"
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/DeleteSecret
Example response
{}

AddSecretVersion

plany.secret.v1.SecretService/AddSecretVersion

Adds a new version, which immediately becomes the latest.

Parameters

  • parentstringRequired

    projects/{project}/locations/{location}/secrets/{secret}.

  • payloadSecretPayloadRequired
    Show child attributes
    • databytes

      Bytes, not a string, because a secret is as often a private key or a keytab as it is a password.

      Environment injection needs valid UTF-8 and says so at the point of use — see plany.playpute.v1.SecretAttachment. Storing it as text here instead would make the platform unable to hold a certificate, which is the second thing anybody asks for.

  • disable_previousbool

    Disable the version this one replaces, in the same call.

    The safe rotation in one step, and off by default because the unsafe order is the one people reach for: disabling first leaves a window where nothing works, and doing it afterwards by hand leaves two live credentials if the second call never happens.

Returns

SecretVersion.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "projects//locations//secrets/",
"payload": {}
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/AddSecretVersion
Example response
{
"name": "projects//locations//secrets//versions/my-version",
"state": "STATE_ENABLED",
"payload_size_bytes": 0,
"payload_fingerprint": "",
"created_by": "",
"create_time": "2026-10-04T12:00:00Z",
"state_change_time": "2026-10-04T12:00:00Z",
"last_access_time": "2026-10-04T12:00:00Z"
}

GetSecretVersion

plany.secret.v1.SecretService/GetSecretVersion

Parameters

  • namestringRequired

    The version's full name. The last segment may be latest, which resolves to the newest enabled version; the answer always names the number.

Returns

SecretVersion.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//secrets//versions/my-version"
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/GetSecretVersion
Example response
{
"name": "projects//locations//secrets//versions/my-version",
"state": "STATE_ENABLED",
"payload_size_bytes": 0,
"payload_fingerprint": "",
"created_by": "",
"create_time": "2026-10-04T12:00:00Z",
"state_change_time": "2026-10-04T12:00:00Z",
"last_access_time": "2026-10-04T12:00:00Z"
}

ListSecretVersions

Read
plany.secret.v1.SecretService/ListSecretVersions

Parameters

  • parentstringRequired
  • page_sizeint32
  • page_tokenstring

Returns

ListSecretVersionsResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "projects//locations//secrets/",
"page_size": 50
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/ListSecretVersions
Example response
{
"versions": [
{
"name": "projects//locations//secrets//versions/my-version",
"state": "STATE_ENABLED",
"payload_size_bytes": 0,
"payload_fingerprint": "",
"created_by": "",
"create_time": "2026-10-04T12:00:00Z",
"state_change_time": "2026-10-04T12:00:00Z",
"last_access_time": "2026-10-04T12:00:00Z"
}
],
"next_page_token": ""
}

AccessSecretVersion

plany.secret.v1.SecretService/AccessSecretVersion

Returns the value.

The only call that discloses a secret's value, and it needs its own permission, secretmanager.versions.access. Every call is recorded in your audit trail, without the value.

Parameters

  • namestringRequired

    The version's full name, or one ending in latest.

Returns

AccessSecretVersionResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//secrets//versions/my-version"
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/AccessSecretVersion
Example response
{
"name": "",
"payload": {
"data": ""
}
}

DisableSecretVersion

plany.secret.v1.SecretService/DisableSecretVersion

Stops a version being served, keeping its bytes.

Parameters

  • namestringRequired

Returns

SecretVersion.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//secrets//versions/my-version"
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/DisableSecretVersion
Example response
{
"name": "projects//locations//secrets//versions/my-version",
"state": "STATE_ENABLED",
"payload_size_bytes": 0,
"payload_fingerprint": "",
"created_by": "",
"create_time": "2026-10-04T12:00:00Z",
"state_change_time": "2026-10-04T12:00:00Z",
"last_access_time": "2026-10-04T12:00:00Z"
}

EnableSecretVersion

plany.secret.v1.SecretService/EnableSecretVersion

Parameters

  • namestringRequired

Returns

SecretVersion.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//secrets//versions/my-version"
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/EnableSecretVersion
Example response
{
"name": "projects//locations//secrets//versions/my-version",
"state": "STATE_ENABLED",
"payload_size_bytes": 0,
"payload_fingerprint": "",
"created_by": "",
"create_time": "2026-10-04T12:00:00Z",
"state_change_time": "2026-10-04T12:00:00Z",
"last_access_time": "2026-10-04T12:00:00Z"
}

DestroySecretVersion

plany.secret.v1.SecretService/DestroySecretVersion

Destroys a version's bytes. Irreversible.

The row survives so the version number is never reissued and the history still reads as one. Refused on the latest enabled version of a secret something still references, for the reason DeleteSecret is.

Parameters

  • namestringRequired

Returns

SecretVersion.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "projects//locations//secrets//versions/my-version"
}' \
api.plany.cloud:443 plany.secret.v1.SecretService/DestroySecretVersion
Example response
{
"name": "projects//locations//secrets//versions/my-version",
"state": "STATE_ENABLED",
"payload_size_bytes": 0,
"payload_fingerprint": "",
"created_by": "",
"create_time": "2026-10-04T12:00:00Z",
"state_change_time": "2026-10-04T12:00:00Z",
"last_access_time": "2026-10-04T12:00:00Z"
}

The SecretPayload object

SecretPayload is the value itself.

The only message on this API that carries one, returned by the only RPC that returns one. Separated from SecretVersion so that nothing can accidentally serve a payload by returning a version: a handler that wants to disclose the bytes has to name this type, which makes the disclosure a thing somebody wrote rather than a field somebody forgot to strip.

Attributes

  • databytes

    Bytes, not a string, because a secret is as often a private key or a keytab as it is a password.

    Environment injection needs valid UTF-8 and says so at the point of use — see plany.playpute.v1.SecretAttachment. Storing it as text here instead would make the platform unable to hold a certificate, which is the second thing anybody asks for.

SecretPayload
{
"data": ""
}

AccessSecretVersionResponse

  • namestring

    The version actually served, by number, never latest.

    So a caller that asked for latest can record what it got. A workload that logged "read the secret" and not "read version 4" cannot answer the only question worth asking after a rotation goes wrong.

  • Show child attributes
    • databytes

      Bytes, not a string, because a secret is as often a private key or a keytab as it is a password.

      Environment injection needs valid UTF-8 and says so at the point of use — see plany.playpute.v1.SecretAttachment. Storing it as text here instead would make the platform unable to hold a certificate, which is the second thing anybody asks for.

ListSecretVersionsResponse

  • Newest first, which is the order somebody asking about a rotation wants.

    Show child attributes
    • namestringIdentifier

      .../secrets/{secret}/versions/{version}, where the last segment is a positive integer that increases and is never reused.

      Deliberately not latest as a stored name. latest is an alias accepted on the read path and resolved to a number, so an audit entry and a log line always name the version that was actually served.

    • stateSecretVersion.StateOutput only
      STATE_ENABLEDSTATE_DISABLEDSTATE_DESTROYED
    • payload_size_bytesint32Output only

      Size of the payload. Metadata, so it comes back from an ordinary read — knowing a key is 32 bytes and not 3 is how a paste that lost its tail is found without anybody looking at either.

    • payload_fingerprintstringOutput only

      A truncated SHA-256 over the payload. See Secret.payload_fingerprint.

    • created_bystringOutput only

      Who added it, as a principal name. Empty when the platform did.

    • create_timeTimestampOutput only
    • state_change_timeTimestampOutput only

      When this version was disabled or destroyed, whichever happened.

    • last_access_timeTimestampOutput only
  • next_page_tokenstring

ListSecretsResponse

  • Show child attributes
    • namestringIdentifier

      projects/{project}/locations/{location}/secrets/{secret}.

      Regional: a secret lives in one region, and a project using the same credential in two regions holds a secret in each.

    • uidstringOutput only

      Server-assigned, immutable, unique for the life of the platform.

    • display_namestring

      What a person calls it. Free text.

    • descriptionstring

      What it is for, in the customer's own words. Worth having on a resource whose value nobody can look at to remind themselves.

    • labelsmap<string, string>
    • stateSecret.StateOutput only
      STATE_ACTIVESTATE_DELETING
    • version_countint64Output only

      The highest version number ever added, whatever its state.

      A counter rather than a count: it never goes down, so a destroyed version's number is never reissued and an audit entry naming versions/3 means one thing forever.

    • latest_versionstringOutput only

      .../secrets/{secret}/versions/{version} — the newest ENABLED version, which is what an unqualified reference resolves to.

      Empty for a secret with no usable version, which is a real state and worth rendering: a secret whose only version was destroyed still exists, still holds its bindings, and fails every access until somebody adds one.

    • payload_fingerprintstringOutput only

      A truncated hash of the latest enabled version's payload.

      The whole of what a read tells you about the value. Two secrets holding one credential share it, so "did I paste the same key into both" is answerable without either being disclosed — and so is "did my rotation take", which is the question a customer actually has after a write they cannot verify.

    • managed_bystringOutput only

      The Plany product that stored this secret on your behalf, if any. Empty for a secret you created.

      A managed secret is not charged for, and cannot be deleted directly — it goes when the resource that created it does.

    • unmeteredboolOutput only

      Not charged for. True exactly when managed_by is set.

    • last_access_timeTimestampOutput only

      When a version of this secret was last handed to somebody.

      The one field here worth more than the rest put together. It is how a customer finds the API key nothing has used since March — which is the credential worth revoking — and it is the first thing to look at when asking whether a leaked key was ever actually used.

    • create_timeTimestampOutput only
    • update_timeTimestampOutput only
    • etagstringOutput only
  • next_page_tokenstring

Secret

Secret is a named credential a project holds.

It carries no sensitive bytes. What it carries is everything about the credential — its name, who may reach it, how many versions it has had, when it was last read — which is the half that belongs in a list, a console page and an audit entry.

  • namestringIdentifier

    projects/{project}/locations/{location}/secrets/{secret}.

    Regional: a secret lives in one region, and a project using the same credential in two regions holds a secret in each.

  • uidstringOutput only

    Server-assigned, immutable, unique for the life of the platform.

  • display_namestring

    What a person calls it. Free text.

  • descriptionstring

    What it is for, in the customer's own words. Worth having on a resource whose value nobody can look at to remind themselves.

  • labelsmap<string, string>
  • stateSecret.StateOutput only
    STATE_ACTIVESTATE_DELETING
  • version_countint64Output only

    The highest version number ever added, whatever its state.

    A counter rather than a count: it never goes down, so a destroyed version's number is never reissued and an audit entry naming versions/3 means one thing forever.

  • latest_versionstringOutput only

    .../secrets/{secret}/versions/{version} — the newest ENABLED version, which is what an unqualified reference resolves to.

    Empty for a secret with no usable version, which is a real state and worth rendering: a secret whose only version was destroyed still exists, still holds its bindings, and fails every access until somebody adds one.

  • payload_fingerprintstringOutput only

    A truncated hash of the latest enabled version's payload.

    The whole of what a read tells you about the value. Two secrets holding one credential share it, so "did I paste the same key into both" is answerable without either being disclosed — and so is "did my rotation take", which is the question a customer actually has after a write they cannot verify.

  • managed_bystringOutput only

    The Plany product that stored this secret on your behalf, if any. Empty for a secret you created.

    A managed secret is not charged for, and cannot be deleted directly — it goes when the resource that created it does.

  • unmeteredboolOutput only

    Not charged for. True exactly when managed_by is set.

  • last_access_timeTimestampOutput only

    When a version of this secret was last handed to somebody.

    The one field here worth more than the rest put together. It is how a customer finds the API key nothing has used since March — which is the credential worth revoking — and it is the first thing to look at when asking whether a leaked key was ever actually used.

  • create_timeTimestampOutput only
  • update_timeTimestampOutput only
  • etagstringOutput only

SecretVersion

SecretVersion is one immutable value a secret has held.

Immutable on purpose: a credential that could be edited in place has no history, so "when did this change and to what" is unanswerable, and anything caching it has no way to know it went stale. Changing a secret is adding a version.

  • namestringIdentifier

    .../secrets/{secret}/versions/{version}, where the last segment is a positive integer that increases and is never reused.

    Deliberately not latest as a stored name. latest is an alias accepted on the read path and resolved to a number, so an audit entry and a log line always name the version that was actually served.

  • stateSecretVersion.StateOutput only
    STATE_ENABLEDSTATE_DISABLEDSTATE_DESTROYED
  • payload_size_bytesint32Output only

    Size of the payload. Metadata, so it comes back from an ordinary read — knowing a key is 32 bytes and not 3 is how a paste that lost its tail is found without anybody looking at either.

  • payload_fingerprintstringOutput only

    A truncated SHA-256 over the payload. See Secret.payload_fingerprint.

  • created_bystringOutput only

    Who added it, as a principal name. Empty when the platform did.

  • create_timeTimestampOutput only
  • state_change_timeTimestampOutput only

    When this version was disabled or destroyed, whichever happened.

  • last_access_timeTimestampOutput only

Enums

Secret.State

ValueDescription
STATE_UNSPECIFIED
STATE_ACTIVEUsable. Versions can be added and accessed.
STATE_DELETINGThe row is gone from every list and its versions are being shredded. A delete is not instant, and a secret in this state still refuses every access rather than serving one last read.

SecretVersion.State

ValueDescription
STATE_UNSPECIFIED
STATE_ENABLEDAccessible.
STATE_DISABLEDRetained but refused. The step a careful rotation takes before destroying: disable, watch for the thing that still needed it to break, and re-enable if it does. Destroying instead makes that recovery impossible.
STATE_DESTROYEDThe ciphertext is gone. Irreversible. The row stays, so the version number is never reissued and the history still reads as a history — what is destroyed is the value, not the fact that there was one.