GET

A GET route supports both a request and a response. We'll cover each below and discuss how these relate to Actions.

Request

Actions 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 (shown below), or with an HTTP error. In addition:

  • 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 an OK HTTP status 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 must 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 - A UTF-8 string to be displayed on the button used to execute the action. Labels should not exceed five-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," meaning that its absence is equivalent to enabled=true. Examples of disabled could include an NFT collection that has minted out or a governance proposal whose voting period has 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 additional, related actions. Each linked action is given 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.

  • Here's a definition of a linked Action written in TypeScript:

export interface LinkedAction {
  /** URL endpoint for an action */
  href: string;
  /** button text rendered to the user */
  label: string;
  /**
   * Parameters to accept user input within an action
   * @see {ActionParameter}
   * @see {ActionParameterSelectable}
   */
  parameters?: Array<TypedActionParameter>;
}

/** Parameter to accept user input within an action */
export interface ActionParameter {
  /** input field type */
  type?: ActionParameterType;
  /** 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;
  /** regular expression pattern to validate user input client side */
  pattern?: string;
  /** human-readable description of the `type` and/or `pattern`, represents a caption and error, if value doesn't match */
  patternDescription?: string;
  /** the minimum value allowed based on the `type` */
  min?: string | number;
  /** the maximum value allowed based on the `type` */
  max?: string | number;
}

Note that ActionParameter represents a second Action type; it has multiple input types and an extended version of ActionParameter , called ActionParameterSelectable , which are explained in greater depth in the Action Types page.

Note that the complete ActionParameter interface is not supported by Blinks clients, and we're working on bringing client support as soon as possible. As of now, the fields in ActionParameter that are supported are name, label and required. ActionParameterSelectable is not currently supported as well.

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 the user should see displayed as a single button with a "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 three related action links that allow the user to click one of three 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 example responses 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):

This example response provides the user with three linked actions to buy WIF:

  • a button labeled "$10";

  • another labeled "$100";

  • a third labeled "$1,000";

If you inspect "parameters" near the bottom, you'll see there's also a text input field that allows the user to enter a specific "amount" 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
          }
        ]
      }
    ]
  }
}

This 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):

{
  "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
          }
        ]
      }
    ]
  }
}

Note that the aspect ratio of the url-to-image is generally flexible and the only limitation is that the max height of the image must be equal to the max width of the blink container. The recommended size for 1:1 aspect ratio is 440px x 440px

Last updated