PlanyDocs
API reference

AccountService

api.plany.cloud:443Global15 methods

Manage your Plany account, the people who belong to it and your own user profile. An account is what owns projects, holds credit and receives the bill. Invite teammates by email, set each member's role, and read back who is signed in with GetCurrentUser.

CreateAccount

plany.account.v1.AccountService/CreateAccount

Creates an account. The calling user becomes its owner.

A new account starts on plans/hobby and is granted that plan's included credit immediately, so a casual user can launch a server without ever entering card details.

Parameters

  • accountAccountRequired
    Show child attributes
    • display_namestringRequired
    • namestringIdentifier

      accounts/{account}, where {account} is an opaque generated id. Not the user's email or chosen name, so both can change freely.

    • account_idstringImmutable

      Short human-readable id unique across Plany, e.g. "northstar-games". Usable in place of the generated id in resource names, so URLs read well.

    • ACCOUNT_TYPE_INDIVIDUALACCOUNT_TYPE_ORGANIZATION
    • default_locationstring

      Default location for new projects, locations/{location}. Set from the signup region so a casual user never has to pick one.

    • labelsmap<string, string>

      Free-form labels for the account holder's own organisation.

    • billing_emailstring

      Contact address for billing and service notices.

    • country_codestring

      ISO 3166-1 alpha-2 country, used for tax treatment and to pick a default region.

    • tax_idstring

      Tax identifier such as a VAT number, for organisations.

  • account_idstring

    Desired short id. Must be globally unique, 3-40 chars, lowercase alphanumeric and hyphens. Empty generates one from display_name.

  • request_idstring

    Idempotency key. Repeating a create with the same key returns the original account rather than creating a second one — signup pages retry.

Returns

Account.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"account": {
"display_name": "My server"
}
}' \
api.plany.cloud:443 plany.account.v1.AccountService/CreateAccount
Example response
{
"name": "accounts/",
"account_id": "my-account",
"display_name": "My server",
"type": "ACCOUNT_TYPE_INDIVIDUAL",
"state": "STATE_ACTIVE",
"owner": "",
"plan": "",
"credit_balance": {
"currency_code": "USD",
"units": "5",
"nanos": 0
},
"default_location": "",
"labels": {
"key": ""
},
"billing_email": "",
"country_code": "",
"tax_id": "my-tax",
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"purge_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\"",
"state_reason": ""
}

GetAccount

Read
plany.account.v1.AccountService/GetAccount

Parameters

  • namestringRequired

Returns

Account.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "accounts/"
}' \
api.plany.cloud:443 plany.account.v1.AccountService/GetAccount
Example response
{
"name": "accounts/",
"account_id": "my-account",
"display_name": "My server",
"type": "ACCOUNT_TYPE_INDIVIDUAL",
"state": "STATE_ACTIVE",
"owner": "",
"plan": "",
"credit_balance": {
"currency_code": "USD",
"units": "5",
"nanos": 0
},
"default_location": "",
"labels": {
"key": ""
},
"billing_email": "",
"country_code": "",
"tax_id": "my-tax",
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"purge_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\"",
"state_reason": ""
}

ListAccounts

Read
plany.account.v1.AccountService/ListAccounts

Lists the accounts you are a member of.

Parameters

  • page_sizeint32
  • page_tokenstring
  • filterstring

    AIP-160 filter, e.g. state = "ACTIVE" AND type = "ORGANIZATION".

  • order_bystring

Returns

ListAccountsResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"page_size": 50
}' \
api.plany.cloud:443 plany.account.v1.AccountService/ListAccounts
Example response
{
"accounts": [
{
"name": "accounts/",
"account_id": "my-account",
"display_name": "My server",
"type": "ACCOUNT_TYPE_INDIVIDUAL",
"state": "STATE_ACTIVE",
"owner": "",
"plan": "",
"credit_balance": {
"currency_code": "USD",
"units": "5",
"nanos": 0
},
"default_location": "",
"labels": {
"key": ""
},
"billing_email": "",
"country_code": "",
"tax_id": "my-tax",
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"purge_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\"",
"state_reason": ""
}
],
"next_page_token": ""
}

UpdateAccount

plany.account.v1.AccountService/UpdateAccount

Parameters

  • accountAccountRequired
    Show child attributes
    • display_namestringRequired
    • namestringIdentifier

      accounts/{account}, where {account} is an opaque generated id. Not the user's email or chosen name, so both can change freely.

    • account_idstringImmutable

      Short human-readable id unique across Plany, e.g. "northstar-games". Usable in place of the generated id in resource names, so URLs read well.

    • ACCOUNT_TYPE_INDIVIDUALACCOUNT_TYPE_ORGANIZATION
    • default_locationstring

      Default location for new projects, locations/{location}. Set from the signup region so a casual user never has to pick one.

    • labelsmap<string, string>

      Free-form labels for the account holder's own organisation.

    • billing_emailstring

      Contact address for billing and service notices.

    • country_codestring

      ISO 3166-1 alpha-2 country, used for tax treatment and to pick a default region.

    • tax_idstring

      Tax identifier such as a VAT number, for organisations.

  • update_maskFieldMaskRequired

    Fields to change. Required: a blanket overwrite of an account is never what the caller means.

Returns

Account.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"account": {
"display_name": "My server"
},
"update_mask": "display_name"
}' \
api.plany.cloud:443 plany.account.v1.AccountService/UpdateAccount
Example response
{
"name": "accounts/",
"account_id": "my-account",
"display_name": "My server",
"type": "ACCOUNT_TYPE_INDIVIDUAL",
"state": "STATE_ACTIVE",
"owner": "",
"plan": "",
"credit_balance": {
"currency_code": "USD",
"units": "5",
"nanos": 0
},
"default_location": "",
"labels": {
"key": ""
},
"billing_email": "",
"country_code": "",
"tax_id": "my-tax",
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"purge_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\"",
"state_reason": ""
}

DeleteAccount

Long-running
plany.account.v1.AccountService/DeleteAccount

Begins account deletion.

The account enters STATE_PENDING_DELETION and can be restored with UndeleteAccount until its purge_time.

Parameters

  • namestringRequired
  • etagstring

    Fail unless the stored etag matches, guarding against deleting an account that changed since it was read.

  • validate_onlybool

    Validate and report what would happen without doing it.

Returns

An Operation that resolves to Empty.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "accounts/"
}' \
api.plany.cloud:443 plany.account.v1.AccountService/DeleteAccount
Example response
{}

UndeleteAccount

plany.account.v1.AccountService/UndeleteAccount

Cancels a pending deletion and returns the account to ACTIVE. Fails once purge_time has passed.

Parameters

  • namestringRequired

Returns

Account.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "accounts/"
}' \
api.plany.cloud:443 plany.account.v1.AccountService/UndeleteAccount
Example response
{
"name": "accounts/",
"account_id": "my-account",
"display_name": "My server",
"type": "ACCOUNT_TYPE_INDIVIDUAL",
"state": "STATE_ACTIVE",
"owner": "",
"plan": "",
"credit_balance": {
"currency_code": "USD",
"units": "5",
"nanos": 0
},
"default_location": "",
"labels": {
"key": ""
},
"billing_email": "",
"country_code": "",
"tax_id": "my-tax",
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"purge_time": "2026-10-04T12:00:00Z",
"etag": "W/\"1\"",
"state_reason": ""
}

CreateMembership

plany.account.v1.AccountService/CreateMembership

Invites a user to the account by email. If no Plany user holds that address the invitation waits for them to sign up.

Parameters

  • parentstringRequired
  • membershipMembershipRequired
    Show child attributes
    • emailstringRequired

      Address the invitation was sent to. Retained after acceptance so the invite trail stays auditable.

    • namestringIdentifier

      accounts/{account}/memberships/{membership}.

    • rolesrepeated string

      Account-level roles granted, as roles/{role} names. Written through to the IAM policy on the account.

Returns

Membership.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "accounts/",
"membership": {
"email": ""
}
}' \
api.plany.cloud:443 plany.account.v1.AccountService/CreateMembership
Example response
{
"name": "accounts//memberships/my-membership",
"user": "",
"email": "",
"state": "STATE_INVITED",
"roles": [
""
],
"inviter": "",
"create_time": "2026-10-04T12:00:00Z",
"invite_expire_time": "2026-10-04T12:00:00Z",
"invitation_token": ""
}

GetMembership

Read
plany.account.v1.AccountService/GetMembership

Parameters

  • namestringRequired

Returns

Membership.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "accounts//memberships/my-membership"
}' \
api.plany.cloud:443 plany.account.v1.AccountService/GetMembership
Example response
{
"name": "accounts//memberships/my-membership",
"user": "",
"email": "",
"state": "STATE_INVITED",
"roles": [
""
],
"inviter": "",
"create_time": "2026-10-04T12:00:00Z",
"invite_expire_time": "2026-10-04T12:00:00Z",
"invitation_token": ""
}

ListMemberships

Read
plany.account.v1.AccountService/ListMemberships

Parameters

  • parentstringRequired
  • page_sizeint32
  • page_tokenstring
  • filterstring

Returns

ListMembershipsResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "accounts/",
"page_size": 50
}' \
api.plany.cloud:443 plany.account.v1.AccountService/ListMemberships
Example response
{
"memberships": [
{
"name": "accounts//memberships/my-membership",
"user": "",
"email": "",
"state": "STATE_INVITED",
"roles": [
""
],
"inviter": "",
"create_time": "2026-10-04T12:00:00Z",
"invite_expire_time": "2026-10-04T12:00:00Z",
"invitation_token": ""
}
],
"next_page_token": ""
}

UpdateMembership

plany.account.v1.AccountService/UpdateMembership

Parameters

  • membershipMembershipRequired
    Show child attributes
    • emailstringRequired

      Address the invitation was sent to. Retained after acceptance so the invite trail stays auditable.

    • namestringIdentifier

      accounts/{account}/memberships/{membership}.

    • rolesrepeated string

      Account-level roles granted, as roles/{role} names. Written through to the IAM policy on the account.

  • update_maskFieldMaskRequired

Returns

Membership.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"membership": {
"email": ""
},
"update_mask": "display_name"
}' \
api.plany.cloud:443 plany.account.v1.AccountService/UpdateMembership
Example response
{
"name": "accounts//memberships/my-membership",
"user": "",
"email": "",
"state": "STATE_INVITED",
"roles": [
""
],
"inviter": "",
"create_time": "2026-10-04T12:00:00Z",
"invite_expire_time": "2026-10-04T12:00:00Z",
"invitation_token": ""
}

DeleteMembership

plany.account.v1.AccountService/DeleteMembership

Removes a member. Refuses to remove the owner; ownership must be transferred first, so an account can never end up with nobody in charge.

Parameters

  • namestringRequired

Returns

Empty.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "accounts//memberships/my-membership"
}' \
api.plany.cloud:443 plany.account.v1.AccountService/DeleteMembership
Example response
{}

AcceptInvitation

plany.account.v1.AccountService/AcceptInvitation

Accepts an invitation. Called by the invited user, who is identified from their own credentials rather than from the request.

Parameters

  • invitation_tokenstringRequired

    Single-use token from the invitation email.

Returns

Membership.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"invitation_token": ""
}' \
api.plany.cloud:443 plany.account.v1.AccountService/AcceptInvitation
Example response
{
"name": "accounts//memberships/my-membership",
"user": "",
"email": "",
"state": "STATE_INVITED",
"roles": [
""
],
"inviter": "",
"create_time": "2026-10-04T12:00:00Z",
"invite_expire_time": "2026-10-04T12:00:00Z",
"invitation_token": ""
}

GetCurrentUser

Read
plany.account.v1.AccountService/GetCurrentUser

Returns the user behind the caller's credentials.

Parameters

No parameters.

Returns

User.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
api.plany.cloud:443 plany.account.v1.AccountService/GetCurrentUser
Example response
{
"name": "users/my-user",
"email": "",
"email_verified": false,
"display_name": "My server",
"timezone": "",
"locale": "",
"mfa_enabled": false,
"create_time": "2026-10-04T12:00:00Z",
"last_login_time": "2026-10-04T12:00:00Z"
}

GetUser

Read
plany.account.v1.AccountService/GetUser

Parameters

  • namestringRequired

Returns

User.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "users/my-user"
}' \
api.plany.cloud:443 plany.account.v1.AccountService/GetUser
Example response
{
"name": "users/my-user",
"email": "",
"email_verified": false,
"display_name": "My server",
"timezone": "",
"locale": "",
"mfa_enabled": false,
"create_time": "2026-10-04T12:00:00Z",
"last_login_time": "2026-10-04T12:00:00Z"
}

UpdateUser

plany.account.v1.AccountService/UpdateUser

Parameters

  • userUserRequired
    Show child attributes
    • emailstringRequired
    • namestringIdentifier

      users/{user}.

    • display_namestring
    • timezonestring

      IANA timezone, e.g. "Europe/London". Used to render billing periods in the user's own time rather than UTC.

    • localestring

      BCP-47 language tag for notification copy.

  • update_maskFieldMaskRequired

Returns

User.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"user": {
"email": "",
"display_name": "My server"
},
"update_mask": "display_name"
}' \
api.plany.cloud:443 plany.account.v1.AccountService/UpdateUser
Example response
{
"name": "users/my-user",
"email": "",
"email_verified": false,
"display_name": "My server",
"timezone": "",
"locale": "",
"mfa_enabled": false,
"create_time": "2026-10-04T12:00:00Z",
"last_login_time": "2026-10-04T12:00:00Z"
}

The DeleteAccountMetadata object

DeleteAccountMetadata reports progress while an account is torn down. The operation can run for a long time when many regions hold resources, so this carries enough detail for a UI to show real progress.

Attributes

  • accountstring
  • projects_totalint32
  • projects_deletedint32
  • resources_totalint32
  • resources_deletedint32
  • current_stepstring

    What the operation is doing right now, e.g. "deleting instances in eu-west-2".

DeleteAccountMetadata
{
"account": "accounts/",
"projects_total": 0,
"projects_deleted": 0,
"resources_total": 0,
"resources_deleted": 0,
"current_step": ""
}

Account

Account is the billing and ownership boundary.

  • display_namestringRequired
  • namestringIdentifier

    accounts/{account}, where {account} is an opaque generated id. Not the user's email or chosen name, so both can change freely.

  • account_idstringImmutable

    Short human-readable id unique across Plany, e.g. "northstar-games". Usable in place of the generated id in resource names, so URLs read well.

  • ACCOUNT_TYPE_INDIVIDUALACCOUNT_TYPE_ORGANIZATION
  • stateAccount.StateOutput only
    STATE_ACTIVESTATE_PENDING_VERIFICATIONSTATE_SUSPENDED_NO_CREDITSTATE_SUSPENDED_ADMINSTATE_PENDING_DELETIONSTATE_CLOSED
  • ownerstringOutput only

    Principal that owns the account, users/{user}. Distinct from the IAM owner role: the owner cannot be removed and is the last point of contact.

  • planstringOutput only

    Current plan, plans/{plan} in plany.billing.v1 — plans/hobby or plans/pro. The plan sets the monthly included credit.

  • credit_balanceMoneyOutput only

    Spendable credit right now, mirrored from billing for convenience so a console load does not need a second call. Billing remains authoritative.

  • default_locationstring

    Default location for new projects, locations/{location}. Set from the signup region so a casual user never has to pick one.

  • labelsmap<string, string>

    Free-form labels for the account holder's own organisation.

  • billing_emailstring

    Contact address for billing and service notices.

  • country_codestring

    ISO 3166-1 alpha-2 country, used for tax treatment and to pick a default region.

  • tax_idstring

    Tax identifier such as a VAT number, for organisations.

  • create_timeTimestampOutput only
  • update_timeTimestampOutput only
  • purge_timeTimestampOutput only

    When a pending deletion becomes irreversible. Set only in STATE_PENDING_DELETION.

  • etagstringOutput only

    Concurrency token for read-modify-write updates.

  • state_reasonstringOutput only

    Why the account is in its current state, when Plany suspended it.

    Shown so that a suspension always comes with its reason. Empty for a state nobody chose — a new account awaiting verification, for example.

ListAccountsResponse

  • Show child attributes
    • display_namestringRequired
    • namestringIdentifier

      accounts/{account}, where {account} is an opaque generated id. Not the user's email or chosen name, so both can change freely.

    • account_idstringImmutable

      Short human-readable id unique across Plany, e.g. "northstar-games". Usable in place of the generated id in resource names, so URLs read well.

    • ACCOUNT_TYPE_INDIVIDUALACCOUNT_TYPE_ORGANIZATION
    • stateAccount.StateOutput only
      STATE_ACTIVESTATE_PENDING_VERIFICATIONSTATE_SUSPENDED_NO_CREDITSTATE_SUSPENDED_ADMINSTATE_PENDING_DELETIONSTATE_CLOSED
    • ownerstringOutput only

      Principal that owns the account, users/{user}. Distinct from the IAM owner role: the owner cannot be removed and is the last point of contact.

    • planstringOutput only

      Current plan, plans/{plan} in plany.billing.v1 — plans/hobby or plans/pro. The plan sets the monthly included credit.

    • credit_balanceMoneyOutput only

      Spendable credit right now, mirrored from billing for convenience so a console load does not need a second call. Billing remains authoritative.

    • default_locationstring

      Default location for new projects, locations/{location}. Set from the signup region so a casual user never has to pick one.

    • labelsmap<string, string>

      Free-form labels for the account holder's own organisation.

    • billing_emailstring

      Contact address for billing and service notices.

    • country_codestring

      ISO 3166-1 alpha-2 country, used for tax treatment and to pick a default region.

    • tax_idstring

      Tax identifier such as a VAT number, for organisations.

    • create_timeTimestampOutput only
    • update_timeTimestampOutput only
    • purge_timeTimestampOutput only

      When a pending deletion becomes irreversible. Set only in STATE_PENDING_DELETION.

    • etagstringOutput only

      Concurrency token for read-modify-write updates.

    • state_reasonstringOutput only

      Why the account is in its current state, when Plany suspended it.

      Shown so that a suspension always comes with its reason. Empty for a state nobody chose — a new account awaiting verification, for example.

  • next_page_tokenstring

ListMembershipsResponse

  • Show child attributes
    • emailstringRequired

      Address the invitation was sent to. Retained after acceptance so the invite trail stays auditable.

    • namestringIdentifier

      accounts/{account}/memberships/{membership}.

    • userstringOutput only

      The member, users/{user}. Empty until an invitation is accepted.

    • stateMembership.StateOutput only
      STATE_INVITEDSTATE_ACTIVESTATE_SUSPENDED
    • rolesrepeated string

      Account-level roles granted, as roles/{role} names. Written through to the IAM policy on the account.

    • inviterstringOutput only

      Principal that issued the invitation.

    • create_timeTimestampOutput only
    • invite_expire_timeTimestampOutput only

      When an unaccepted invitation lapses.

    • invitation_tokenstringOutput only

      The invitation token, returned by CreateMembership and never again.

      Stored only as a hash, exactly like an API key and for the same reason: anyone with database read access could otherwise join any account. There is nowhere to look it up afterwards because there is nothing stored to look up — a lost invitation is reissued, not recovered.

  • next_page_tokenstring

Membership

Membership grants a user access to an account.

Roles themselves live in IAM; this resource exists so an account can enumerate its people, invite new ones and track invitation state without every membership question becoming a policy query.

  • emailstringRequired

    Address the invitation was sent to. Retained after acceptance so the invite trail stays auditable.

  • namestringIdentifier

    accounts/{account}/memberships/{membership}.

  • userstringOutput only

    The member, users/{user}. Empty until an invitation is accepted.

  • stateMembership.StateOutput only
    STATE_INVITEDSTATE_ACTIVESTATE_SUSPENDED
  • rolesrepeated string

    Account-level roles granted, as roles/{role} names. Written through to the IAM policy on the account.

  • inviterstringOutput only

    Principal that issued the invitation.

  • create_timeTimestampOutput only
  • invite_expire_timeTimestampOutput only

    When an unaccepted invitation lapses.

  • invitation_tokenstringOutput only

    The invitation token, returned by CreateMembership and never again.

    Stored only as a hash, exactly like an API key and for the same reason: anyone with database read access could otherwise join any account. There is nowhere to look it up afterwards because there is nothing stored to look up — a lost invitation is reissued, not recovered.

User

User is a person with Plany credentials. A user may belong to several accounts; the account is the tenancy boundary, the user is not.

  • emailstringRequired
  • namestringIdentifier

    users/{user}.

  • email_verifiedboolOutput only
  • display_namestring
  • timezonestring

    IANA timezone, e.g. "Europe/London". Used to render billing periods in the user's own time rather than UTC.

  • localestring

    BCP-47 language tag for notification copy.

  • mfa_enabledboolOutput only
  • create_timeTimestampOutput only
  • last_login_timeTimestampOutput only

Enums

Account.AccountType

AccountType shapes defaults, quotas and support expectations. It does not change the pricing model — both types spend the same credit at the same rates.

ValueDescription
ACCOUNT_TYPE_UNSPECIFIED
ACCOUNT_TYPE_INDIVIDUALA person hosting servers for themselves and their friends. Lower default quotas, simpler console, aggressive idle-shutdown defaults.
ACCOUNT_TYPE_ORGANIZATIONA studio or business. Higher default quotas, multi-seat membership, invoicing and support entitlements.

Account.State

ValueDescription
STATE_UNSPECIFIED
STATE_ACTIVENormal operation.
STATE_PENDING_VERIFICATIONEmail not yet verified. The account can browse but cannot create billable resources.
STATE_SUSPENDED_NO_CREDITOut of credit. Running workloads are stopped and creation is refused, but data is retained so a top-up restores service. This is the ordinary end state for a lapsed hobby account, not a punishment.
STATE_SUSPENDED_ADMINSuspended by Plany, for abuse or non-payment. Only Plany can lift it — open a support case.
STATE_PENDING_DELETIONDeletion requested and inside the retention window. Everything is stopped; the account can still be restored.
STATE_CLOSEDRetention elapsed and resources are gone. The row survives so historical ledger entries still resolve.

Membership.State

ValueDescription
STATE_UNSPECIFIED
STATE_INVITEDInvited, not yet accepted.
STATE_ACTIVEAccepted and active.
STATE_SUSPENDEDAccess suspended without removing the record.