CRM cards

This API is currently in public beta. For the latest stable version check out this page.

Custom CRM cards allow information from other systems to appear on HubSpot contact, company, deal, or ticket records. Using this feature, apps can create custom cards to display this data. 

Example use case: Your engineering team uses one software service to track bugs, but your customer service reps use HubSpot. Your reps want to see information about their customers’ bugs without leaving HubSpot. Your app can define a custom card that displays this info right on the HubSpot contact record.

How it works

Cards can be defined as part of your app’s feature settings. Once the app is installed and a user views the target CRM records, HubSpot makes an outbound request to the app, retrieves the relevant data, and displays it in a card on the record page. Apps can also specify custom actions the user can take based on this information. One example of a custom action would be opening a modal and displaying the app's own UI in HubSpot.

Here's an example of a CRM card:

CRM_Card_1

And here’s an example of how data flows to show card properties in the CRM:

CRM_card_diagram

 

Setting up CRM cards

CRM cards can be created and configured in your developer account. Individual details on the card are represented by card properties, and the titles for these properties can (optionally) link to the integrator’s external system.

On the Apps dashboard, choose the app where you want to add a card and then go to CRM cards. Click the “Create CRM card” button to get started.

Screen Shot 2020-01-14 at 7.36.35 PM

Scope requirements

To create custom CRM cards, your app has to request the OAuth scopes needed to modify the CRM records where your card will appear. This means you request the contacts scope to set up a card for contacts, companies, or deals, and the tickets scope to do the same for tickets.

See the OAuth documentation for more details about scopes and setting up the authorization URL for your app.

Removing scopes

If your app is already using CRM cards, you won’t be able to remove the contacts or tickets scopes until you delete all existing cards for the associated object types.

 

Creating new cards

Creating card templates is the first step in using CRM cards. Here’s what a user will see:

CRM_card_2

 

Configuring cards through the API

Learn more about managing cards through the API in the endpoints tab

Configuring cards from the app settings UI

You can also create and manage CRM cards* in your developer account under your app’s feature settings. (See previous instructions.)

Example_CRM_card_3

*You can create up to 25 CRM cards per app.


Related docs

Understanding the CRM

Timeline events

Data fetch requests

As mentioned in the overview tab, HubSpot makes a data fetch request to your app whenever a user views the associated CRM record. These requests are sent to the card’s specified  fetch/targetUrl with a payload providing details for the associated CRM record.

Responses can contain up to five card properties. If more card properties are available for a specific CRM object, your app can link to them.

Example data fetch request:

GET: https://example.com/demo-tickets?userId=12345&userEmail=testuser@example.com&associatedObjectId=78912&associatedObjectType=COMPANY&portalId=9999999&domain=testcompany.com

 
With a header:
X-HubSpot-Signature: <some base64 string>

The X-HubSpot-Signature header provides verification that a request came from HubSpot. See request signatures for details.

Query parameters:
  • userId: The numeric user ID of the customer requesting data.
  • userEmail: The HubSpot address of the user requesting data.
  • associatedObjectId: The ID for the current object, depending on the associatedObjectType. This will be the companyId, dealId, contact vID, or objectId for tickets.
  • associatedObjectType: The object type the user is requesting data about (contact, company, deal, or ticket). This will be one of the associatedHubSpotObjectTypes provided for this record type.
  • And values for any of the requested associatedHubSpotObjectTypeProperties. If one of the request properties isn't defined for the current object, it won't be listed in the query string. In the example above, the company property domain is included. Request properties can be defined in the app settings UI, as you can see in the screenshot below: 

Associated_Objects

Example response:
JSON
// example response{
  "results": [
    {
      "objectId": 245,
      "title": "API-22: APIs working too fast",
      "link": "http://example.com/1",
      "created": "2016-09-15",
      "priority": "HIGH",
      "project": "API",
      "reported_by": "msmith@hubspot.com",
      "description": "Customer reported that the APIs are just running too fast. This is causing a problem in that they're so happy.",
      "reporter_type": "Account Manager",
      "status": "In Progress",
      "ticket_type": "Bug",
      "updated": "2016-09-28",
      "actions": [
        {
          "type": "IFRAME",
          "width": 890,
          "height": 748,
          "uri": "https://example.com/edit-iframe-contents",
          "label": "Edit",
          "associatedObjectProperties": []
        },
        {
          "type": "IFRAME",
          "width": 890,
          "height": 748,
          "uri": "https://example.com/reassign-iframe-contents",
          "label": "Reassign",
          "associatedObjectProperties": []
        },
        {
          "type": "ACTION_HOOK",
          "httpMethod": "PUT",
          "associatedObjectProperties": [],
          "uri": "https://example.com/tickets/245/resolve",
          "label": "Resolve"
        },
        {
          "type": "CONFIRMATION_ACTION_HOOK",
          "confirmationMessage": "Are you sure you want to delete this ticket?",
          "confirmButtonText": "Yes",
          "cancelButtonText": "No",
          "httpMethod": "DELETE",
          "associatedObjectProperties": [
            "protected_account"
          ],
          "uri": "https://example.com/tickets/245",
          "label": "Delete"
        }
      ],
    },
    {
      "objectId": 988,
      "title": "API-54: Question about bulk APIs",
      "link": "http://example.com/2",
      "created": "2016-08-04",
      "priority": "HIGH",
        "project": "API",
        "reported_by": "ksmith@hubspot.com",
        "description": "Customer is not able to find documentation about our bulk Contacts APIs.",
        "reporter_type": "Support Rep",
        "status": "Resolved",
        "ticket_type": "Bug",
        "updated": "2016-09-23",
        "properties": [
          {
            "label": "Resolved by",
            "dataType": "EMAIL",
            "value": "ijones@hubspot.com"
          },
          {
            "label": "Resolution type",
            "dataType": "STRING",
            "value": "Referred to documentation"
          },
          {
            "label": "Resolution impact",
            "dataType": "CURRENCY",
            "value": "94.34",
            "currencyCode": "GBP"
          }
        ],
        "actions": [
          {
            "type": "IFRAME",
            "width": 890,
            "height": 748,
            "uri": "https://example.com/edit-iframe-contents",
            "label": "Edit"
          },
          {
            "type": "CONFIRMATION_ACTION_HOOK",
            "confirmationMessage": "Are you sure you want to delete this ticket?",
            "confirmButtonText": "Yes",
            "cancelButtonText": "No",
            "httpMethod": "DELETE",
            "associatedObjectProperties": [
              "protected_account"
            ],
            "uri": "https://example.com/tickets/245",
            "label": "Delete"
          }
        ]
      }
    ],
    "settingsAction": {
      "type": "IFRAME",
      "width": 890,
      "height": 748,
      "uri": "https://example.com/settings-iframe-contents",
      "label": "Settings"
    },
    "primaryAction": {
      "type": "IFRAME",
      "width": 890,
      "height": 748,
      "uri": "https://example.com/create-iframe-contents",
      "label": "Create Ticket"
    }
  }
Definitions:
  • results: A list of up to five valid card properties. 
  • results[].objectId: A unique ID for this object. This property is required.
  • results[].title: The title of this object. This property is required.
  • results[].link: The URI the user can follow to get more details about this object. This property is optional, but if all objects don’t have a link, you should provide a value of null.
  • results[].properties: A list of custom properties that aren’t defined in the card settings. You can use this list to display a specific object's unique properties. These properties will be shown in the order they're provided, but after the properties defined in the card settings. This property is optional.
  • results[].actions: A list of available actions a user can take on this object. See action types for details on specifying actions. This property is optional.
  • totalCount: The total number of card properties available, if there are more than five related to the requested CRM object. This property is optional.
  • allItemsLink: A URI showing all card properties associated with the requested CRM object, if there are more than five. This property is optional.
  • itemLabel: The label to be used in the "See more" link, e.g. "See more tickets". This property is optional, and if it's not provided, it defaults to the card title.
  • settingsAction: An iframe action giving users the ability to update the app's settings. See action types for details on specifying actions. This property is optional.
  • primaryAction: The primary action for a record type, typically a "creation" action. See action types for details on specifying actions. This property is optional.
  • secondaryActions: A list of actions displayed on the card level. See action types for details on specifying actions. This property is optional.

In addition to the above properties, the integrator can provide values for the properties defined in the card settings. In the above example, the created JSON property:

"created":"2016-08-04"

Is providing a value for this object for the pre-defined created property.

CRM_card_5

Handling action hooks 

When a user clicks on an action defined as an action hook, HubSpot sends a request using the URI and HTTP method specified in the action definition.

Example request:

DELETE https://example.com/tickets/245?userId=12345&userEmail=testuser@example.com&associatedObjectId=78912&associatedObjectType=COMPANY&portalId=9999999&domain=testcompany.com

With a header:
X-HubSpot-Signature: <some base64 string>
Query parameters:
  • userId: The numeric user ID of the customer requesting data.
  • userEmail: The HubSpot user address of the customer requesting data.
  • associatedObjectId: The ID for the current object, depending on the associatedObjectType. This will be the companyId, dealId, contact vid, or objectId for tickets.
  • associatedObjectType: The type of object the user is requesting data about (contact, company, deal, or ticket).
  • portalId: The account ID (also called Hub ID) of the customer requesting data.
  • And values for any of the requested associatedObjectProperties. If one of the requested properties is undefined for the current object, it will not be listed in the query string. In the above example, the company property domain is included.

The X-HubSpot-Signature header allows the integrator to verify that a request came from HubSpot. See request signatures for details.

Example response:
{"message": "Successfully deleted object"}

HubSpot will attempt to parse responses to action hooks as JSON and look for a message property. The user will get a message on either success or failure.

Response status code of 2XX will show a success message and 4XX or 5XX will show error messages.

 

Action types

The following sections provide details about each type of action that can be specified.

Iframe actions

When a user clicks an iframe action, a modal dialog with an iframe pointing at the provided URL will open.

Example iframe action:
JSON
//
{
  "type": "IFRAME",
  "width": 890,
  "height": 748,
  "uri": "https://example.com/iframe- contents",
  "label": "Edit",
  "associatedObjectProperties": [
    "some_crm_property"
  ]

}
efinitions:
  • type: Should be IFRAME to indicate that this is an iframe action.
  • width, height: The desired iframe dimensions.
  • uri: The URI opened in the iframe.
  • label: The label displayed in the action dropdown.
  • associatedObjectProperties: A list of properties on the associated contact, company, deal, or ticket. The property values for the current object will be appended to the URI as query parameters when opening the iframe.

Signaling for the modal to close

When the user completes an iframe action, the modal dialog should close and return the user to the original CRM screen. To close the dialog model, the app can use a window.postMessage. The following messages are accepted:

  • {"action": "DONE"} - The user has successfully completed the action.
  • {"action": "CANCEL"} - The user has canceled the action.
Example: window.parent.postMessage(JSON.stringify({"action": "DONE"}), "*");

Note: iframe modals accessed through an iframe action will have a responsive width. 

 

Action hook actions

Action hook actions send a server-side request to an app. The only UI a user sees for this action is a success or error message. This type of action is useful for simple operations that don’t require further user input.

Example action hook action:
JSON
//
{
  "type": "ACTION_HOOK",
  "httpMethod": "POST",
  "uri": "https://example.com/action-hook",
  "label": "Example action",
  "associatedObjectProperties": [
    "some_crm_property"
  ]
}
Definitions:
  • type: Should be ACTION_HOOK to indicate that this is an action hook action.
  • httpMethod: The HTTP method to use when making the request. This can be GET, POST, PUT, DELETE, or PATCH.
  • uri: The URI of the request to make.
  • label: The label to display in the action dropdown.
  • associatedObjectProperties: A list of properties on the associated contact, company, deal, or ticket. If httpMethod is GET or DELETE, these property values will be appended to the URI of the request as query parameters. Otherwise, they’ll be sent as a JSON request body.

See Handling action hooks for more details on how to implement the action endpoint.

Confirmation actions

Confirmation actions behave the same as action hooks, except a confirmation dialog is shown to the user before running the server-side request.

 

JSON
// {
  "type": "CONFIRMATION_ACTION_HOOK",
  "httpMethod": "POST",
  "uri": "https://example.com/action-hook",
  "label": "Example action",
  "associatedObjectProperties": [
    "some_crm_property"
  ],
  "confirmationMessage": "Are you sure you want to run example action?",
  "confirmButtonText": "Yes",
  "cancelButtonText": "No"
}
Definitions:
  • type: Should be ACTION_HOOK to indicate that this is an action hook action.
  • httpMethod: The HTTP method to use when making the request. This can be GET, POST, PUT, DELETE, or PATCH.
  • uri: The URI of the request to make.
  • label: The label to display in the action dropdown.
  • associatedObjectProperties: A list of properties on the associated contact, company, deal, or ticket. If httpMethod is GET or DELETE, these property values will be appended to the URI of the request as query parameters. Otherwise, they’ll be sent as a JSON request body.

See Handling action hooks for more details on how to implement the action endpoint.

Confirmation actions

Confirmation actions behave the same as action hooks, except a confirmation dialog is shown to the user before running the server-side request.

Definitions:
  • type: Should be CONFIRMATION_ACTION_HOOK to indicate that this is a confirmation action hook action.
  • httpMethod: The HTTP method to use when making the request. This can be GET, POST, PUT, DELETE, or PATCH.
  • uri: The URI of the request to make.
  • label: The label to display in the action dropdown.
  • associatedObjectProperties: A list of properties on the associated contact, company, deal, or ticket. If httpMethod is GET or DELETE, these property values will be appended to the URI of the request as query parameters. Otherwise, they’ll be sent as a JSON request body.
  • confirmationMessage: The message to display to the user in the confirmation dialog.
  • confirmButtonText: The text for the "OK" button. This is optional, as the button text will default to "OK".
  • cancelButtonText: Text for the "Cancel" button. This is optional, as the button text will default to "Cancel."

See Handling action hooks for more details on how to implement the action endpoint.