Guidance
This guide covers the standards the API is built on, how each endpoint behaves, request limits, and how to interpret the metadata in responses. For getting your credentials see Getting Started; for the full endpoint reference see the API Reference.
If you are building with an agentic coding tool, AI coding tools covers the machine-readable form of this documentation, a read-only setup that cannot spend money, and which endpoints have side effects.
External Standards
The API makes use of external standards for the responses and authentication.
- IPTC NinJS 2.0 - used to represent item metadata
- ODRL - used to represent machine readable rights within the item metadata
- OAuth 2.0 - used for authentication and authorisation
- JWT - used by OAuth 2.0 for the access token used to authenticate each request
Endpoints
Search
With the search endpoint you can search all content in the Alamy archive which is available to your subscription receiving metadata for your matching items as a response. The individual metadata items are represented as IPTC NinJS 2.0 JSON partial news item documents.
A partial response means that some metadata is not available in this response and can be acquired by calling the item endpoint for the complete metadata response.
Please note paging of search results is limited to 100,000 items. If the supplied combination of limit and offset request content beyond the first 100,000 items you will receive a bad request response with a JSON body which looks as follows: -
{
"message": "Offset and limit exceeded the maximum"
}
The API currently supports search in English only.
In terms of characters queries may include:
- English letters (A–Z, a–z)
- Digits (0–9)
- Common punctuation and symbols (- , ( ) ? * # & ' ")
- Common accented Latin characters used in European languages acute, grave, circumflex, tilde, umlaut, caron, ring, macron, etc. (e.g., é, ñ, ü, Š, Å, Ł, Ø, Ū, Ż)
- All other characters — including non-Latin scripts such as Cyrillic, Greek, Arabic, and Chinese — are removed before processing.
Pagination
The search endpoint supports pagination of search results. The limit parameter is used to control the number of items returned and the offset parameter is used to control the position in the result set to start from.
The limit parameter is optional, defaults to 100 items and is capped at 100. The offset parameter is optional and defaults to 0.
We recommend the following for determining the offset value: -
offset = (page - 1) * limit
Item
With the item endpoint you can retrieve more detailed metadata on a specific item in the Alamy archive. The individual metadata item is represented as IPTC NinJS 2.0 JSON complete news item documents.
The subjects array on the single-item response includes both keyword entries (rel: "keyword") and category entries (rel: "category"). Category entries surface the primary and (where present) secondary Alamy category for the item and can be used in conjunction with the includeCategory parameter on the search endpoint to find similar content.
Items
With the items endpoint — GET /item?ids=… — you can
retrieve detailed metadata for up to 500 items in the Alamy archive in a single call. The ids
parameter takes a comma-separated list of ids. Both seq and ref ids are accepted, and the two
may be mixed in a single request. More than 500 ids, or ids that are invalid, duplicated or
incorrectly separated, produce a bad request response.
Items are not returned in the order you requested them. Match each returned item to your
request using its altids rather than by position in the array.
The response contains an 'items' array containing metadata of matched items each represented as IPTC NinJS 2.0 JSON complete news item document. It also contains an unprocessed array and a count of the total number of requested items.
The unprocessed array is a list of items which could not be retrieved due to any transient problem such as timeout / temporary network issue but not because the items do not exist or were prohibited. The unprocessed array allows for re-trying these items independently from the successfully retrieved items & excluded / disallowed items.
Any requested items that have been deleted, unavailable or restricted will not be in the response. They will be included in the total count.
Unlike the single-item endpoint, the bulk items response does not include category entries in subjects — only keyword entries are returned. Call /item/{id} if you need the category for a given item.
Download
With the download endpoint you can request a signed URL for an item you wish to download, the URL returned will expire so should not be stored but should instead be followed to download the item itself. The expiry time is given in the response as 'expires_in_seconds'. If the media type of the request item is a video it should be downloaded within 30 minutes.
Calling this endpoint is logged as a download against your account, so it is not a metadata call and there is no preview or dry-run mode. To exercise the download path while you are building, ask your account manager for a pre-production account with an agreed download test quota rather than using your production credentials — see Testing without spending production budget.
For holding a URL for a future download you should hold the download URL not the returned signed URL e.g. https://api.alamy.com/v3/download/242882626 then upon purchase call this URL with your credentials to acquire access to the purchased item.
Feed
The feed endpoint provides a long-polling endpoint for retrieving notifications pertaining to the creation, modification and removal of content from the Alamy platform.
The response contains a feed (top) level object, the 'items' array contains each notification, the 'associations' array within the notification will contain the single item which the notification pertains to.
The notifications returned by the feed endpoint are ordered by firstcreated in ascending order. This represents the chronological order in which the changes took place to the millisecond up to five days in the past.
Expected Usage
The way we expect users to interact with the endpoint is to make an initial call without criteria, (optionally a non standard limit or an offset up to five days in the past) then in a loop follow the next page link.
If there are no new changes immediately available the API will hold the request for up to five seconds returning as soon as changes occur or returning an empty items array if no new changes occur.
Within the feed response the most critical attributes are: -
- nextPage - the URL to request on the next iteration of your loop
Within the notification the important attributes are: -
- uri - this is a unique ID for the notification. You should use this to de-duplicate any notifications to ensure you've not already processed this specific notification.
- firstcreated - this is the millisecond accurate date time that the notification was created. You should use this to determine the correct order of notifications. You should store this and any notification for the same item which arrives later which has an earlier firstcreated can be safely ignored, anything newer should be processed.
Within the item the important attributes are: -
- pubstatus - usable or withheld. If the pubstatus is usable the item can be created or updated in your platform. If it is withheld the item should be removed from sale on your platform.
- uri - the unique ID of this item, you should store. If your platform has not received this item before and the pubstatus is usable consider this a create operation. You should use this to determine whether the notification is a create or an update for your integration.. If your platform has seen this item before consider this an update operation where the provided metadata completely replaces the previous version.
Orders
The orders endpoint — GET /orders — returns the
authenticated user's order history, newest first, and requires the orders scope.
Each entry carries the date the order was placed, the uri of the item ordered, and a
downloadUrl for retrieving it. Paging is page-based rather than offset-based here: limit
defaults to 10 and page selects the page. This differs from search and feed, which both use
offset.
dateFrom accepts an ISO 8601 datetime, defaults to 24 hours ago, and must be within the last
365 days.
group=true widens the response to include orders from the rest of your organisation. This is a
subscription feature — without it the request returns 403:
{
"message": "Your subscription does not allow listing of group orders. Please contact your account manager for details."
}
When there are no orders in the window the response is {"items": []}, with no nextPage.
Long polling
Supplying dateFrom puts the endpoint into long-polling mode: if no matching orders exist yet the
request is held open for about five seconds, returning as soon as orders arrive or with an empty
items array if none do. This mirrors the feed and lets you reconcile orders as they
happen rather than polling on a timer.
Request Limits
A limit of 15 requests a second per source IP address across all endpoints is enforced by the API. Requests above this limit are blocked.
No rate-limit headers are returned — there is no Retry-After and no X-RateLimit-* — so track
your own request rate rather than waiting for the API to tell you. Because the limit is per source
IP, everything sharing an egress address shares the budget: containers behind one NAT gateway,
functions in a VPC, or a CI fleet. See Errors for the full picture.
Result sets are bounded independently of that rate: search paging stops at 100,000 items (see
Pagination), search limit is capped at 100, feed limit at 100, and the items
endpoint accepts at most 500 ids per call.
Metadata Guidance
Rights
Within complete NinJS responses only the API returns a combination of machine and human-readable rights, the following describes briefly what you should expect and how you can use this information.
Machine Readable
Within the 'rightsinfo' attribute of NinJS 2.0 responses you will find an encodedrights attribute, the value of which will be an ODRL statement encoded as a string.
For rights managed images with restrictions we use policies which list prohibited usages and permitted usages for the item, the possible prohibitions and permissions are as follows: -
- Consumer goods (alamy:consumerGoodsUse)
- Direct mail and brochures (alamy:directMailBrochuresUse)
- Indoor display (alamy:indoorDisplayUse)
- Editorial (alamy:editorialUse)
- Internal business usage (alamy:internalBusinessUse)
- Commercial electronic (alamy:commercialElectronicUse)
- Personal use (alamy:personalUse)
- Advertising and promotion (alamy:advertisingCommercialUse)
So for example an ODRL statement such as the following means that the item (https://api.alamy.com/v3/item/343253265) cannot be used for advertising and promotion use as listed in the prohibition list but all other uses as specified in permission list are allowed.
{
"@context": [
"http://www.w3.org/ns/odrl.jsonld",
"https://api.alamy.com/v3/odrl-profile/alamy-rights.jsonld"
],
"@type": "Set",
"uid": "http://api.alamy.com/v3/rights/policy/99z:99y:2b:2c:2d:2g:2e/2a",
"profile": "https://api.alamy.com/v3/odrl-profile/",
"target": "http://api.alamy.com/v3/item/343253265",
"conflict": "invalid",
"prohibition": [
{
"action": [
"alamy:advertisingCommercialUse"
]
}
],
"permission": [
{
"action": [
"alamy:personalUse",
"alamy:commercialElectronicUse",
"alamy:consumerGoodsUse",
"alamy:directMailBrochuresUse",
"alamy:indoorDisplayUse",
"alamy:internalBusinessUse",
"alamy:editorialUse"
]
}
]
}
For royalty free content which are restricted to editorial use only we use a policy which lists editorial use as a permission and all other uses are not allowed as specified in the prohibition list.
{
"@context": [
"http://www.w3.org/ns/odrl.jsonld",
"https://api.alamy.com/v3/odrl-profile/alamy-rights.jsonld"
],
"@type": "Set",
"uid": "http://api.alamy.com/v3/rights/policy/99z:2a:99y:2b:2c:2d:2g/2e",
"profile": "https://api.alamy.com/v3/odrl-profile/",
"target": "http://api.alamy.com/v3/item/343253265",
"conflict": "invalid",
"prohibition": [
{
"action": [
"alamy:personalUse",
"alamy:advertisingCommercialUse",
"alamy:commercialElectronicUse",
"alamy:consumerGoodsUse",
"alamy:directMailBrochuresUse",
"alamy:indoorDisplayUse",
"alamy:internalBusinessUse"
]
}
],
"permission": [
{
"action": [
"alamy:editorialUse"
]
}
]
}
This policy means that the item (https://api.alamy.com/v3/item/343253265) can only be used in an editorial context and in no other.
The rights statement can be parsed by your service to drive icons / disable licensing options to your users or simply drive human readable notifications to the users. This statement will only be present if at least one usage is prohibited.
Human Readable
The 'usageterms' attribute of NinJS 2.0 responses if present contains a human readable string of restrictions which must be presented to the user who is choosing to acquire the item. If no human readable rights are relevant this attribute will not be present.
// One property of the NinJS response, not a whole document.
"usageterms": "EDITORIAL USE ONLY No use with unauthorised audio, video, data, fixture lists, club/league logos or “live” services. Online in-match use limited to 120 images, no video emulation. No use in betting, games or single club/league/player publications"
Metadata Flags
Within the 'objects' array of NinJS 2.0 responses you will find metadata flags, these denote features of the item, so whether the item is rights managed or royalty free for example, or if the item is black and white.
The possible types of metadata flag are broken down by relationship and are as follows: -
usageDefinedBy
This relationship is about features of the item which may impact how it is used.
- modelReleased - Model released
- propertyReleased - Property released
- containsPeople - Contains people
- containsProperty - Contains property
- royaltyFree - Royalty free
- rightsManaged - Rights managed
affectedBy
This relationship is about features of the item that affect how it is perceived by the end user visually for example.
- blackAndWhite - Black and white
- cutOut - Cut out
- digitallyAltered - Digitally altered
partOf
This relationship is about whether the item belongs to a larger body of content for example the library for customers who have an account which includes an IQ / discount library or a curated creative collection.
The 'literal' property denotes which larger body of content the item belongs to. These are the possible values: -
- iqLibrary
- discountLibrary
- creativeCollectionUltimate
- creativeCollectionVital
- creativeCollectionFoundation
The objects will only be present if they are relevant to the item being retrieved.
An example of machine-readable metadata flags denoting that the image is black and white and royalty free would be as follows: -
// One property of the NinJS response, not a whole document.
"objects": [
{
"rel": "affectedBy",
"literal": "blackAndWhite",
"name": "Black and white"
},
{
"rel": "usageDefinedBy",
"literal": "royaltyFree",
"name": "Royalty Free"
}
]
Info Sources
For all items added to the platform over 48 hours ago information about the contributor of the item will be present in the infosources array of the NinJS response as shown in the following example as well as the name of the contributor being present in the 'By' attribute.
// One property of the NinJS response, not a whole document.
"infosources": [
{
"name": "PjrXX",
"role": "https://api.alamy.com/v3/roles/contributorPseudonym",
"literal": "080A1B4B-3A87-4303-858A-B3914E97697A"
}
]