Stocksy API Quickstart Guide
Introduction
This document will take you through the basics of getting started using the Stocksy API. It is intended to get you through the initial steps of using API keys and signing requests. We will take you through a simple flow of authenticating, searching for an asset, purchasing a product and downloading the asset. This document is not intended as a complete reference. For detailed reference documentation, please see our API Reference at https://www.stocksy.com/docs/api/index.html.
What You'll Need To Begin
In order to use the Stocksy API, there are two pieces of information you'll require:
- The first requirement is a Stocksy User Account, consisting of an email and password combination.
- The second requirement is a Stocksy API Key, a generated hash used to uniquely identify your User Account.
Contact us via our API Information page to request API access; we will provide you with a User Account and API Key that allows access to our Sandbox Environment. Our Sandbox Environment allows you to test your implementation and execute all the API operations offered by our endpoint (including purchasing) safely.
Once you are ready to deploy your API implementation, we will provide you with a Production User Account and a Production Environment API Key.
Basic Authentication
In general, authentication using Identity Credentials are required in order to use the Stocksy API.
These Identity Credentials are obtained by requesting a set from our "identity" endpoint using your User Account and your API Key. These are temporary in nature so it is expected that you may need to reauthenticate regularly. To that end, we provide an expiration datetime value with the response indicating when the credentials will expire.
Example Request
Here is an example of using curl to make a request using an identity request with a Stocksy API key and Stocksy User Account (substitute in your API key, email address and password).
Note that in all requests, the API Key you've been provided must always be delivered in a custom X-Api-Key HTTP request header.
curl -X POST "https://api.stocksy.com/identity" -H "X-Api-Key: c8b27sI8WQ4DtvxW9wxi84JEUqoJGFGo46WFRINb" -d "{ \"email\": \"[email protected]\", \"password\": \"password123\"}"
Example Responses
With an invalid API key, you should get an HTTP 200 status code and a response like this:
{"message":"Forbidden"}
With an invalid Stocksy User Account (username/password), you should get an HTTP 403 status code and a response like this:
{"message":"Invalid Credentials"}
With a valid Stocksy API key and a Stocksy User Account, you should get an HTTP 200 status code and a response like this:
{
"AccessKeyId":"RSEA83TWFK6TWEERNORQ",
"SecretKey":"x11PhIP3RoHP9bRnytJ3ZHU3YPS45iSxRO77MyFX",
"SessionToken":"AgoGb3JpHi34EB4aCXVzLWVhc3QtMSKAAlIj4wgDI4gukP1m7kzqRS6oNHKMkn131DfUkgEQ1HdDtDxKCyx\/pbAa1q0XkOU239451gYlViNhsMnktnDzf1wEUqMjez2yq3eZBObEbizaswJkoo0pV3o62gPA4Hnfnc2WGyxAff7cw4j7ztrqtCF3ajZ0\/bwoYkQ0R0hxM193i1YKXdwaZGxiLDGQMhMg0SKsor+83OizzuQcEI6mUCbL6aqetI8kBAdI7k4LR\/5ZYiIlvADALXBp\/wW1g05Ji\/NocHwSiiymoxLSxFv1IjoL6Et2KqPiCaEv7u\/+z16oIbr4eIhfqpTrDp9xAdm50SyqxyAcYMrj2TXJiMznsGcq5QQIw\/\/\/\/\/\/\/\/\/\/\/ARAAGgw4NzQ3MDI4NTU5MzkiDKkMh8QnY6\/Yaqehciq5BNodge5wyhUKV6oOoxhP7TH\/9AXg7ZmM4okjFNw9DEM5xW8goMBT752MhCSXuaHxALam0g1zs1S5J3ZaqYDgr3Rj5QytbbqbTmazywi1zRJv2\/KzKFZKhgkZuDZxA7iIMBJUVgoG08CdqQAZulU6ry274GLX1Hwdt4XbANRqhXCKD30Cu3Ti\/A5\/53Vp8Re2eoQ43BvpBJOr2OUJlH3qAagdZukeDete89EzkTo+s2mmi9g+y6NZN\/5Yvt\/RG+7yaMSskYMZ53+UueCRrG1WqBR4n3629dH\/uUjQbH3ISkkayYmkRjXUEqO0FvcEAks4ITBhhlxGRcbzLuANt2XeXAsixu94lgWZJF4VYSVBEUoPthMnfMTU\/JAApqjJkxyzIuJLvU0CtqlFvMJMd9Q+jmJHRrwN3b3hWbXx7rV5kQuoB0\/BFKNlv+dV+aKnTaoZ8x9Lr+Jc01nyfp4TtFt\/XbIKhtOeVQ8g4g5j9VdNsRorJVYP7NHXiauBCfNmZ\/tPmYSoZ4KwNMAbwNxcbJp3Z5P9J0mV3IODWF+OoNWcYynCD\/SSoW2YylIGbDOhj04u5dUtId0dkx0+S+Yd6j0X4SZBuHib8hzF7RERdelghkzgXgX657HVv+TtDCsF78UKbS250azHttn1K9SRHfpMCqMo0tmagdfy81ZEBuHnUwlbTG3fiW62qTKJ4HLYZXkKpuff5Nrtg7yKc4IYYVr4orQGcQ\/q8vQlUlNdEjj6bsrmMSrAFPaRw6zQMLupz9kF",
"Expiration":"2018-06-27T19:17:31+00:00"
}
Example Python Code
We have provided a Python example below. In this example, we authenticate a user using their Stocksy API key and Stocksy User Account and return the Identity Credentials.
import requests
import json
from boto3 import session
from datetime import datetime, timedelta, tzinfo
from dateutil import parser, tz
from requests_aws_sign import AWSV4Sign
class StocksyApi:
def __init__(self, config):
# On class init, we merge the provided config with the defaults and store them.
defaults = {
"email": "",
"password": "",
"apiKey": "",
"region": "us-east-1",
"url": "https://api.stocksy.com"
}
defaults.update(config)
self.config = defaults
self.creds = None
def getCredentials(self):
# Configuration
region = "us-east-1"
service = "execute-api"
# identity query data. Prepare the headers and the request data
url = self.config["url"] + "/identity"
headers = {'X-Api-Key': self.config["apiKey"]}
dataDict = {"email": self.config["email"], "password": self.config["password"]}
# The request data needs to be properly formatted JSON.
data = json.dumps(dataDict)
# Execute the request, sending the headers and request body as JSON.
myResponse = requests.post(url, headers=headers, data=data)
# For successful API call, response code will be 200 (OK).
# This does not indicate full success. Just that an API call actually happened.
if myResponse.ok:
# Loading the response data into a dict variable
responseData = json.loads(myResponse.content)
# If a request triggered an API call but did not fully succeed, you will get a 200 response
# code, but you will get an error message instead of the results that you want.
if 'message' in responseData.keys():
raise Exception("message : " + responseData['Error'])
# The signing library AWSV4Sign wants credentials in a botocore credentials object
boto_session = session.Session(
aws_access_key_id=responseData["AccessKeyId"],
aws_secret_access_key=responseData["SecretKey"],
aws_session_token=responseData["SessionToken"],
region_name=region)
botoCredentials = boto_session.get_credentials()
# we store the credentials in the class.
self.creds = {
"AccessKeyId": responseData['AccessKeyId'],
"SecretKey": responseData['SecretKey'],
"SessionToken": responseData['SessionToken'],
"Expiration": responseData['Expiration'],
"BotoCredentials": botoCredentials,
"ApiKey": apiKey,
"Service": service,
"Region": region
}
return self.creds
else:
# If response code is not ok (200), print the resulting http error code with description
myResponse.raise_for_status()
# We will instantiate this basic class, feed it our API key and username/password combo,
# and get back our credentials we will use for subsequent requests
config = {
"email": "[email protected]",
"password": "password123",
"apiKey": "c8b27sI8WQ4DtvxW9wxi84JEUqoJGFGo46WFRINb"
}
api = StocksyApi(config)
myCredentials = api.getCredentials()
print ("Your credentials are {}".format(myCredentials))
Signing Requests
Once you have your Identity Credentials, every subsequent request requires the Stocksy API Key submitted via the X-Api-Key header and a signature generated using the Identity Credentials provided above.
Stocksy's API endpoints are protected by Amazon's API Gateway. This gateway expects signatures that are generated following the Amazon's AWS Signature Version 4 method. There are a number of libraries that perform aws-sigv4 request signing, but the methodology is explained in detail in Amazon's AWS Documentation.
If you choose to use a third party library, please ensure that it supports AWS sigv4 calls with a temporary session token. From our experience, it appears that although some libraries are built to generate sigv4 calls with permanent IAM credentials, they do not necessarily support temporary IAM credentials (which also use a session token for added security).
Our examples in this Quickstart guide use the aws-requests-auth Python library.
Example Code
Starting with the code example above, we'll add functionality that signs a request for getting your logged in user's information. In order to do this, we'll take the Identity Credentials, sign the request using those credentials and perform the request to the "users" endpoint.
First, we'll add the "call" method to the StocksyApi class. This general purpose method, given the target URI and request data, signs the request using the credentials and executes a GET or a POST, returning the response.
def call(self, uri, data = None, post = False):
# This is an all-purpose method that signs requests to the specified uri.
# Given the data for the request, we will sign and execute the request, and return the results.
creds = self.getCredentials()
uri = self.config["url"] + uri
standardHeaders = {"Content-Type":"application/json", "X-Api-Key": creds['ApiKey']}
# This generates an AWS V4 request auth object that signs the request when applied.
auth = AWSV4Sign(creds["BotoCredentials"], creds["Region"], creds["Service"])
self.auth = auth
# Send a signed POST or a GET request, using the auth object.
if data and post:
dataJson = json.dumps(data)
response = requests.post(uri, auth=auth, headers=standardHeaders, data=dataJson)
elif data:
response = requests.get(uri, auth=auth, headers=standardHeaders, params=data)
else:
response = requests.get(uri, auth=auth, headers=standardHeaders)
# Parse the result as JSON and return
try:
return json.loads(response.content)
except Exception:
print("Error parsing JSON: {}".format(response.content))
Now we'll add some code that exercises the class to run a signed request to the "users" endpoint.
# We will instantiate this basic class, feed it our API key and username/password combo,
# And perform a request for my user info.
config = {
"email": "[email protected]",
"password": "password123",
"apiKey": "c8b27sI8WQ4DtvxW9wxi84JEUqoJGFGo46WFRINb"
}
api = StocksyApi(config)
userinfo = api.call("/users", None, post=False)
print ("Your userinfo is {}".format(userinfo))
If you are having trouble finding an aws-sigv4 library for the language you are working in, we can help you find one or help guide you on implementing your own version.
Searching for Assets
All Images and Videos on Stocksy are defined as "Assets." Each asset has various metadata elements associated with it, including keywords, orientation, and so on. The API's "search" endpoint exposes most of our search tools, which allows for keyword search as well as filtering using different "facets". These facets encompass specific metadata such as content type and orientation.
In its most basic form, the "search" endpoint only requires a minimal set of information. Here's a basic search for the top 5 matches for "horse", performed by making a GET request to the "search" endpoint.
curl -X GET 'https://api.stocksy.com/search?query=horse&limit=5&page=1' -H 'x-api-key: R1OArV6Mp6Ml8aKZUQt3ZUe1EE8Mqq1SkIyY198i'
Additional parameters can be added; these apply additional facet filters, further narrowing down the search results. Please refer to the API Reference and/or the Swagger definitions for the full list of available options.
curl -X GET 'https://api.stocksy.com/search?query=horse&limit=5&page=1&safe_search=false&facet_contenttype=photo_creative&facet_mobile=false&facet_film=false' -H 'x-api-key: R1OArV6Mp6Ml8aKZUQt3ZUe1EE8Mqq1SkIyY198i'
Example Code
# We will instantiate this basic class, feed it our API key and username/password combo,
# And perform a search against the search API endpoint.
config = {
"email": "[email protected]",
"password": "password123",
"apiKey": "c8b27sI8WQ4DtvxW9wxi84JEUqoJGFGo46WFRINb"
}
api = StocksyApi(config)
searchParams = {
"query": "dog beach",
"limit": 5,
"page": 1,
"facet_contenttype": "photo_creative"
}
searchResults = api.call('/search', searchParams, post=False);
print ("Your search results are {}".format(searchResults))
Getting Asset Information
Once you've selected an asset that you want to view more information about, we'll find out more about it by calling the "assets" endpoint.
In addition to exposing more metadata about the asset in question, it also provides a list of available products for this asset, which we will need for making a purchase later on.
This endpoint also provides access to previously purchased products. For instance, if you purchased a Large download, it would be seen here in future calls to this endpoint.
Example Code
Based on the previous example, we're going to use the "assets" endpoint to retrieve detailed information for each asset and print it out as well.
# We will instantiate this basic class, feed it our API key and username/password combo,
# And retrieve details for Asset 12345.
config = {
"email": "[email protected]",
"password": "password123",
"apiKey": "c8b27sI8WQ4DtvxW9wxi84JEUqoJGFGo46WFRINb"
}
api = StocksyApi(config)
assetData = api.call("/assets/{}".format(12345), None, post=False)
print ("Your asset data is {}".format(assetData))
Important Notes about Stocksy Products
Although we offer a number of products for each asset, they have unique information for each that is important to understand.
First of all, each product has a productTypeId, which needs to be known for purchasing later on. A "product" is a combination of the asset's Id and the productType Id.
Second, each product also has a type, that is either a Deliverable or a License.
- Deliverables are downloadable products, such as a Small, Medium, or Large images or a 720p or 1080p video. When you purchase these you'll be presented with access endpoints to directly download the binary files. Deliverables are always licensed by Stocksy's standard Royalty-Free License.
- Licenses, on the other hand, are extended licenses purchased for extending the rights permitted by the standard license, such as Products for Resale, or a Multi-Seat License to permit use by multiple end clients. These are purchased in addition to the Deliverable. Purchasing a License alone will not provide access to the download!
Finally, although the productTypeIds are always the same numerical values (A medium JPG, for instance, will be productTypeId 2 for all photo assets), not all assets have the same products available as it is dependent on the size and quality of the original source files. For example, we'll only sell an extra-large JPG if the original photo meets the minimum requirements for this product type.
For more information, please review Appendix B for a partial list of available Product Types you may encounter in the responses from the "assets" endpoint.
Making the Purchase
In order to make a purchase, we need to make a POST request to the "purchases" endpoint. The purchase mechanism is quite simple. We generate a list of "products" we wish to buy; each "product" is a combination of assetId and one or more productTypeIds. See the chart in Appendix B for examples of the product types Stocksy sells.
You can purchase several product types simultaneously for a given assetId. For example, you can purchase a "Large" photo (productTypeId 3) and a "Multi-Seat" (productTypeId 8) extended license for a single asset simultaneously. Please note, as previously mentioned, if you wish to purchase an extended license, you also need to purchase a standard license at the same time, or have purchased a standard license in a previous transaction.
Example Code
# We will instantiate this basic class, feed it our API key and username/password combo,
# And purchase three products: A large JPG of asset 12345 with an extended license, and a small JPG of asset 45678
config = {
"email": "[email protected]",
"password": "password123",
"apiKey": "c8b27sI8WQ4DtvxW9wxi84JEUqoJGFGo46WFRINb"
}
api = StocksyApi(config)
requestData = {
# Optional Fields for the Client to track their own purchase history by Client, Project and/or PO Number
"client": "Stork Industries",
"project": "Aluminium Man",
"poNumber": "PO 12345",
# Required information
"products": [
# Large JPG deliverable + Multi-Seat Extended License
{
"assetId": 12345,
"productTypeIds": [3,8]
},
# Small JPG deliverable
{
"assetId": 45678,
"productTypeIds": [1]
}
]
}
purchaseData = api.call("/purchases", requestData, post=True);
print ("Your purchase result data is {}" . format(purchaseData))
This endpoint will respond with information about the purchase you just completed, including a purchaseId that can be used to relocate this purchase. This can be done through running a GET against /purchases/#purchaseId#
or a GET against /purchases
for your purchase history.
In the response on a success, you'll get back metadata about the purchase, a detailed breakdown of payment totals, and a list of products. Each one indicates whether it is deliverable, and if so it provides a URL to the "downloads" endpoint you can GET to retrieve the associated binary.
In addition, any products you've previously purchased of a given assetId will be returned in the purchasedProducts section when performing a GET against the "assets" endpoint.
Downloading a Product
In order to download the files that you just purchased, you need to use the "downloads" endpoint to get a temporary download link that gives you access for a short period of time to your deliverable.
The "downloads" endpoint requires the Purchase Product ID, which is returned in the results of a purchase creation, a lookup of an existing purchase, or in the purchasedProducts section of the asset info lookup.
# Get the download link for a given Purchase Product ID
purchaseProductId = 987654321
config = {
"email": "[email protected]",
"password": "password123",
"apiKey": "c8b27sI8WQ4DtvxW9wxi84JEUqoJGFGo46WFRINb"
}
api = StocksyApi(config)
downloadData = api.call("/downloads/{}".format(purchaseProductId), None, post=False)
print("To download this product use " + downloadData["url"] + " before " + downloadData["expiryDate"])
The URL returned is an S3 signed URL that automatically expires at the returned expiry date (currently 1 hour). If you do not download it before the expiryDate, you can just call the "downloads" endpoint to get a new download link. You should treat this URL as privileged information; if possible, we strongly recommend downloading the deliverable to your system and then redistributing it to your customer.
Next Steps
In this document we've demonstrated many of the main functions of the Stocksy API, but obviously we haven't spent much time on the detailed responses coming back from each of the endpoints. Please review our API Reference for more information about what to expect from our endpoints. We can also help provide preconstructed client libraries for your language based on our Swagger documentation, which we can help validate and provide additional assistance for integration into your environments.
We also have sample code and pre-built clients available for download.
Description | Download Link |
---|---|
Executable Python code examples (ZIP file) These examples are expanded versions of what we used in the examples throughout the Quickstart guide. This may provide a starting point to understanding and using the Stocksy API. |
Download |
Swagger 2.0 API Definition (YAML file) This Swagger API definition file can be used to generate an SDK framework in the language of your choice. Learn more about Swagger at https://swagger.io/ |
Download |
Thank you for reading this guide and we hope that it provides enough information to get you acquainted with the Stocksy API.
Appendix A: About Payment Methods
When Stocksy sets up your API access, your credentials will either be considered as an Individual or in a Group Account. Each of these behaves slightly different and it is worth mentioning it here.
Individuals are required to have one of the following payment configurations: having a saved credit card on their account, carrying a positive balance via cash deposit into your site account, or carrying a line of credit with Stocksy. When purchasing, Stocksy will use all of your account balance first before applying the credit card. If an individual's balance doesn't cover the entire cost of a purchase, it will automatically use the credit card to capture funds. The ability to select the payment method will be addressed in a future version of the "purchases" endpoint.
Group Accounts have specific payment methods associated with them. In the current version of the "checkout" endpoint, it will ONLY use account balance / line of credit payment method to purchase. The ability to select the payment method will be addressed in a future version of the "purchases" endpoint.
In short, here's the various ways customers pay through Stocksy:
- Deposit money into your account through our Deposits page, which you can then spend using the API's "purchases" endpoint.
- Configure a Subscription with Stocksy, which automatically deposits a set amount into your account each month. You can do this by contacting Support.
- Set up a Line of Credit with Stocksy, which allows you to spend and then be invoiced each month. You can do this by contacting Support.
- Configure a Credit Card within your account, which will be charged for each purchase. You can do this under Billing Details on the Profile Edit Page.
Appendix B: Example Product Types
Deliverable Products
Deliverable products are downloadable files that accompany the Stocksy standard royalty-free license. This is a partial list of available deliverable products.
Product Type ID | Name | Photo or Video | Description | Download |
---|---|---|---|---|
1 | Small | Photos | A royalty-free license for advertising, promotional and editorial use for one user. Print copies are limited to 500,000 and web use is unlimited. | JPG Image 0.5 MP or more |
2 | Medium | Photos | A royalty-free license for advertising, promotional and editorial use for one user. Print copies are limited to 500,000 and web use is unlimited. | JPG Image 2 MP or more |
3 | Large | Photos | A royalty-free license for advertising, promotional and editorial use for one user. Print copies are limited to 500,000 and web use is unlimited. | JPG Image 5.7 MP or more |
4 | X-Large | Photos | A royalty-free license for advertising, promotional and editorial use for one user. Print copies are limited to 500,000 and web use is unlimited. | JPG Image 12 MP or more |
51 | 720p Video | Videos | A royalty-free license for advertising, promotional and editorial use for one user. | Graded H264 Video 1280 x 720 or equivalent |
52 | 1080p Video | Videos | A royalty-free license for advertising, promotional and editorial use for one user. | Graded H264 Video 1920 x 1080 or equivalent |
53 | 4k Video | Videos | A royalty-free license for advertising, promotional and editorial use for one user. | Graded H264 Video 3940 x 2160 or larger |
54 | 1080p Ungraded Original Video | Videos | A royalty-free license for advertising, promotional and editorial use for one user. | Ungraded Prores Video 1920 x 1080 or equivalent |
55 | 4k Ungraded Original Video | Videos | A royalty-free license for advertising, promotional and editorial use for one user. | Ungraded Prores Video 3940 x 2160 or larger |
Extended License Products
License products extend the standard royalty-free license associated to the deliverable. These are considered upgrades to existing products and do not have a downloadable file associated with them.
Product Type ID | Name | Photo or Video | Description | Download |
---|---|---|---|---|
5 | Unlimited Print | Photos | Removes restriction of 500,000 and allows for unlimited print copies. Multi-Seat usage is included. | No Download |
6 | Products for Resale | Photos | Allows use of the image in your design to sell on t-shirts, greeting cards, posters, calendars, etc. Multi-Seat usage is included. | No Download |
8 | Multi-Seat (Unlimited) | Photos | Allows for an unlimited number of users in an organization to use the content. | No Download |
61 | Multi-Seat (Unlimited) | Videos | Allows for an unlimited number of users in an organization to use the content. | No Download |
62 | Products for Resale | Videos | Allows use of the video in your product to sell in an unaltered state, such as sample clips for video projects. Multi-Seat usage is included. | No Download |