Creating custom Action Menu Items

API developers can customize context menu items on a per-entity basis, through Action Menu Items (AMIs). For example, from a Versions page, you could select multiple versions, right-click, then choose “Build a PDF Report.”


Action Menu Item fields

Types of Action Menu items

There are two types of menu items you can create:

HTTP URL example

As an example, you can create a custom menu item called “Build PDF Report.” This will allow people to go to any Versions page, select one or more Versions, right-click, and then choose “Build PDF Report” from the Shotgun menu. Doing this will launch a script, which you must create, to get a nicely formatted report sent back to their browser. Here's how it works:

Create the menu item via the UI

AMI menu

From the settings menu, choose Action Menu Items to open the AMI Admin page. To create a new AMI, click on Add AMI. Fill out the Title and any other required fields, and click on “Create Action Menu Item.”

What happens when a user clicks on the AMI?

Shotgun dispatches a POST request in a new window, or in a modal dialog if that option was selected, and sends along data from the current page (as part of the POST request) to the receiving URL. Here's an example of the workflow.

  • User navigates to a Versions page
  • User selects one or more Versions
  • User brings up the context menu (by right-clicking or clicking on the gear menu in the toolbar)
  • User clicks ‘Build PDF Report’
  • Shotgun dispatches a POST request to the AMI’s URL in a new window (If your Shotgun server is served over HTTPS, and your URL is served over HTTP, expect to see a browser warning)
  • Your script, located at the URL specified, processes the POST data, and generates a PDF document
  • A nicely formatted PDF report is sent back to the user for viewing or download

Custom protocol handler example

A more advanced implementation of custom AMIs involves setting up a custom protocol handler (e.g., shotgun://process_version). This allows you to bridge Shotgun with applications like Maya, RV, or Cinesync via a script on your local computer. When you specify a non HTTP(S) protocol, data is sent via GET instead of POST to your URL. You may want to use this to launch an in-house tool to dispatch different requests.

Read more about custom protocols in “Launching Applications Using Custom Browser Protocols.”

Note: We also have built-in integration with Maya and other software packages via Shotgun integrations.

Light payload

When using custom protocols, the query information is sent as a GET request. Certain operating system and browser combinations have varying limitations of the size of the GET request they allow. We suggest enabling the light payload checkbox on custom protocol AMIs. With light payload checked, your script will receive a single event log entry ID that it can fetch to get the full payload from by reading the ami_payload key of the record's meta field.


Here are some related example scripts to help get you started:

Payload contents

User data

  • user_id: The user ID of the currently logged in user (e.g., 34)
  • user_login: The login of the currently logged in user (e.g., joe)

Entity data

  • entity_type: The entity type of the current page or view (e.g., Version)
  • selected_ids: A comma-separated list of the selected entity IDs (e.g., 931, 900)
  • ids: A comma-separated list of all IDs of the entities returned by the current page's query. This returns ALL IDs, including those that aren't visible due to pagination. (e.g., 931, 900, 904, 907). If "Selection required" was checked on the AMI, this value will be the same as selected_ids.

Page data

  • title: The page title (e.g., "All Versions")
  • page_id: The ID of the page from which the action menu item was clicked (e.g., 1353)
  • server_hostname: The hostname of the system where the AMI was triggered. Can be useful if you have multiple servers invoking the same AMIs like a staging and a production server.
  • referrer_path: the canonical path of the URL where the AMI was invoked.
  • session_uuid: The unique identifier for the window where this AMI was invoked. This can be used with the “Poll for Data Updates” checkbox and the Python API's set_session_uuid method to broadcast back information to the page where the AMI was invoked. Note: This feature’s polling for updates falls off exponentially and eventually stops so if your AMI doesn’t update before polling stops, you may not see any updates in your source page.
  • cols: A comma-separated list of system field names of all the visible columns on the page (e.g., code, sg_status_list, description)
  • column_display_names: A comma-separated list of display names of all the visible columns on the page (e.g., Version, Status, Description)
  • view: The view that was selected when the AMI was invoked. Multiple views can be created for any given page via the design page mode.
  • sort_column: The system name of the column that was sorted by (e.g., code). Only sends the first sort key if there are multiple, see sort_columns
  • sort_direction: (e.g., asc or desc) Only sends the first sort direction if there are multiple, see sort_directions
  • sort_columns: A comma separated list of the system names of the columns that the page or view was sorted by (e.g., code,created_at). Only sent if there are multiple sorting keys
  • sort_directions: A comma separated list of the system names of the columns that the page or view was sorted by (e.g., code, created_at). Only sent if there are multiple sorting keys
  • grouping_column: The system name of the column that was grouped by (e.g., code). Only sends the first grouping column if there are multiple, see grouping_columns
  • grouping_method: The method the by which the grouping occurs (e.g. grouping by entitytype for an entity field or month for a date field). Only sends the first grouping method if there are multiple, see grouping_columns
  • grouping_direction: The grouping direction (e.g., asc or desc) Only sends the first grouping direction if there are multiple, see grouping_directions
  • grouping_columns: A comma separated list of system names of the columns that the data was grouped by (e.g., code,created_at). Only sent if there are multiple grouping columns
  • grouping_methods: A comma separated list of grouping methods (e.g., entity_type,month). Only sent if there are multiple grouping columns
  • grouping_directions: A comma separated list of grouping directions (e.g., asc,desc). Only sent if there are multiple grouping columns

Project data (only sent if all entities on the current page share the same project)

  • project_name: The name of the Project (e.g., Gunslinger)
  • project_id: The ID of the Project (e.g., 81)


  • 0
    Prabu Kasireddy

    Is there a way to group the Custom Menu items?

    We have 4 Custom menu items as of now for an entity and might have more in the future.


    We were wondering if there is a way to group the menu items based on what they do.

    Tried adding an item with the text as ----------------------- and left the URL blank - When this item is selected - the page freezes.

    Any thoughts?

  • 0

    We don't have a way to group the menu options yet, but I can certainly add that request to our list.

    Thinking you'd provide an additional parameter 'group' and then the menu would group up all items in the same group for that entity type with the value of 'group' as the menu header. Then each group would be separated by an appropriate separator as you're requesting. Does that sound like it would cover your use case?

  • 0
    Prabu Kasireddy

    Yes that sounds perfect.

    May be the order for the group by its name?

  • 0
    Chris Mihaly

    Is there any way to know what shotgun server instance called the tool web app?   We run a dev, produciton and staging server for shotgun and would like the tool to call back to the right shotgun instance?

  • 0

    The POST doesn't currently send the instance name or url in the request but we have it on our list to add this. You could inject it manually as part of the parameters in the ActionMenuItem for now which at least one client is doing but this is pretty hacky. Could you also get at it using the HTTP_REFERER? I haven't tested that but it might be worth a shot since I'm pretty sure Apache is sending that info.

  • 0
    Shani Turner

    in the data hash I set

     'url' : '/Volumes/SEAT_B/_developer/shani/scripts/smf/'

    but when I click on the new action menu item I created using this url I get this page:

    with error:

    Sorry, this page does not exist. It may have been deleted or your link may be incorrect.

    If you believe this is an error, please contact support at

    Do you know whayt I am doing wrong?

  • 0
    Stu Aitken



    if you havn't already solved this, I'm pretty sure its because it needs a proper web URL - ie  http or https - it won't work with a local file system path

    the error returned infers that shotgun interpreted what you had supplied as a sub path on the hosted shotgun web site, not as a link to an actual script on your internal file server

    Shotgun assumes that the information is being passed to a web service not a local script

    the way to get his working would be to have your python script served from behind a web server (eg apache) at a specific URL


    hope that helps

  • 0
    Shani Turner

    thanks Stu for looking at my question and giving me some clues! Makes sense what you wrote, I'll try that....

  • 0
    Arthur Na

    Is there a way I can execute scripts/program that is stored in a local path?

  • 0
    Arthur Na

    I mean from action menu item .

  • 0
    Finn Nielsen

    When I select more than about 60 shots and invoke my custom protocol handler, Chrome refuses with a "Failed to load resource" error. I get a similar error in Firefox.

    I am wondering if the maximum size of a GET request as been exceeded. However, the documentation states that Shotgun uses POST - is this correct?

  • 0


    The request is a POST if it is going to another website via http or https. Custom protocols use a GET format (ie. myhandler://dosomething?ids=1,2,3[........])

  • 0



    It appears you may be correct. Though 60 rows is pretty low. Seems that much of the space is taken up by including the column names in the query. If you hide some of the columns on the page you should be able to select more than that. On my testing page, I was able to get almost 200 selected before I got that error.

    I've created a ticket to see if we can do something there. Maybe an option on ActionMenuItems to suppress the column names if they're not needed.

    As far as working around the browser limitation, seems like there's no defined limitation in any spec but they vary from browser to browser :/. Theoretically we could save the state of the page with some sort of key and then just pass the key in the GET request but that would change things a lot and require you to make an additional roundtrip to the server to get the ids.

    We'll think about this one, but for now I'd remove some columns from your page and see if that shrinks the request size to allow you to select more rows.

  • 0
    Finn Nielsen

    Thanks for investigating the issue thoroughly and providing a workaround:-)

    All my ActionMenuItem handler scripts use the Python API to do stuff in Shotgun, including get any needed additional data from the records. So in the case of this type of handlers, only the record id's are really needed. I would suggest an option on ActionMenuItems like the one you mentioned, except the request only contains a list of id's.

  • 0
    Dugan Chen

    The link to the " Handling ActionMenuItem Calls" example is broken.

  • 0
    Nate Barnard

    Could the entity type field become multi rather than single?  To have the same menu item available for more than one entity currently requires duplicating the Action Menu item and then updating to an additional type.  Keep it cleaner if we could just have one multi.



  • 0
    Patrick Wolf

    What happens when a user clicks on the Action Menu Item?

    ... Shotgun dispatches a POST request to the ActionMenuItem's url in a "NEW WINDOW" ...

    Would be great if Shotgun could open a in page pop up window instead of a new window to allow for seamless integration

    see feature request:

  • 0
    Jake Richards

    Is there any sample code that redirects the user to the custom protocol?  I see the link for "Example: Handling Shotgun ActionMenuItem calls " but it basically just gets all the fields passed to it but I was interested in the last part where I redirect to the custom protocol.  Essentially, I'm looking for almost the same functionality as the "Play in RV" action menu item.  Thanks!

  • 0
    Sung, Yun-Chen - Paramount Animation

    The need to open URL in a new window requires popup windows to be enabled  (Safari won't enable on per-site basis) and is annoying to users who want to keep popups blocked when they browse.  Plus it leaves a new tab in browser every time the menu time is invoked.  So, I support Patrick Wolf's suggestion above... which is a year old now.


  • 0
    Tony Aiello

    This limitation noted above:

    sort_column: The system name of the column that was sorted by _(eg. code). _

         * Only sent if there is a sort applied. If an advanced sort is applied, only the first sort-by column is sent.

    is sad.  The same limitation applies to the grouping_column kwarg.  But, the full set of sort and group columns are available in the latest PageSetting entity for the current user for the page, or in the "zero-th" PageSetting if the current user hasn't modified the page from its default.  So if you're building an ActionMenuItem that needs to know the full grouping and sorting settings for the selected entities on a page, you'd have to both use the API to query for that latest "current user" PageSetting, as well as read the PostGreSQL directly for the zero-th PageSetting ... since as-of Shotgun 5, the API doesn't return the full details for a page's zero-th PageSetting.  :-(

    It would be so much more easier and helpful if the sort_column and the grouping_column could return multiple results, just like the cols and column_display_names.  Similarly, the sort_direction, grouping_direction, **and grouping_method** would have to be corresponding comma-separated lists too.


  • 0

    It's been more than a year since the last response, but after working with AMIs, I would like to add, that I support most of what westernx is doing to provide a more customized AMI setup:


    1. Grouping actions

    2. Icons

  • 0
    Mike Hendricks

    Light Payload seems a little too light.

    Light Payload should at least include the shotgun site that made the request(server_hostname). Currently if you have to support more than one shotgun site, you have no built in way to identify the site the request came from. You should probably include info on the user(user_login) as well.

    Currently I'm having to embed the site in the url. myprotocol://shotgun/mytool/

    You could keep all the data but column data and ids and never run into the issue with the url too long causing it to fail to run the action menu.

Please sign in to leave a comment.