PlanyDocs
API reference

SupportService

api.plany.cloud:443Global9 methods

Ask Plany for help, and keep the whole conversation in one place. Open a case about a product, a feature and optionally the exact resource that is misbehaving, attach screenshots or logs, and reply on it until it is resolved. The people answering see the case alongside the resource it names, so you do not have to explain which server you mean.

ListSupportTopics

Read
plany.support.v1.SupportService/ListSupportTopics

The products and features a case can be about.

Parameters

No parameters.

Returns

ListSupportTopicsResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
api.plany.cloud:443 plany.support.v1.SupportService/ListSupportTopics
Example response
{
"topics": [
{
"id": "",
"display_name": "My server",
"description": "",
"features": [
{
"id": "",
"display_name": "My server"
}
],
"resource_types": [
""
]
}
]
}

CreateAttachment

plany.support.v1.SupportService/CreateAttachment

Issues a URL to upload one file to, before it is attached to anything.

Parameters

  • parentstringRequired

    accounts/{account}.

  • attachmentAttachmentRequired
    Show child attributes
    • filenamestringRequired

      The file's own name, as the customer's machine called it. Shown, never used as a path.

    • content_typestringRequired

      Images, video, plain text, logs, JSON, PDF or zip. Anything else is refused when the upload is requested.

    • size_bytesint64Required

      What the client said it would upload; once attached, what actually arrived.

    • namestringIdentifier

      accounts/{account}/attachments/{attachment}.

Returns

CreateAttachmentResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "accounts/",
"attachment": {
"filename": "",
"content_type": "",
"size_bytes": "0"
}
}' \
api.plany.cloud:443 plany.support.v1.SupportService/CreateAttachment
Example response
{
"attachment": {
"name": "accounts//attachments/my-attachment",
"filename": "",
"content_type": "",
"size_bytes": "0",
"state": "STATE_PENDING",
"create_time": "2026-10-04T12:00:00Z"
},
"upload_url": "",
"upload_headers": {
"key": ""
},
"expire_time": "2026-10-04T12:00:00Z"
}

GetAttachmentDownloadUrl

plany.support.v1.SupportService/GetAttachmentDownloadUrl

A short-lived URL to read an attached file back.

Authorized as reading the case the file is attached to. A pending upload nobody attached has no case, and is readable by nobody.

Parameters

  • namestringRequired

Returns

GetAttachmentDownloadUrlResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "accounts//attachments/my-attachment"
}' \
api.plany.cloud:443 plany.support.v1.SupportService/GetAttachmentDownloadUrl
Example response
{
"url": "",
"expire_time": "2026-10-04T12:00:00Z"
}

CreateCase

plany.support.v1.SupportService/CreateCase

Opens a case.

The case starts with two messages: your description with its attachments, and an acknowledgement naming who will answer. Both exist before this returns.

Parameters

  • parentstringRequired

    accounts/{account}.

  • caseCaseRequired
    Show child attributes
    • productstringRequiredImmutable

      The product the case is about, as a SupportTopic.id — playpute, sandbox, billing, other.

    • featurestringRequiredImmutable

      The part of the product, as a SupportFeature.id within it. other is always valid.

    • titlestringRequired

      One line, written by the customer. At most 140 characters.

    • descriptionstringRequiredImmutable

      What the customer wrote when they opened the case. Also the first message on the timeline, with the attachments that came with it; kept here so a list can show it without reading the timeline.

    • namestringIdentifier

      accounts/{account}/cases/{case}.

    • resourcestringImmutable

      The one resource the case is about, if there is one — projects/p/locations/eu-west-2/gameServers/survival.

      Optional, and the most useful field on the case when set: it lets the person answering see that server's state and recent logs straight away rather than asking which one you mean. Must belong to the case's account.

  • attachmentsrepeated string

    Uploaded attachments to put on the opening message, by name. Each must be this account's, pending, and actually uploaded.

  • request_idstring

    Makes a retried create return the case the first attempt made rather than opening a second one. A double-click on "Submit" is the ordinary way a support queue fills with duplicates.

Returns

Case.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "accounts/",
"case": {
"product": "",
"feature": "",
"title": "",
"description": ""
}
}' \
api.plany.cloud:443 plany.support.v1.SupportService/CreateCase
Example response
{
"name": "accounts//cases/my-case",
"uid": "0b6f3c1e-8a2d-4f6e-9c1a-2f4b7d9e0a11",
"number": "0",
"product": "",
"feature": "",
"resource": "",
"title": "",
"description": "",
"state": "STATE_OPEN",
"state_reason": "",
"closed_by": "AUTHOR_TYPE_CUSTOMER",
"priority": "PRIORITY_NORMAL",
"plan": "",
"escalated": false,
"agent_display_name": "",
"waiting_on": "WAITING_ON_SUPPORT",
"creator": "",
"creator_email": "",
"message_count": 0,
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_message_time": "2026-10-04T12:00:00Z",
"resolve_time": "2026-10-04T12:00:00Z",
"close_time": "2026-10-04T12:00:00Z",
"escalate_time": "2026-10-04T12:00:00Z"
}

GetCase

Read
plany.support.v1.SupportService/GetCase

Parameters

  • namestringRequired

Returns

Case.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "accounts//cases/my-case"
}' \
api.plany.cloud:443 plany.support.v1.SupportService/GetCase
Example response
{
"name": "accounts//cases/my-case",
"uid": "0b6f3c1e-8a2d-4f6e-9c1a-2f4b7d9e0a11",
"number": "0",
"product": "",
"feature": "",
"resource": "",
"title": "",
"description": "",
"state": "STATE_OPEN",
"state_reason": "",
"closed_by": "AUTHOR_TYPE_CUSTOMER",
"priority": "PRIORITY_NORMAL",
"plan": "",
"escalated": false,
"agent_display_name": "",
"waiting_on": "WAITING_ON_SUPPORT",
"creator": "",
"creator_email": "",
"message_count": 0,
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_message_time": "2026-10-04T12:00:00Z",
"resolve_time": "2026-10-04T12:00:00Z",
"close_time": "2026-10-04T12:00:00Z",
"escalate_time": "2026-10-04T12:00:00Z"
}

ListCases

Read
plany.support.v1.SupportService/ListCases

Lists an account's cases, most recent activity first.

Parameters

  • parentstringRequired

    accounts/{account}, or accounts/- for an internal caller.

  • page_sizeint32
  • page_tokenstring
  • Only cases in these states. Empty means all of them.

    STATE_OPENSTATE_RESOLVEDSTATE_CLOSED

Returns

ListCasesResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "accounts/",
"page_size": 50
}' \
api.plany.cloud:443 plany.support.v1.SupportService/ListCases
Example response
{
"cases": [
{
"name": "accounts//cases/my-case",
"uid": "0b6f3c1e-8a2d-4f6e-9c1a-2f4b7d9e0a11",
"number": "0",
"product": "",
"feature": "",
"resource": "",
"title": "",
"description": "",
"state": "STATE_OPEN",
"state_reason": "",
"closed_by": "AUTHOR_TYPE_CUSTOMER",
"priority": "PRIORITY_NORMAL",
"plan": "",
"escalated": false,
"agent_display_name": "",
"waiting_on": "WAITING_ON_SUPPORT",
"creator": "",
"creator_email": "",
"message_count": 0,
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_message_time": "2026-10-04T12:00:00Z",
"resolve_time": "2026-10-04T12:00:00Z",
"close_time": "2026-10-04T12:00:00Z",
"escalate_time": "2026-10-04T12:00:00Z"
}
],
"next_page_token": ""
}

ListCaseMessages

Read
plany.support.v1.SupportService/ListCaseMessages

The timeline, oldest first.

Parameters

  • parentstringRequired

    accounts/{account}/cases/{case}.

  • page_sizeint32
  • page_tokenstring

Returns

ListCaseMessagesResponse.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "accounts//cases/my-case",
"page_size": 50
}' \
api.plany.cloud:443 plany.support.v1.SupportService/ListCaseMessages
Example response
{
"messages": [
{
"name": "accounts//cases/my-case/messages/my-message",
"author_type": "AUTHOR_TYPE_CUSTOMER",
"author_display_name": "",
"body": "",
"attachments": [
{
"name": "accounts//attachments/my-attachment",
"filename": "",
"content_type": "",
"size_bytes": "0",
"state": "STATE_PENDING",
"create_time": "2026-10-04T12:00:00Z"
}
],
"create_time": "2026-10-04T12:00:00Z"
}
],
"next_page_token": ""
}

CreateCaseMessage

plany.support.v1.SupportService/CreateCaseMessage

The customer writes on a case.

On a resolved case this reopens it. On a closed one it is refused with FAILED_PRECONDITION, and the customer opens a new case.

Parameters

  • parentstringRequired

    accounts/{account}/cases/{case}.

  • messageCaseMessageRequired
    Show child attributes
    • bodystringRequired

      Plain text. Markdown is not rendered by either end, so nothing a customer writes can turn into a link that does not look like one.

    • namestringIdentifier

      accounts/{account}/cases/{case}/messages/{message}.

  • attachmentsrepeated string

    Uploaded attachments, by name.

  • request_idstring

    Makes a retried send return the message the first attempt stored.

Returns

CaseMessage.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"parent": "accounts//cases/my-case",
"message": {
"body": ""
}
}' \
api.plany.cloud:443 plany.support.v1.SupportService/CreateCaseMessage
Example response
{
"name": "accounts//cases/my-case/messages/my-message",
"author_type": "AUTHOR_TYPE_CUSTOMER",
"author_display_name": "",
"body": "",
"attachments": [
{
"name": "accounts//attachments/my-attachment",
"filename": "",
"content_type": "",
"size_bytes": "0",
"state": "STATE_PENDING",
"create_time": "2026-10-04T12:00:00Z"
}
],
"create_time": "2026-10-04T12:00:00Z"
}

CloseCase

plany.support.v1.SupportService/CloseCase

Closes a case — "I don't need this any more". A person at Plany may also close a case once it is finished.

Parameters

  • namestringRequired
  • reasonstring

    Why. Optional.

Returns

Case.

grpcurl -H "authorization: Bearer $PLANY_API_KEY" \
-d '{
"name": "accounts//cases/my-case"
}' \
api.plany.cloud:443 plany.support.v1.SupportService/CloseCase
Example response
{
"name": "accounts//cases/my-case",
"uid": "0b6f3c1e-8a2d-4f6e-9c1a-2f4b7d9e0a11",
"number": "0",
"product": "",
"feature": "",
"resource": "",
"title": "",
"description": "",
"state": "STATE_OPEN",
"state_reason": "",
"closed_by": "AUTHOR_TYPE_CUSTOMER",
"priority": "PRIORITY_NORMAL",
"plan": "",
"escalated": false,
"agent_display_name": "",
"waiting_on": "WAITING_ON_SUPPORT",
"creator": "",
"creator_email": "",
"message_count": 0,
"create_time": "2026-10-04T12:00:00Z",
"update_time": "2026-10-04T12:00:00Z",
"last_message_time": "2026-10-04T12:00:00Z",
"resolve_time": "2026-10-04T12:00:00Z",
"close_time": "2026-10-04T12:00:00Z",
"escalate_time": "2026-10-04T12:00:00Z"
}

The Attachment object

accounts//attachments/{{attachment}}

Attachment is a file added to a case: a screenshot, a recording, a crash log.

Uploaded before it is attached: CreateAttachment returns a URL to upload the file to directly, then the attachment is named when writing on the case.

Attributes

  • filenamestringRequired

    The file's own name, as the customer's machine called it. Shown, never used as a path.

  • content_typestringRequired

    Images, video, plain text, logs, JSON, PDF or zip. Anything else is refused when the upload is requested.

  • size_bytesint64Required

    What the client said it would upload; once attached, what actually arrived.

  • namestringIdentifier

    accounts/{account}/attachments/{attachment}.

  • stateAttachment.StateOutput only
    STATE_PENDINGSTATE_ATTACHED
  • create_timeTimestampOutput only
Attachment
{
"name": "accounts//attachments/my-attachment",
"filename": "",
"content_type": "",
"size_bytes": "0",
"state": "STATE_PENDING",
"create_time": "2026-10-04T12:00:00Z"
}

The SupportFeature object

SupportFeature is one part of a product.

Attributes

  • idstring

    connectivity. Unique within its product; other is in every product.

  • display_namestring

    "Players can't connect".

SupportFeature
{
"id": "",
"display_name": "My server"
}

The SupportTopic object

SupportTopic is a product a case can be about, and its parts.

The catalogue is served rather than written into each client, so the console's picker, the CLI's validation and the bot's thread titles cannot disagree about what playpute/connectivity means.

Attributes

  • idstring

    playpute, billing, other.

  • display_namestring

    "Game servers".

  • descriptionstring

    One sentence, shown under the product in a picker.

  • Show child attributes
    • idstring

      connectivity. Unique within its product; other is in every product.

    • display_namestring

      "Players can't connect".

  • resource_typesrepeated string

    The resource types a case about this product may name, as google.api.resource types — playpute.plany.cloud/GameServer. Empty when the product has nothing a case would point at, like billing.

SupportTopic
{
"id": "",
"display_name": "My server",
"description": "",
"features": [
{
"id": "",
"display_name": "My server"
}
],
"resource_types": [
""
]
}

Case

Case is one support conversation.

  • productstringRequiredImmutable

    The product the case is about, as a SupportTopic.id — playpute, sandbox, billing, other.

  • featurestringRequiredImmutable

    The part of the product, as a SupportFeature.id within it. other is always valid.

  • titlestringRequired

    One line, written by the customer. At most 140 characters.

  • descriptionstringRequiredImmutable

    What the customer wrote when they opened the case. Also the first message on the timeline, with the attachments that came with it; kept here so a list can show it without reading the timeline.

  • namestringIdentifier

    accounts/{account}/cases/{case}.

  • uidstringOutput only
  • numberint64Output only

    A short number for a person to say out loud: "case 1042". Unique across the platform and assigned in order, so it also tells somebody roughly how old a case is.

  • resourcestringImmutable

    The one resource the case is about, if there is one — projects/p/locations/eu-west-2/gameServers/survival.

    Optional, and the most useful field on the case when set: it lets the person answering see that server's state and recent logs straight away rather than asking which one you mean. Must belong to the case's account.

  • stateCase.StateOutput only
    STATE_OPENSTATE_RESOLVEDSTATE_CLOSED
  • state_reasonstringOutput only

    The resolution for STATE_RESOLVED, the reason for STATE_CLOSED. Empty while open.

  • closed_byAuthorTypeOutput only

    Who closed it. Unset unless the case is closed.

    AUTHOR_TYPE_CUSTOMERAUTHOR_TYPE_STAFFAUTHOR_TYPE_SYSTEM
  • priorityCase.PriorityOutput only
    PRIORITY_NORMALPRIORITY_HIGH
  • planstringOutput only

    The plan the account was on when the case was opened, which is where priority came from. plans/pro.

  • escalatedboolOutput only

    Handed to a specialist. Orthogonal to state: an escalated case is still open, and is still resolved or closed in the ordinary way.

  • agent_display_namestringOutput only

    The name every staff message on this case is signed with, e.g. "Juniper". Generated when the case is opened and never changed.

  • waiting_onCase.WaitingOnOutput only
    WAITING_ON_SUPPORTWAITING_ON_CUSTOMER
  • creatorstringOutput only

    users/{user}, or the API key or service account that opened it.

  • creator_emailstringOutput only

    Where replies are emailed. The creator's verified address when a person opened the case; empty when a credential with no person behind it did, and the account's own contact is written to instead.

  • message_countint32Output only
  • create_timeTimestampOutput only
  • update_timeTimestampOutput only
  • last_message_timeTimestampOutput only

    The newest message, from anybody including the platform.

  • resolve_timeTimestampOutput only
  • close_timeTimestampOutput only
  • escalate_timeTimestampOutput only

CaseMessage

CaseMessage is one entry on a case's timeline. Immutable.

  • bodystringRequired

    Plain text. Markdown is not rendered by either end, so nothing a customer writes can turn into a link that does not look like one.

  • namestringIdentifier

    accounts/{account}/cases/{case}/messages/{message}.

  • author_typeAuthorTypeOutput only
    AUTHOR_TYPE_CUSTOMERAUTHOR_TYPE_STAFFAUTHOR_TYPE_SYSTEM
  • author_display_namestringOutput only

    What to show beside it. The case's alias for staff, the person's own name for a customer, "Plany" for the platform.

  • attachmentsrepeated AttachmentOutput only
    Show child attributes
    • filenamestringRequired

      The file's own name, as the customer's machine called it. Shown, never used as a path.

    • content_typestringRequired

      Images, video, plain text, logs, JSON, PDF or zip. Anything else is refused when the upload is requested.

    • size_bytesint64Required

      What the client said it would upload; once attached, what actually arrived.

    • namestringIdentifier

      accounts/{account}/attachments/{attachment}.

    • stateAttachment.StateOutput only
      STATE_PENDINGSTATE_ATTACHED
    • create_timeTimestampOutput only
  • create_timeTimestampOutput only

CreateAttachmentResponse

  • attachmentAttachment
    Show child attributes
    • filenamestringRequired

      The file's own name, as the customer's machine called it. Shown, never used as a path.

    • content_typestringRequired

      Images, video, plain text, logs, JSON, PDF or zip. Anything else is refused when the upload is requested.

    • size_bytesint64Required

      What the client said it would upload; once attached, what actually arrived.

    • namestringIdentifier

      accounts/{account}/attachments/{attachment}.

    • stateAttachment.StateOutput only
      STATE_PENDINGSTATE_ATTACHED
    • create_timeTimestampOutput only
  • upload_urlstring

    PUT the file's bytes here.

  • upload_headersmap<string, string>

    Headers the PUT must carry, exactly. They are signed into the URL, so a missing one is a 403 rather than a file stored without it.

  • expire_timeTimestamp

GetAttachmentDownloadUrlResponse

ListCaseMessagesResponse

  • Show child attributes
    • bodystringRequired

      Plain text. Markdown is not rendered by either end, so nothing a customer writes can turn into a link that does not look like one.

    • namestringIdentifier

      accounts/{account}/cases/{case}/messages/{message}.

    • author_typeAuthorTypeOutput only
      AUTHOR_TYPE_CUSTOMERAUTHOR_TYPE_STAFFAUTHOR_TYPE_SYSTEM
    • author_display_namestringOutput only

      What to show beside it. The case's alias for staff, the person's own name for a customer, "Plany" for the platform.

    • attachmentsrepeated AttachmentOutput only
      Show child attributes
      • filenamestringRequired

        The file's own name, as the customer's machine called it. Shown, never used as a path.

      • content_typestringRequired

        Images, video, plain text, logs, JSON, PDF or zip. Anything else is refused when the upload is requested.

      • size_bytesint64Required

        What the client said it would upload; once attached, what actually arrived.

      • namestringIdentifier

        accounts/{account}/attachments/{attachment}.

      • stateAttachment.StateOutput only
        STATE_PENDINGSTATE_ATTACHED
      • create_timeTimestampOutput only
    • create_timeTimestampOutput only
  • next_page_tokenstring

ListCasesResponse

  • Show child attributes
    • productstringRequiredImmutable

      The product the case is about, as a SupportTopic.id — playpute, sandbox, billing, other.

    • featurestringRequiredImmutable

      The part of the product, as a SupportFeature.id within it. other is always valid.

    • titlestringRequired

      One line, written by the customer. At most 140 characters.

    • descriptionstringRequiredImmutable

      What the customer wrote when they opened the case. Also the first message on the timeline, with the attachments that came with it; kept here so a list can show it without reading the timeline.

    • namestringIdentifier

      accounts/{account}/cases/{case}.

    • uidstringOutput only
    • numberint64Output only

      A short number for a person to say out loud: "case 1042". Unique across the platform and assigned in order, so it also tells somebody roughly how old a case is.

    • resourcestringImmutable

      The one resource the case is about, if there is one — projects/p/locations/eu-west-2/gameServers/survival.

      Optional, and the most useful field on the case when set: it lets the person answering see that server's state and recent logs straight away rather than asking which one you mean. Must belong to the case's account.

    • stateCase.StateOutput only
      STATE_OPENSTATE_RESOLVEDSTATE_CLOSED
    • state_reasonstringOutput only

      The resolution for STATE_RESOLVED, the reason for STATE_CLOSED. Empty while open.

    • closed_byAuthorTypeOutput only

      Who closed it. Unset unless the case is closed.

      AUTHOR_TYPE_CUSTOMERAUTHOR_TYPE_STAFFAUTHOR_TYPE_SYSTEM
    • priorityCase.PriorityOutput only
      PRIORITY_NORMALPRIORITY_HIGH
    • planstringOutput only

      The plan the account was on when the case was opened, which is where priority came from. plans/pro.

    • escalatedboolOutput only

      Handed to a specialist. Orthogonal to state: an escalated case is still open, and is still resolved or closed in the ordinary way.

    • agent_display_namestringOutput only

      The name every staff message on this case is signed with, e.g. "Juniper". Generated when the case is opened and never changed.

    • waiting_onCase.WaitingOnOutput only
      WAITING_ON_SUPPORTWAITING_ON_CUSTOMER
    • creatorstringOutput only

      users/{user}, or the API key or service account that opened it.

    • creator_emailstringOutput only

      Where replies are emailed. The creator's verified address when a person opened the case; empty when a credential with no person behind it did, and the account's own contact is written to instead.

    • message_countint32Output only
    • create_timeTimestampOutput only
    • update_timeTimestampOutput only
    • last_message_timeTimestampOutput only

      The newest message, from anybody including the platform.

    • resolve_timeTimestampOutput only
    • close_timeTimestampOutput only
    • escalate_timeTimestampOutput only
  • next_page_tokenstring

ListSupportTopicsResponse

  • Show child attributes
    • idstring

      playpute, billing, other.

    • display_namestring

      "Game servers".

    • descriptionstring

      One sentence, shown under the product in a picker.

    • Show child attributes
      • idstring

        connectivity. Unique within its product; other is in every product.

      • display_namestring

        "Players can't connect".

    • resource_typesrepeated string

      The resource types a case about this product may name, as google.api.resource types — playpute.plany.cloud/GameServer. Empty when the product has nothing a case would point at, like billing.

Enums

Attachment.State

ValueDescription
STATE_UNSPECIFIED
STATE_PENDINGA URL has been issued and nothing has been confirmed to have arrived.
STATE_ATTACHEDAttached to a message, with the bytes confirmed present.

AuthorType

Who wrote a message.

ValueDescription
AUTHOR_TYPE_UNSPECIFIED
AUTHOR_TYPE_CUSTOMERSomebody on the customer's account.
AUTHOR_TYPE_STAFFA person at Plany, signed with the case's alias.
AUTHOR_TYPE_SYSTEMThe platform: the acknowledgement when a case opens, and the sentence recording each change of state. Never waits on anybody.

Case.Priority

ValueDescription
PRIORITY_UNSPECIFIED
PRIORITY_NORMAL
PRIORITY_HIGHAn account on the Pro plan when the case was opened.

Case.State

ValueDescription
STATE_UNSPECIFIED
STATE_OPENSomebody is expected to say something. Who is `waiting_on`.
STATE_RESOLVEDPlany believes the problem is solved. `state_reason` is the resolution. Not terminal: a customer replying to a resolved case reopens it, because "that did not fix it" is the most common reply a resolution gets and making somebody open a second case to say it loses the first one's history.
STATE_CLOSEDFinished. Terminal: a closed case refuses new messages, and the customer opens a new case instead. `state_reason` says why it closed.

Case.WaitingOn

Who has to speak next, derived from the last message that was not the platform's own.

ValueDescription
WAITING_ON_UNSPECIFIED
WAITING_ON_SUPPORTThe customer wrote last, or nobody at Plany has answered yet.
WAITING_ON_CUSTOMERPlany wrote last.