OAuth 2.0

Use OAuth 2.0 for more complicated integrations that involve taking actions on behalf of end users, such as licensing and downloading images.

OAuth is a protocol which lets external apps authenticate and request authorization to details in a user's Shutterstock account without needing access to their password. OAuth2 is described in detail in RFC6749. There are many existing libraries that can be used to perform the OAuth2 flow. The rest of the document will outline the specific endpoints and parameters supported by the Shutterstock API.

Registering an Application

All developers need to register their application before getting started. A registered OAuth application is assigned a unique Client ID and Client Secret. The Client Secret should not be shared. You can register an application by going here.

Sample code

Express.js with Passport.js

If you are using Express, you can use the shutterstock/passport-shutterstock-oauth2 middleware which provides the logic needed to use Shutterstock as an OAuth choice for your users. The library, and an example integration are in the GitHub repo shutterstock/passport-shutterstock-oauth2.

Javascript

We have also released a client side Javascript library to simplify the process of authorizing a user via a browser window or popup. The library, detailed documentation, and an example are in the GitHub repo shutterstock/shutterstock-oauth-sample.

User Authorization

One of the most common ways of using OAuth is to get a user's authorization to act on their behalf. In this flow, your application will begin by a get request to the authorize endpoint which will redirect them to the Shutterstock login page. The login page will show the user the hostname of your application and the permissions you are requesting for their account. If your API integration involves the use of only one user account (for example to license images under one enterprise account) you can run the CURL requests in the Authentication Guide and re-use the resulting access_token for subsequent requests without needing to implement the OAuth2 flow within your client application.

oauth_popup

Once the user logs in (signaling that they authorize your application to act on their behalf), Shutterstock will redirect them back to the specified redirect_uri in your application where your application will use the code parameter when contacting the /oauth/access_token endpoint (described below) to retreive an access_token which can be used in future requests for Shutterstock resources such as the user's profile, or licensing content using the user's account.

Authorize Endpoint

GET https://api.shutterstock.com/v2/oauth/authorize

Parameters

Name Type Description Default
client_id string Required. The client ID you received from Shutterstock when you registered. N/A
realm string Optional. The user type which you would like to grant you access. Options: customer or contributor customer
redirect_uri string Required The uri Shutterstock will redirect the user to after they finish with the authorize. N/A
response_type string Required. Only code is supported right now. N/A
scope string Optional. The list of scopes you would like the user to grant you access. user.view
state string Required. The given value will be passed back to the redirect_uri so you can verify the request N/A

Response

The response will be in the form of a redirect:

... Redirecting to https://accounts.shutterstock.com/login?next=%2Foauth%2Fauthorize%3Fstate%3Ddemo_1447708817%26response_type%3Dcode%26redirect_uri%3Dhttp%3A%2F%2Flocalhost%3A3000%2Fcallback%26client_id%3D1234567890qwertyuiopasdfghjklzxcvbnm

User Redirection

The redirect_uri parameter's host and port must exactly match the host by which the application was registered.

HOST: example.com

GOOD: http://example.com/path
GOOD: http://example.com/path/subdir/other
BAD: http://example.com/
BAD: http://example.com:8080/path
BAD: http://oauth.example.com/path
BAD: http://example.org

If the user denies your request or it fails, Shutterstock will redirect the user back to your site with the following params:

Name Description
code The code to be used to request an access token.
state The unique state parameter which was passed in the request.
error The type of failure. Most-likely "access_denied"
error_reason The reason why the authorization failed.
error_description A human readable description of the error reason.

If the user accepts your request, Shutterstock redirects the user back to your site with a temporary code in a code parameter as well as the state you provided in the previous step in a state parameter. If the states don't match, the request has been created by a third party and the process should be aborted.

Token Endpoint

POST https://api.shutterstock.com/v2/oauth/access_token

Parameters

Name Type Description
client_id string Required. The client ID you received from Shutterstock when you registered.
client_secret string Required. The client secret you received from Shutterstock when you registered.
code string Required. The code you received as a response from the user authorization step.
grant_type string Required. The OAuth2 Grant Type you will use. Supported values: authorization_code, client_credentials
realm string Optional. The user type which you would like to grant you access. Options: customer or contributor customer

Response

Access tokens are the key to using the Shutterstock API. Access tokens prefixed with v2/ do not expire and do not need to be renewed with a refresh_token.

The response will be in the form of JSON:

{
    "access_token":"v2/pl0okm9ijn8uhb7ygv6tfc5rdx4esz3wa2q1qasz2wsdxc3edcf4rfgv5tgb6yhn7ujm8ijFGHJKLpl0okm9ijn8uhb7ygv6tfc5rdx4esz3wa2q1qasz2wsdxc3edcf4rfgv5tgb6yhn7ujm8ijFGHJKLpl0okm9ijn8uhb7ygv6tfc5rdx4esz3wa2q1qasz2wsdxc3edcf4rfgv5tgb6yhn7ujm8ijFGHJKLpl0okm9ijn8uhb7ygv6tfc5rdx4esz3wa2q1qasz2wsdxc3edcf4rfgv5tgb6yhn7ujm8ijFGHJKLpl0okm9ijn8uhb7ygv6tfc5rdx4esz3wa2q1qasz2wsdxc3edcf4rfgv5tgb6yhn7ujm8ijFGHJKL",
    "token_type":"Bearer"
}

Using the access token

The access token allows you to make requests to the API on a behalf of a user.

curl https://api.shutterstock.com/v2/user?access_token=$ACCESS_TOKEN

You can pass the token in the query params like shown above, but a cleaner approach is to include it in the Authorization header

Authorization: Bearer $ACCESS_TOKEN

For example, in curl you can set the Authorization header like this:

curl -H "Authorization: Bearer $ACCESS_TOKEN" https://api.shutterstock.com/v2/user

The response from the /user route will contain user identifiable JSON data such as this:

{
  "id": "123456789",
  "username": "test",
  "full_name": "",
  "first_name": "Test",
  "last_name": "User",
  "organization_id": "8831",
  "language": "en",
  "email": "api@shutterstock.com",
  "customer_id": "9876543210"
}

Note that the email will not be provided unless you requested the user.email scope.

Grant Types

grant_type Description
authorization_code This is the most familiar OAuth2 grant type. It involves three parties: an authorization server (Shutterstock), a client (your application), and a user agent (the end-user's browser)
client_credentials When there's no end-user involved and it is just one system talking to another, this is the grant type to use.

Authorizing Without a User

In rare cases, when there is no actual user, you could use a Client Credentials grant. If your integration requires licensing images on behalf of only one user, you cannot use a Client Credentials Grant, instead see the guide for Single User Integration. Unlike the familiar Authorization Code grant type, Client Credentials grants require only one step: a POST to the access token route.

Token Endpoint

POST https://api.shutterstock.com/v2/oauth/access_token

Parameters

Name Type Description
client_id string Required. The client ID you received from Shutterstock when you registered.
client_secret string Required. The client secret you received from Shutterstock when you registered.
grant_type string Required. The OAuth2 Grant Type you will use. For authorization without a user, use the value client_credentials

Response

The response will be the same as for the Authorization Code grant, with the exception that access token you receive from a Client Credentials grant lasts for one hour before you need to request a one.

Refreshing a Token

Access tokens for client_credentials expire after one hour, to renew them your app must send another POST request for the client_credentials grant type.

Scopes

Scopes let you specify exactly what type of access you need. Scopes limit access for OAuth tokens. They do not grant any additional permission beyond that which the user already has.

Requested scopes will be displayed to the user on the authorize form.

permission_request

Name Description
(no scope) Implies user.view.
user.view Default. Grants read-only access to a user's basic account information (includes username, id, first and last name). If email is the same as username, it also implies user.email.
user.email Grants read-only access to a user's email address.
user.address Grants read-only access to a user's physical address.
organization.view Grant read-only access to basic information about a user's organization.
organization.address Grant read-only access to a user's organization's address.
collections.view Grant read-only access to a user's collections (lightboxes, clipboxes, etc.).
collections.edit Grant read and write access to a user's collections (lightboxes, clipboxes, etc.).
licenses.view Grant read-only access to a user's licenses.
licenses.create Grant the ability to download and license media on behalf of the user.
purchases.view Grant read-only access to a user's purchase history.
earnings.view Grant the ability to view a user's current earnings and payouts.
media.upload Grant the ability to upload media to a user's account.
media.submit Grant the ability to submit a user's uploaded media for review and check their approval states.
media.edit Grant the ability to make changes to a user's existing approved media.

NOTE: Your application can request the scopes in the initial redirection. You can specify multiple scopes by separating them with a space:

https://api.shutterstock.com/v2/oauth/authorize?
  client_id=$CLIENT_ID&
  scope=user.view user.email collections.view

Requested scopes vs. granted scopes

The scope attribute lists scopes attached to the token which were granted by the user. Unless the scopes are specially reserved for privileged clients, these scopes will be identical to what you requested. You should be aware of this possibility and adjust your application's behavior accordingly.

It is important to handle error cases where you are granted less access than you originally requested. For example, your application may need to warn or otherwise communicate with its users that they will see reduced functionality or be unable to perform some actions.

Also, applications can always send users back through the flow again to get additional permissions, but don't forget that users can always say no.

Common Errors

There are a few things that can go wrong in the process of obtaining an OAuth token for a user. In the initial authorization request phase, these are some errors you might see:

Redirect URI mismatch

If you provide a redirect_uri which is not on the hostname which you used when you registered with your application, Shutterstock will display an error message to your users indicating that your application has been blocked from doing something dangerous:

Invalid redirect URI:
The Redirect URI http://someplace.com doesn't match the valid hostnames for this client.

invalid_redirect_url

To avoid this error, you must provide a redirect_uri which is hosted on the hostname which you indicated during your API key registration, or update the hostnames of your application.

Access denied

If the user rejects access to your application, Shutterstock will redirect to the registered callback URL with the following parameters summarizing the error:

http://localhost:3000/callback?error=access_denied
  &error_description=The user denied the authorization request.
  &error_reason=user_denied

There's nothing you can do here as users are free to choose not to use your application. More often than not, users will just close the window or press back in their browser, so it is unlikely that you'll ever see this error.

Missing required parameters

If a required parameter is not passed, you will receive an error response status code of 400 with text "Validation failed"

{
  "message": "Validation failed",
  "errors": [{
    "code": "VALIDATION_OBJECT_REQUIRED",
    "message": "Missing required property: client_id"
  }]
}

If the client_id and or client_secret is not passed correctly, you will receive an error response status code of 400 with text "Authorization scheme not supported!"

If the client_id and or client_secret is not correct, you will receive an error response status code of 403 with text "Invalid client_id/secret given."