Table of Content

  1. Overview

    1. Content rights

    2. Versioning

    3. Authentication and Authorization

    4. Pagination

    5. Rate Limiting

  2. Media

    1. Media Sizing Options

    2. GET MEDIA BY ID

    3. CREATE SEARCH RESULT

    4. GET RESULT PER PAGE

Olapic Content API provides programmatic access to media search. This API allows you to retrieve content that matches specific hashtags, specific keywords, product name, or even geographical location.

This API is a REST API, and its responses are available in JSON format.

Content rights

This API only returns content that have rights-approved status. For more information on the rights approval process, please refer to our documentation on Request Rights to Content

Versioning

A versioning number must be included in the endpoint URI:

/{version}/media/search

Example request:

POST /v1/media/search HTTP/1.1 Host: content.photorank.me Content-Type: application/json { ... }

Authentication and Authorization

API calls must be authenticated using an API KEY that must be provided as an Authorization request header, with the following format:

ApiKey token="{your_api_key}"

In order to get an API KEY, contact your Account Manager.

Example request:

POST /v1/media/search HTTP/1.1 Host: content.photorank.me Content-Type: application/json Authorization: ApiKey token="{your_api_key}" { ... }

Pagination

For the endpoints that return a collection of objects, the maximum number of returned elements per page can be set by sending the parameter items_per_page as a query string.

The value sent can be any integer number between 5 and 100. The default value is 20.

In order to navigate through the generated pages, use the URIs in the attribute data.pagination of the API responses. These URIs must not be saved since they have an expiration time.

The expiration time for the pagination links is 43200 seconds (or 12 hours).

If the value of attribute pagination.next equals null, the current page is the last page. The header Authorization must be included in the requests.

Example:

  1. Make a first request to create a result set:

Request:

POST /v1/media/search HTTP/1.1 Host: content.photorank.me Content-Type: application/json Authorization: ApiKey token="{your_api_key}" { ... }

Response:

{
"metadata": {
"code": 200,
"message": "OK"
},
"data": {
...,
"pagination": {
"self": "https://content.photorank.me/v1/media/search?page_key={page_key}&page_number=1",
"first": "https://content.photorank.me/v1/media/search?page_key={page_key}&page_number=1",
"next": "https://content.photorank.me/v1/media/search?page_key={page_key}&page_number=2",
"prev": null
}
}
}
  1. In order to move to the next page, follow the link in data.pagination.next.

Request:

GET /v1/media/search?page_key={page_key}&page_number=2 HTTP/1.1 Host: content.photorank.me Content-Type: application/json Authorization: ApiKey token="{your_api_key}"

Rate Limiting

Every API KEY has enforced rate limits. These limits are:

  • Up to 5 requests per second.

  • Up to 500 requests per hour.

  • Up to 100,000 requests per month.

The returned HTTP headers of any API request includes the current rate limit status. The following table provides the name and description of these headers.

Header Name

Description

X-RateLimit-Limit

The maximum number of requests that the consumer is permitted to make per hour.

X-RateLimit-Remaining

The number of requests remaining in the current rate limit window.

X-RateLimit-Reset

The time at which the current rate limit window resets in UTC epoch seconds.

Example:

HTTP/1.1 200 OK Date: Mon, 05 Dec 2016 18:07:05 GMT X-Rate-Limit-Limit: 500 X-Rate-Limit-Remaining: 498 X-Rate-Limit-Reset: 1480964400000

When an application exceeds any rate limit, the API will return an HTTP 429 “Too Many Requests” response code.

Example:

HTTP/1.1 429 Too Many Requests Date: Mon, 05 Dec 2016 18:13:38 GMT Content-Type: application/json 
{
"metadata": {
"code": 429,
"message": "Too Many Requests"
},
"data": {
"message": "Rate limit quota violation: [hour] quota limit exceeded."
}
}

Media

The entity media represents the media content Olapic collects from various sources.

Media Sizing Options

For every media object returned in the request response, you can access the property images to retrieve the URIs of the media assets.

Example object:

{ "id": 2360204628, "source": "instagram", ..., "images": { "square": "https://z1photorankmedia-a.akamaihd.net/media/2/3/w/23wyvu3/square.jpg", "thumbnail": "https://z3photorankmedia-a.akamaihd.net/media/2/3/w/23wyvu3/thumbnail.jpg", "mobile": "https://photorankmedia-a.akamaihd.net/media/2/3/w/23wyvu3/mobile.jpg", "normal": "https://z2photorankmedia-a.akamaihd.net/media/2/3/w/23wyvu3/normal.jpg", "original": "https://z3photorankmedia-a.akamaihd.net/media/2/3/w/23wyvu3/original.jpg" }, ... }

The object property images contains five different versions of the asset. The following table lists the different versions and its proper description.

Version

Specification

square

90x90px image. Cropped, does not maintain ratio.

thumbnail

150x150px image. Maintains ratio.

mobile

320x320px image. Maintains ratio.

normal

640x640px image. Maintains ratio.

original

Original image without modifications. If available this could be in HD.

GET MEDIA BY ID

This endpoint returns media object(s) for the given ID(s).

HTTP Request

GET /v1/media?ids={ids}

To get specific media from the Content API, simply pass in a comma separated list of IDs to the media endpoint.

Parameters

ids

string (required)

Comma separated list of ID(s) of requested media objects.

Responses 200

Headers

Content-Type: application/json

Body

{
"data": {
"media": {
"{id_01}": {
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id_01}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": {
"lat": "{lat}",
"long": "{long}"
},
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
},
"{id_02}": {
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id_02}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": null,
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
}
}
},
"metadata": {
"code": 200,
"message": "OK"
}
}

CREATE SEARCH RESULT

This endpoint allows to get media that matches certain filters.

HTTP Request

POST /v1/media/search?items_per_page={items_per_page}

To create a new search, the POST method must be used. This allows to build a complex search criteria. The result obtained is the first page of the paginated result set.

To navigate through the pages, follow the pagination links using a GET method.

NOTE:

The Authorization header must be used always, as this is the mechanism that allows only authorized clients to access their earned content.

Parameters

items_per_page

number (optional)

Count of media in a page. See Pagination section for more information.

Requests Search

Headers

Content-Type: application/json

Body

{
"filters": {
"keywords": {
"values": [
"adventure",
"sunny"
],
"condition": "or"
},
"stream_name": "Hello, world!",
"caption": "Hello, world!",
"hashtags": {
"values": [
"adventure",
"sunny"
],
"condition": "or"
},
"location": {
"distance": 100,
"center": {
"lat": 40.714,
"long": -74.0155
},
"condition": "and"
}
},
"sort": [
{
"key": "relevance",
"order": "asc"
}
],
"fields": [
"id",
"source",
"source_id",
"original_source",
"caption",
"images",
"images.mobile",
"images.normal",
"images.original",
"images.square",
"images.thumbnail",
"date_submitted",
"date_approved",
"keywords",
"hashtags",
"location",
"streams",
"user",
"user.name",
"user.username",
"user.avatar_url"
]
}

Schema

{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"filters": {
"type": "object",
"properties": {
"keywords": {
"type": "object",
"properties": {
"values": {
"type": "array",
"description": "Keywords filters Value/s"
},
"condition": {
"type": "string",
"enum": [
"or",
"and"
],
"default": "or",
"description": "Keywords filter condition"
}
},
"description": "Object with keywords filters values"
},
"stream_name": {
"type": "string",
"description": "String value of the stream name"
},
"caption": {
"type": "string",
"description": "String value of the caption"
},
"hashtags": {
"type": "object",
"properties": {
"values": {
"type": "array",
"description": "Hashtag filters Value/s"
},
"condition": {
"type": "string",
"enum": [
"or",
"and"
],
"default": "or",
"description": "Keywords filter condition"
}
},
"description": "Object with hashtags filters values"
},
"location": {
"type": "object",
"properties": {
"distance": {
"type": "number",
"description": "Maximum search radius distance in meters from the center point. Accepted range: greater than 0 and less than or equal to 10000."
},
"center": {
"type": "object",
"properties": {
"lat": {
"type": "number",
"description": "Latitude of the center point. Accepted range: greater than or equal to -90.0 and less than or equal to 90.0."
},
"long": {
"type": "number",
"description": "Longitude of the center point. Accepted range: greater than or equal to -180.0 and less than or equal to 180.0."
}
},
"description": "Object to represent the center point"
},
"condition": {
"type": "string",
"enum": [
"and",
"or"
],
"default": "and",
"description": "Location filter condition"
}
},
"description": "Object with location filters values. The filter allows you to search for media using geospatial search (center point)."
}
},
"description": "Object with filters options"
},
"sort": {
"type": "array",
"description": "Criteria to order the result set"
},
"fields": {
"type": "array",
"description": "List of fields to include in the response."
}
}
}

Responses 200

Headers

Content-Type: application/json

Body

{
"data": {
"media": [
{
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": {
"lat": "{lat}",
"long": "{long}"
},
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
},
{
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": null,
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
},
{
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": {
"lat": "{lat}",
"long": "{long}"
},
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
},
{
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": null,
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
},
{
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": {
"lat": "{lat}",
"long": "{long}"
},
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
}
],
"pagination": {
"first": "https://content.photorank.me/v1/media/search?page_key={page_key}&page_number={page_number}",
"next": "https://content.photorank.me/v1/media/search?page_key={page_key}&page_number={page_number}",
"prev": null,
"self": "https://content.photorank.me/v1/media/search?page_key={page_key}&page_number={page_number}"
}
},
"metadata": {
"code": 200,
"message": "OK"
}
}

Response 400

Headers

Content-Type: application/json

Body

{
"data": {
"message": "The parameter \"keywords\" received an invalid value, expected was \"[valid Keyword]\"."
},
"metadata": {
"code": 400,
"message": "Bad Request"
}
}

Response 400

Headers

Content-Type: application/json

Body

{
"data": {
"message": "The parameter \"sort.key\" received an invalid value, expected was \"[valid sort key]\"."
},
"metadata": {
"code": 400,
"message": "Bad Request"
}
}


GET RESULT PER PAGE

HTTP Request

GET /v1/media/search?page_key={page_key}&page_number={page_number}

This endpoint allows to navigate through pages of a previously created search with Search endpoint.

This URI can only be used after a media search result has been created.

See the Pagination section for more information.

Parameters

page_key

string (required)

Pagination key. It allows to identify a search result set. It must be provided in order to get a page from the result set. This value is created with the first POST request to Search endpoint.

page_number

number (required)

Page number to get.

Responses

Responses 200

Headers

Content-Type: application/json

Body

{
"data": {
"media": [
{
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": {
"lat": "{lat}",
"long": "{long}"
},
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
},
{
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": null,
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
},
{
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": {
"lat": "{lat}",
"long": "{long}"
},
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
},
{
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": null,
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
},
{
"caption": "{caption}",
"date_approved": "{date_approved}",
"date_submitted": "{date_submitted}",
"hashtags": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"id": "{id}",
"images": {
"mobile": "{mobile}",
"normal": "{normal}",
"original": "{original}",
"square": "{square}",
"thumbnail": "{thumbnail}"
},
"keywords": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"location": null,
"original_source": "{original_source}",
"source": "{source}",
"source_id": "{source_id}",
"streams": [
"{value_01}",
"{value_02}",
"{value_n}"
],
"user": {
"name": "{name}",
"username": "{username}",
"avatar_url": "{avatar_url}"
}
}
],
"pagination": {
"first": "https://content.photorank.me/v1/media/search?page_key={page_key}&page_number={page_number}",
"next": "https://content.photorank.me/v1/media/search?page_key={page_key}&page_number={page_number}",
"prev": "https://content.photorank.me/v1/media/search?page_key={page_key}&page_number={page_number}",
"self": "https://content.photorank.me/v1/media/search?page_key={page_key}&page_number={page_number}"
}
},
"metadata": {
"code": 200,
"message": "OK"
}
}

Response 404

Headers

Content-Type: application/json

Body

{
"data": {
"message": "No pagination found."
},
"metadata": {
"code": 404,
"message": "Not Found"
}
}
Did this answer your question?