GET

Request

Action clients first make an HTTP GET JSON request to the Action URL. The request should be made with an Accept-Encoding header.

Response

The Action URL should respond with an HTTP OK JSON response with the body payload below, or with an HTTP error.

  • The client must handle HTTP client errors, server errors, and redirect responses.

  • The endpoint should respond with a Content-Encoding header for HTTP compression.

  • The client should not cache the response except as instructed by HTTP caching response headers.

  • The client should then display the response body information, like icon, title, description, and labels.

GET Response Body

A successful GET response with status HTTP OK should conform to the following payload:

export interface ActionGetResponse {
  /** url of some descriptive image for the action */
  icon: string;
  /** title of the action */
  title: string;
  /** brief description of the action */
  description: string;
  /** text to be rendered on the action button */
  label: string;
  /** optional state for disabling the action button(s) */
  disabled?: boolean;
  /** optional list of related Actions */
  links?: {
    actions: LinkedAction[];
  };
  /** optional (non-fatal) error message */
  error?: ActionError;
}
  • icon - Must be an absolute HTTP or HTTPS URL of an image describing the action. Supported image formats are SVG, PNG, or WebP image. If none of the above, the client ust reject it as malformed.

  • title - A UTF-8 string for the title of the action.

  • description - A UTF-8 string providing a brief description of the action.

  • label - AUTF-8 string to be displayed on the button used to execute the action. Labels should not exceed 5 word phrases and should start with a verb, to emphasize the action to be taken. For example, "Mint NFT", "Vote Yes", or "Stake 1 SOL".

  • disabled - An optional boolean value. If present, all buttons associated with the action should be disabled. This optional value is falsey, in that its absence is equivalent to enabled=true. Examples of disabled in use could include an NFT collection that has minted out, or a governance proposal whose voting period as ended.

  • error - An optional error indication for non-fatal errors, intended to be human readable and presented to the end-user. If set, it should not prevent the client from interpreting the action or displaying it to the user. For example, the error can be used together with disabled to display a reason like business constraints, authorization, the state, or an error of external resource.

export interface ActionError {
  /** non-fatal error message to be displayed to the user */
  message: string;
}
  • links.actions - An optional array of addtional actions related to this action. Each linked action is given only a label, to be rendered on a button, and an associated Action URL at href. No additional icons, titles, or descriptions are provided. For example, a governance vote action endpoint may return three options for the user: "Vote Yes", "Vote No", and "Abstain from Vote".

    • If no links.actions is provided, the client should render a single button using the root label string and make the POST request to the same action URL endpoint as the initial GET request.

    • If any links.actions are provided, the client should only render buttons and input fields based on the items listed in the links.actions field. The client should not render a button for the contents of the root label.

export interface LinkedAction {
  /** URL endpoint for an action */
  href: string;
  /** button text rendered to the user */
  label: string;
  /** Parameter to accept user input within an action */
  parameters?: [ActionParameter];
}

/** Parameter to accept user input within an action */
export interface ActionParameter {
  /** parameter name in url */
  name: string;
  /** placeholder text for the user input field */
  label?: string;
  /** declare if this field is required (defaults to `false`) */
  required?: boolean;
}

Note that ActionParameters represent a second action type, one with a text-input field for end-users. See Action Types for more information.

For more information on how actions are linked to create multi-action experiences, see Multi-Actions.

Examples

Example GET Response

The following example response provides a single "root" action that is expected to be presented to the user a single button with a label of "Buy WIF":

{
  "title": "Buy WIF with SOL",
  "icon": "<url-to-image>",
  "description": "Buy WIF using SOL. Choose a USD amount of SOL from the options below.",
  "label": "Buy WIF" // button text
}

The following example response provides 3 related action links that allow the user to click one of 3 buttons to buy WIF:

{
  "title": "Buy WIF with SOL",
  "icon": "<url-to-image>",
  "description": "Buy WIF using SOL. Choose a USD amount of SOL from the options below.",
  "label": "Buy WIF",
  "links": {
    "actions": [
      {
        "label": "$10", // button text
        "href": "/api/buy?amount=10"
      },
      {
        "label": "$100", // button text
        "href": "/api/buy?amount=100"
      },
      {
        "label": "$1,000", // button text
        "href": "/api/buy?amount=1000"
      }
    ]
  }
}

Example GET Response with Parameters

The following examples response demonstrate how to accept text input from the user (via parameters) and include that input in the final POST request endpoint (via the href field within a LinkedAction):

The following example response provides the user with 3 linked actions to buy WIF: a button labeled "$10", another button labeled "$100", a third button labeled "$1,000" and a text input field that allows the user to enter a specific "amount" value that will be sent to the Action API:

{
  "title": "Buy WIF with SOL",
  "icon": "<url-to-image>",
  "description": "Buy WIF using SOL. Choose a USD amount of SOL from the options below, or enter a custom amount.",
  "label": "Buy WIF", // not displayed since `links.actions` are provided
  "links": {
    "actions": [
      {
        "label": "$10", // button text
        "href": "/api/buy?amount=10"
        // no `parameters` therefore not a text input field
      },
      {
        "label": "$100", // button text
        "href": "/api/buy?amount=100"
        // no `parameters` therefore not a text input field
      },
      {
        "label": "$1,000", // button text
        "href": "/api/buy?amount=1000"
        // no `parameters` therefore not a text input field
      },
      {
        "label": "Buy WIF", // button text
        "href": "/api/buy?amount={amount}",
        "parameters": [
          {
            "name": "amount", // field name
            "label": "Enter a custom USD amount" // text input placeholder
          }
        ]
      }
    ]
  }
}

The following example response provides a single input field for the user to enter an amount which is sent with the POST request (either as a query parameter or a subpath can be used):

{
  "icon": "<url-to-image>",
  "label": "Buy WIF",
  "title": "Buy WIF with SOL",
  "description": "Buy WIF using SOL. Choose a USD amount of SOL from the options below, or enter a custom amount.",
  "links": {
    "actions": [
      {
        "label": "Buy WIF", // button text
        "href": "/api/buy/{amount}", // or /api/buy?amount={amount}
        "parameters": [
          // {amount} input field
          {
            "name": "amount", // input field name
            "label": "Enter a custom USD amount" // text input placeholder
          }
        ]
      }
    ]
  }
}

Last updated