Please note! This version of the API is in beta and may change. If you would like to use a stable version of the API please see version 1.

Getting Started with the UserVoice API v2

The UserVoice API provides a fast and easy way of working with your feedback data that allows you to build client applications and custom integrations.

Authentication

Any interaction with the UserVoice API requires a trusted API client. You can create one from your UserVoice Admin Console in Settings → Integrations → UserVoice API keys.

Enter a name for the API Client. Make sure the “Trusted” checkbox is checked:

When you create your client you will see a “key” and a “secret”: these are the credentials you will use to access the API.

Beware: You should never store trusted client credentials in an insecure environment (for example: in your client-side JavaScript or a public source code repository). Trusted clients have full access to perform the same actions admins do, including deleting content.

Note: The UserVoice API requires all calls to be made over SSL. Please use HTTPS for all requests to ensure the security and privacy of your data.

To make an API request, you will need an API token. You can request a token for your UserVoice account owner with the API key and secret. Here’s how it would be done with curl:

$ curl https://SUBDOMAIN.uservoice.com/api/v2/oauth/token \
       --data "grant_type=client_credentials;client_id=KEY;client_secret=SECRET"
Example response:
{"access_token": "096e8ae9c6a3c039"}

Now you can authenticate your API requests by passing your access_token in the Authorization header. Here’s how you would do that with curl:

  $ curl https://SUBDOMAIN.uservoice.com/api/v2/admin/users/current \
       -H "Authorization: Bearer 096e8ae9c6a3c039"

All requests to the API will need to use this Authorization header for access. Store the token in your client application. For instance, you might save it in a session store, connection object, or variable, as convenient on your platform.

If the token expires or is invalidated, the API will return a 401 Unauthorized error that looks like this:

  {"errors":{"error":"not_authorized"}}

At this point, your application should request a new access_token and retry the request with the new token.

Data Format

The UserVoice API will respond to all requests with a JSON data structure. Bodies for POST and PUT requests can be passed as either JSON or url-form-encoded data.

JSON Request:
  $ curl https://SUBDOMAIN.uservoice.com/api/v2/admin/suggestions \
       -X "POST" \
       -H "Authorization: Bearer 096e8ae9c6a3c039" \
       -H "Content-type: application/json" \
       -d "{
           'title': 'Test Suggestion',
           'links': {
              'forum': 1
            }
          }"
Form Request:
  $ curl https://SUBDOMAIN.uservoice.com/api/v2/admin/suggestions \
       -X "POST" \
       -H "Authorization: Bearer 096e8ae9c6a3c039" \
       -H "Content-type: application/x-www-form-urlencoded" \
       -d "title=Test+Suggestion&links.forum=1"
Response:
  {
    "links": {
      "suggestions.category": {
        "type": "categories"
      },
      "suggestions.created_by": {
        "type": "users"
      },
      "suggestions.forum": {
        "type": "forums"
      },
      "suggestions.labels": {
        "type": "labels"
      },
      "suggestions.last_status_update": {
        "type": "status_updates"
      },
      "suggestions.parent_suggestion": {
        "type": "suggestions"
      },
      "suggestions.status": {
        "type": "statuses"
      },
      "suggestions.ticket": {
        "type": "tickets"
      }
    },
    "suggestions": [
      {
        "id": 184102,
        "title": "Test Suggestion",
        "body": "",
        "body_mime_type": "",
        "portal_url": "http://SUBDOMAIN.uservoice.com/forums/1/suggestions/184102",
        "admin_url": "https://SUBDOMAIN.uservoice.com/admin/v3/suggestions/184102",
        "created_at": "2017-02-24T16:27:36Z",
        "creator_user_agent": null,
        "creator_referrer": null,
        "creator_browser": null,
        "creator_browser_version": null,
        "creator_os": null,
        "creator_mobile": false,
        "state": "approved",
        "inappropriate_flags_count": 0,
        "approved_at": null,
        "updated_at": "2017-02-24T16:27:36Z",
        "closed_at": null,
        "comments_count": 0,
        "notes_count": 0,
        "requests_count": 0,
        "votes_count": 0,
        "supporters_count": 0,
        "supporting_accounts_count": 0,
        "supporter_mrr": 0,
        "supporter_satisfaction_score": 0,
        "satisfaction_detractor_count": 0,
        "satisfaction_promoter_count": 0,
        "satisfaction_neutral_count": 0,
        "average_engagement": 0,
        "recent_engagement": 1,
        "engagement_trend": 0,
        "first_support_at": null,
        "links": {
          "forum": 1,
          "category": null,
          "labels": null,
          "status": null,
          "parent_suggestion": null,
          "ticket": null,
          "last_status_update": null,
          "created_by": 9182
        }
      }
    ]
  }

Associations & Side-loading

The response JSON object contains a key for each collection you request. The value of each key is an array of objects. Using the “includes” param, you can easily side-load associated records. This allows you to request additional data in a single query and gives you control over the weight of the response. The “links” object in a response provides a list of available associations.

In this example, we’re requesting a list of suggestions and side-loading the associated forums and users:

  $ curl https://SUBDOMAIN.uservoice.com/api/v2/admin/suggestions?includes=forums,users \
       -H "Authorization: Bearer 096e8ae9c6a3c039"
(Simplified) Response:
  {
    "forums": [
      {
        "id": 2002,
        "name": "Product Ideas",
        "open_suggestions_count": 1,
        "suggestions_count": 1,
        "is_public": true,
        "created_at": "2017-01-20T14:24:45Z",
        "updated_at": "2017-01-20T14:24:45Z",
        "links": {
          "updated_by": null
        }
      }
    ],
    "links": {
      "forums.updated_by": {
        "type": "users"
      },
      "suggestions.category": {
        "type": "categories"
      },
      "suggestions.created_by": {
        "type": "users"
      },
      "suggestions.forum": {
        "type": "forums"
      },
      "suggestions.labels": {
        "type": "labels"
      },
      "suggestions.last_status_update": {
        "type": "status_updates"
      },
      "suggestions.parent_suggestion": {
        "type": "suggestions"
      },
      "suggestions.status": {
        "type": "statuses"
      },
      "suggestions.ticket": {
        "type": "tickets"
      },
      "users.current_nps_rating": {
        "type": "nps_ratings"
      },
      "users.external_users": {
        "type": "external_users"
      },
      "users.previous_nps_rating": {
        "type": "nps_ratings"
      },
      "users.teams": {
        "type": "teams"
      }
    },
    "list_meta": null,
    "pagination": {
      "page": 1,
      "per_page": 20,
      "total_pages": 1,
      "total_records": 1
    },
    "suggestions": [
      {
        "id": 303,
        "title": "Make the logo bigger",
        "body": "I love your logo but I can barely see it!",
        "created_at": "2012-07-19T14:23:16Z",
        "state": "published",
        "updated_at": "2017-01-20T14:24:47Z",
        "comments_count": 1,
        "links": {
          "forum": 2002,
          "category": null,
          "labels": null,
          "status": null,
          "parent_suggestion": null,
          "ticket": null,
          "last_status_update": null,
          "created_by": 1001
        }
      }
    ],
    "users": [
      {
        "id": 1001,
        "name": "Logo Fan",
        "email_address": "logofan@example.com",
        "avatar_url": "https://cdn.uservoice.com/pkg/admin/icons/user_80-fc2452956c9d66d679a429bd81acd3f3.png",
        "created_at": "2017-01-20T14:24:47Z",
        "updated_at": "2017-01-20T14:24:47Z",
      }
    ]
  }

Using the “links” property of the suggestion object, we can map the “forum” and “created_by” ids to the forum our suggestion belongs to and the user that created it.

Pagination

You can use the “per_page” and “page” params to iterate through collections. “per_page” defaults to 20 with a max of 100. The “pagination” object in the response includes info about the record and page count:

  "pagination": {
    "page": 1,
    "per_page": 100,
    "total_pages": 3,
    "total_records": 272
  }

Rate Limiting

API requests have per-minute rate limiting. Each request counts toward your limit. Not all requests are created equal: if a request takes longer than 1 second to compute then another “request” is counted for every whole second after the first. This helps us account for expensive endpoints (like complex searches) that use more resources.

Once you have exceeded your limit for the current minute, the UserVoice API will return a 429 HTTP error response for subsequent requests.

Every request returns the following HTTP headers:

  • X-Rate-Limit-Limit: The number of requests available every minute
  • X-Rate-Limit-Remaining: The number of requests remaining this period
  • X-Rate-Limit-Reset: The unix epoch in seconds when the limit resets

Once rate limited, every request returns the following HTTP header:

  • Retry-After: The unix epoch in seconds until the rate limit expires

The limit depends on your plan. See Terms of Service for details.

Take advantage of side-loading, per_page settings and bulk endpoints to consolidate your requests.

File Uploads

The UserVoice API allows you to upload files and link them to suggestions. This is done through a two-step process.

  1. Use the Attachments API to upload your file in multipart/form-data format. Take note of the token in the response, as this will allow you to link the file to a suggestion later on. Note: If you lose your access token, don’t worry. You can retrieve it later through our GET endpoint!
  2.     $ curl https://SUBDOMAIN.uservoice.com/api/v2/admin/attachments \
             -H "Authorization: Bearer <token>" \
             -F "file=@/path/to/file"
      
        {
          "attachments": [
            {
              "id": 116876320,
              "file_name": "test.jpg",
              "content_type": "image/jpeg",
              "size_in_bytes": 14919,
              "updated_at": "2017-02-16T14:06:35Z",
              "created_at": "2017-02-16T14:06:35Z",
              "url": "someUrl.com",
              "thumb_url": "someOtherUrl.com",
              "token": "1234567890ebcf3635a209ab4ozp1kd9",
              "links": {
                "suggestion": null,
                "note": null
              }
            }
          ],
          "links": {
            "attachments.note": {
              "type": "notes"
            },
            "attachments.suggestion": {
              "type": "suggestions"
            }
          }
        }
      
  3. Use the token you received in the response to link the file to a suggestion or when creating a note. Take a look at our Suggestions API for how to update a suggestion with an attachment token, or at our Notes API for how to create a note with an attachment token.
  4.     $ curl https://SUBDOMAIN.uservoice.com/api/v2/admin/suggestions/ID \
              -X "PUT" \
              -H "Authorization: Bearer <token>" \
              -d attachment_tokens=1234567890ebcf3635a209ab4ozp1kd9,someOtherToken
      
        {
          "links": {
            "suggestions.category": {
              "type": "categories"
            },
            "suggestions.created_by": {
              "type": "users"
            },
            "suggestions.forum": {
              "type": "forums"
            },
            "suggestions.labels": {
              "type": "labels"
            },
            "suggestions.last_status_update": {
              "type": "status_updates"
            },
            "suggestions.parent_suggestion": {
              "type": "suggestions"
            },
            "suggestions.status": {
              "type": "statuses"
            },
            "suggestions.ticket": {
              "type": "tickets"
            }
          },
          "suggestions": [
            {
              "id": 12345,
              "title": "Make a Getting Started Guide",
              "body": "A good starting guide would be helpful thanks!",
              "body_mime_type": "",
              "portal_url": "http://SUBDOMAIN.uservoice.com/forums/54321/suggestions/12345",
              "admin_url": "https://SUBDOMAIN.uservoice.com/admin/v3/suggestions/12345",
              "created_at": "2013-03-08T00:17:42Z",
              "creator_user_agent": null,
              "creator_referrer": null,
              "creator_browser": null,
              "creator_browser_version": null,
              "creator_os": null,
              "creator_mobile": false,
              "state": "approved",
              "inappropriate_flags_count": 0,
              "approved_at": null,
              "updated_at": "2017-02-16T14:09:34Z",
              "closed_at": null,
              "comments_count": 2,
              "notes_count": 0,
              "requests_count": 0,
              "votes_count": 1,
              "supporters_count": 0,
              "supporting_accounts_count": 0,
              "supporter_mrr": 0,
              "supporter_satisfaction_score": 0,
              "satisfaction_detractor_count": 0,
              "satisfaction_promoter_count": 0,
              "satisfaction_neutral_count": 0,
              "average_engagement": 0,
              "recent_engagement": 0,
              "engagement_trend": 0,
              "first_support_at": null,
              "links": {
                "forum": 54321,
                "category": null,
                "labels": null,
                "status": 567899,
                "parent_suggestion": null,
                "ticket": null,
                "last_status_update": 5321563,
                "created_by": 32364234
              }
            }
          ]
        }
      

Constraints

File Size: 50 MB (50000000 bytes)

A complete list of endpoints is available in our API v2 Reference.