Connect Bolt.new to the Getty Images API by applying for developer access at developer.gettyimages.com, using your API key to search and display watermarked preview images via a Next.js API route, and implementing the licensing flow for purchasing rights to high-resolution images. Getty Images is the premium source for editorial and news photography. All API calls must go through a server-side route — the API key is a credential that should never be exposed in the browser.
Build a Getty Images Search and Licensing App with Bolt.new
Getty Images is the world's largest premium stock photography agency, with an archive of over 500 million assets including editorial news photography, creative stock images, sports and entertainment photography, and archival historical images. The Getty Images API gives developers programmatic access to search this collection, display watermarked previews, and license images for specific uses. For media companies, news apps, editorial tools, and content platforms built in Bolt.new, the Getty API provides access to the most comprehensive library of editorial photography available.
Getting started with the Getty Images API requires creating a developer account at developer.gettyimages.com and submitting an API application. Unlike many APIs that offer instant access, Getty reviews applications to understand your use case — this typically takes 1-3 business days. Once approved, you receive an API key that authenticates your search and preview requests. The API key approach is straightforward: include it in the Api-Key header on all requests. For licensed downloads (purchasing rights to use images without watermarks), Getty uses OAuth 2.0 — a separate credential layer that requires user authentication. The search and preview tier works with just the API key and is what most developers need for building image galleries, search tools, and content discovery features.
Getty's image collection has an important distinction: editorial content versus creative content. Editorial images document real events — news photography, celebrity events, sports, politics. They can only be used in editorial contexts (news reporting, educational content) and not for commercial advertising. Creative images are cleared for commercial use in advertising, products, and marketing. When building search features, you should filter by this asset_type to show users only the content they are licensed to use for their purpose. Displaying editorial images in a commercial context without the correct license is a legal issue that Getty actively enforces.
Integration method
Getty Images API uses API key authentication for search and preview endpoints — include your API key in the Api-Key header on all requests. Because the API key is a privileged credential (it may be tied to a billing account for licensed downloads), all Getty API calls happen in a Next.js API route in your Bolt.new app. The frontend calls your API route, which proxies to Getty Images and returns search results with watermarked preview URLs. For licensing (purchasing rights), an additional OAuth 2.0 flow is required. Search and preview work in Bolt's WebContainer during development.
Prerequisites
- A Getty Images developer account at developer.gettyimages.com with an approved API key
- A Bolt.new project using Next.js (required for server-side API routes that keep the API key out of the browser)
- Understanding of Getty Images' editorial vs creative content distinction for proper licensing
- Optional: a Getty Images account with licensing credits for the download/licensing use case
- Basic understanding of image pagination and lazy loading for large result sets
Step-by-step guide
Apply for Getty Images API Access
Apply for Getty Images API Access
Navigate to developer.gettyimages.com and click 'Get API Access'. You will need to create a Getty developer account (separate from a regular Getty Images account) and fill out an application form describing your project. Getty wants to understand your use case: what type of application you are building, how you will display images, whether you intend to offer licensing to end users, and your estimated monthly API call volume. Provide specific, honest answers — vague responses slow down approval. Common approved use cases include media company tools, news aggregators, editorial content platforms, creative agency asset browsers, and developer demos/portfolios. After submitting, approval typically takes 1-3 business days. Getty sends your API key by email once approved. The API key looks like a long alphanumeric string and is associated with your developer account. There are two tiers: the Developers tier (free, rate-limited, returns watermarked previews only, no licensing capabilities) and the Partners tier (requires a Getty commercial agreement, enables licensed downloads and higher rate limits). For building and testing, the Developers tier is sufficient. Add the API key to your .env file as GETTY_API_KEY. Getty's API base URL is https://api.gettyimages.com/v3 and all endpoints require the Api-Key header (note: 'Api-Key' with a capital K, not 'Authorization: Bearer'). Test your key by calling the /search/images endpoint — a 200 response confirms the key is working.
Set up Getty Images API access in my Next.js Bolt.new app. Create a .env file with GETTY_API_KEY placeholder. Create lib/getty.ts with a gettyRequest(endpoint, queryParams) async helper function that calls https://api.gettyimages.com/v3{endpoint} with the headers: Api-Key set to GETTY_API_KEY and Accept-Language set to 'en-US'. Stringify the queryParams as URL search parameters. If the response is not OK, throw an error with the status and response body. Export the helper. Verify connectivity by creating a simple test: call /search/images?phrase=nature&page_size=1 and return the first result.
Paste this in Bolt.new chat
1// lib/getty.ts2export async function gettyRequest<T>(3 endpoint: string,4 queryParams: Record<string, string | number | boolean> = {}5): Promise<T> {6 const apiKey = process.env.GETTY_API_KEY;78 const params = new URLSearchParams();9 Object.entries(queryParams).forEach(([key, value]) => {10 if (value !== undefined && value !== null && value !== '') {11 params.append(key, String(value));12 }13 });1415 const url = `https://api.gettyimages.com/v3${endpoint}${params.toString() ? '?' + params.toString() : ''}`;1617 const response = await fetch(url, {18 headers: {19 'Api-Key': apiKey!,20 'Accept-Language': 'en-US',21 'Content-Type': 'application/json',22 },23 });2425 if (!response.ok) {26 const errorText = await response.text();27 throw new Error(`Getty API error ${response.status}: ${errorText}`);28 }2930 return response.json() as Promise<T>;31}Pro tip: Getty's API uses 'Api-Key' as the header name — note the capital K. This is unusual compared to most APIs that use 'Authorization: Bearer' or 'X-API-Key'. Using the wrong header format results in a 401 Unauthorized response. Also, the header is literally 'Api-Key', not 'api-key' — though HTTP headers are case-insensitive in transit, matching the documented format is safer.
Expected result: The Getty API connection is verified. The gettyRequest helper is ready to use in API routes throughout the app. A test search returns Getty image data.
Build the Image Search API Route and Gallery Component
Build the Image Search API Route and Gallery Component
With your API key configured, build the core search functionality. The Getty Images search endpoint is GET /v3/search/images and accepts numerous filtering parameters. The key ones for most applications: phrase (search keywords), page and page_size (pagination, max 100 per page), asset_type (editorial vs creative — critical for correct licensing), orientations (horizontal, vertical, square), number_of_people (none, one, small_group, large_group), and sort_order (best_match, most_popular, newest, oldest). The response includes a result_count (total matching images) and an images array. Each image object contains the id, title, caption, date_created, artist (photographer), asset_type, display_sizes (array of preview URLs at different sizes), and keywords array. The display_sizes array contains objects with a name (comp, preview, thumb) and uri (the image URL). 'thumb' is the smallest (170px), 'preview' is medium (340px), and 'comp' is the largest watermarked preview suitable for layout comping. All of these URLs include Getty's watermark overlay. Use the 'thumb' URIs for grid thumbnails and 'comp' or 'preview' for enlarged image views. During development in Bolt's WebContainer, outbound API calls to Getty Images work correctly from Next.js API routes. You can build and test the full search and gallery interface in the Bolt preview.
Create a Next.js API route at app/api/images/search/route.ts that accepts GET with query params: q, page (default 1), pageSize (default 20), assetType (editorial/creative, default creative), orientation. Call the Getty Images search API using the gettyRequest helper. Return formatted results: { images: [{ id, title, caption, artist, assetType, thumbUrl, previewUrl, compUrl }], totalCount, page, pageSize }. Then build a SearchPage component at app/search/page.tsx with a search input, asset type toggle (editorial/creative), orientation filter, masonry image grid showing comp images with photographer credit overlay, and pagination controls.
Paste this in Bolt.new chat
1// app/api/images/search/route.ts2import { NextRequest, NextResponse } from 'next/server';3import { gettyRequest } from '@/lib/getty';45interface GettyImage {6 id: string;7 title: string;8 caption: string;9 artist: string;10 asset_type: string;11 date_created: string;12 display_sizes: Array<{ name: string; uri: string }>;13 keywords: Array<{ text: string }>;14}1516interface GettySearchResponse {17 result_count: number;18 images: GettyImage[];19}2021export async function GET(request: NextRequest) {22 const { searchParams } = new URL(request.url);23 const q = searchParams.get('q') || '';24 const page = parseInt(searchParams.get('page') || '1');25 const pageSize = Math.min(parseInt(searchParams.get('pageSize') || '20'), 100);26 const assetType = searchParams.get('assetType') || 'creative';27 const orientation = searchParams.get('orientation') || '';2829 if (!q) {30 return NextResponse.json({ images: [], totalCount: 0 });31 }3233 const data = await gettyRequest<GettySearchResponse>('/search/images', {34 phrase: q,35 page,36 page_size: pageSize,37 asset_type: assetType,38 ...(orientation && { orientations: orientation }),39 fields: 'id,title,caption,artist,asset_type,date_created,display_sizes,keywords',40 sort_order: 'best_match',41 });4243 const getDisplayUrl = (sizes: Array<{ name: string; uri: string }>, name: string) =>44 sizes.find((s) => s.name === name)?.uri || '';4546 const images = (data.images || []).map((img) => ({47 id: img.id,48 title: img.title,49 caption: img.caption,50 artist: img.artist,51 assetType: img.asset_type,52 dateCreated: img.date_created,53 thumbUrl: getDisplayUrl(img.display_sizes, 'thumb'),54 previewUrl: getDisplayUrl(img.display_sizes, 'preview'),55 compUrl: getDisplayUrl(img.display_sizes, 'comp'),56 keywords: img.keywords?.slice(0, 8).map((k) => k.text) || [],57 }));5859 return NextResponse.json({ images, totalCount: data.result_count, page, pageSize });60}Pro tip: Always request specific fields in your Getty API call using the 'fields' parameter. Without it, Getty returns the full image object with all available metadata — this significantly increases response size and slows down your API route. Request only the fields you actually display.
Expected result: The search API route returns formatted image results with watermarked preview URLs. The gallery component displays a grid of Getty Images thumbnails with photographer credits.
Display Image Details and Implement the Licensing Workflow
Display Image Details and Implement the Licensing Workflow
When a user clicks a gallery image, show a detail view with the full caption, photographer name, date taken, Getty image ID, and usage rights information. The detail page should clearly show whether the image is editorial (news use only) or creative (commercial use allowed). Include a direct link to the image's licensing page on Getty's website — this is the standard approach for developers on the free API tier. The Getty image detail URL follows the pattern: https://www.gettyimages.com/detail/photo/{image-id}. For developers with a Getty partner agreement and OAuth credentials, the licensing API lets you download licensed images programmatically. This requires OAuth 2.0 authentication where the user logs in with their Getty account, authorizes your app, and you exchange the authorization code for tokens to call the /downloads endpoint. The OAuth flow requires a deployed redirect URI — it cannot work with Bolt's WebContainer preview URL since incoming OAuth callbacks need a stable public HTTPS URL. Build the OAuth flow in Bolt but test it after deployment to Netlify. For the detail page accessible to all visitors, display watermarked comp-size images and link to Getty's own licensing UI. The important thing is to never serve un-watermarked Getty images without proper licensing — Getty actively monitors for unauthorized image use and enforces licensing violations.
Build an image detail page at app/images/[id]/page.tsx. Fetch image details from the Getty API (GET /images/{id}) to get full metadata: caption, artist, date_created, keywords, asset_type, and all display sizes. Display the comp-size watermarked image prominently. Show: image title, full caption, photographer name, date taken, asset type badge (editorial/creative with tooltip explaining the difference). Show a 'License this image on Getty Images' button that links to https://www.gettyimages.com/detail/photo/{id}. Include the Getty image ID visibly for reference. Add a similar images section by calling the search API with the first 3 keywords.
Paste this in Bolt.new chat
1// app/images/[id]/page.tsx2import { gettyRequest } from '@/lib/getty';3import { notFound } from 'next/navigation';45interface GettyImageDetail {6 id: string;7 title: string;8 caption: string;9 artist: string;10 date_created: string;11 asset_type: string;12 display_sizes: Array<{ name: string; uri: string; is_watermarked: boolean }>;13 keywords: Array<{ text: string; type: string }>;14}1516type Props = { params: { id: string } };1718export async function generateMetadata({ params }: Props) {19 const image = await gettyRequest<GettyImageDetail>(`/images/${params.id}`)20 .catch(() => null);21 if (!image) return { title: 'Image Not Found' };22 return {23 title: `${image.title} | Getty Images`,24 description: image.caption?.slice(0, 155),25 };26}2728export default async function ImageDetailPage({ params }: Props) {29 const image = await gettyRequest<GettyImageDetail>(`/images/${params.id}`, {30 fields: 'id,title,caption,artist,date_created,asset_type,display_sizes,keywords',31 }).catch(() => null);3233 if (!image) notFound();3435 const compImage = image.display_sizes?.find((s) => s.name === 'comp');36 const gettyLicenseUrl = `https://www.gettyimages.com/detail/photo/${image.id}`;3738 return (39 <div className="max-w-4xl mx-auto px-4 py-8">40 <div className="relative aspect-video bg-gray-100 rounded-lg overflow-hidden mb-6">41 {compImage && (42 <img43 src={compImage.uri}44 alt={image.caption || image.title}45 className="w-full h-full object-contain"46 />47 )}48 <span className="absolute top-2 right-2 text-xs bg-black/60 text-white px-2 py-1 rounded">49 {image.asset_type === 'editorial' ? 'Editorial Use Only' : 'Creative'}50 </span>51 </div>52 <h1 className="text-2xl font-bold mb-2">{image.title}</h1>53 <p className="text-gray-600 mb-4">{image.caption}</p>54 <div className="flex gap-4 text-sm text-gray-500 mb-6">55 <span>Photo by: {image.artist}</span>56 <span>Date: {new Date(image.date_created).toLocaleDateString()}</span>57 <span>ID: {image.id}</span>58 </div>59 <a60 href={gettyLicenseUrl}61 target="_blank"62 rel="noopener noreferrer"63 className="inline-flex items-center gap-2 bg-blue-600 text-white px-6 py-3 rounded-lg hover:bg-blue-700"64 >65 License on Getty Images66 </a>67 </div>68 );69}Pro tip: Always link to Getty's official licensing page for images rather than providing download functionality on the free API tier. Getty Images actively uses reverse image search and licensing enforcement to identify unauthorized image use. The watermarked preview images include invisible digital watermarks in addition to visible ones — always respect Getty's licensing terms.
Expected result: Clicking any gallery image shows the detail page with the watermarked comp-size image, full caption, photographer info, and a clear link to license the image on Getty's website.
Common use cases
Editorial News Photography Search Tool
Build an internal image search tool for a news or media organization that allows journalists and editors to search Getty's editorial archive, preview watermarked images, and initiate licensing for approved images. Filter by event type, date range, and orientation.
Build a Getty Images search interface for editorial photography. Create a Next.js API route at app/api/images/search/route.ts that accepts a GET with query params: q (search term), page, pageSize, asset_type (editorial or creative). Call the Getty Images API search endpoint with the Api-Key header. Return the images array with: id, title, caption, display_sizes (preview URL), and asset_type. Build a search page with a search input, image grid (watermarked previews), and pagination. Each image card shows the preview photo, caption, and photographer credit.
Copy this prompt to try it in Bolt.new
Stock Photo Browser for Creative Teams
Build a creative stock photo browser that filters Getty's creative library by orientation, color, and people count. Team members can search, save favorites to a collection, and share shortlists with each other before initiating licensing through Getty's platform.
Build a creative stock photo browser using the Getty Images API. Add filters for: orientation (horizontal/vertical/square), number_of_people (none/one/small_group), and minimum_quality_rank (1-3). Search creative images only (asset_type=creative). Display results in a masonry grid layout. Add a 'Save to Favorites' button that stores the image ID and preview URL in Supabase favorites table (linked to the current user). Build a /favorites page that shows all saved images with their Getty image IDs for licensing reference.
Copy this prompt to try it in Bolt.new
Automated Press Release Image Matching
Build a tool that analyzes press release text and automatically suggests relevant Getty Images to accompany the story. Take a press release as input, extract key people, events, and topics, search Getty Images for matching editorial content, and return a curated selection of appropriate images.
Build a press release image matcher. Input: a text area for pasting press release content. On submit, extract the top 3 search terms from the text (company names, people, topics — use simple keyword extraction). For each search term, call the Getty Images search API (via our API route) and return the top 3 results. Display a grid of 9 suggested images (3 per search term, labeled with the keyword that found them) with preview images, captions, and Getty image IDs. Add a 'Copy Image ID' button for each image to use when licensing.
Copy this prompt to try it in Bolt.new
Troubleshooting
Getty API returns 401 Unauthorized for all requests
Cause: The Api-Key header is missing, misspelled (wrong capitalization), or the API key itself has not been approved yet — Getty reviews API applications before granting access.
Solution: Verify the header is exactly 'Api-Key' (capital A and K) in your request. Check that GETTY_API_KEY in your .env file matches the key from developer.gettyimages.com exactly. If your application is still under review, you will not be able to make successful API calls until approval.
1// Correct Getty header format:2headers: { 'Api-Key': process.env.GETTY_API_KEY }34// WRONG formats that cause 401:5headers: { 'api-key': process.env.GETTY_API_KEY }6headers: { 'Authorization': `Bearer ${process.env.GETTY_API_KEY}` }Image URLs (thumbUrl, previewUrl, compUrl) return 403 Forbidden when accessed in an img tag
Cause: Getty Images display URLs include a short-lived token in the URL that expires after a period of time, or the URL is being hotlinked from a domain that is not registered with Getty.
Solution: Fetch fresh image URLs from the Getty API for each page load rather than caching URL strings long-term. Do not store Getty preview URLs in your database — store only the Getty image ID and re-fetch the display URLs when needed. Getty's URLs are signed and expire.
1// Store only the Getty image ID, not the URL:2await supabase.from('favorites').insert({ getty_image_id: image.id, user_id: userId });34// When displaying: fetch fresh URLs from Getty API using the stored ID5const freshImage = await gettyRequest(`/images/${savedImageId}`, { fields: 'display_sizes' });Search returns no results for certain queries even though images exist on Getty's website
Cause: The asset_type filter may be excluding results — editorial images will not appear in creative searches and vice versa. Or the free developer API tier may have restrictions on certain content types.
Solution: Try removing the asset_type filter to search both editorial and creative images simultaneously. If searching for specific events or news photography, use asset_type=editorial. If the Developers tier does not return expected results, some content may only be accessible to Partners with a Getty commercial agreement.
1// Search across both asset types by omitting the asset_type filter2const data = await gettyRequest('/search/images', {3 phrase: q,4 page,5 page_size: pageSize,6 // Remove asset_type to search all content7 fields: 'id,title,caption,artist,asset_type,display_sizes',8});Getty Images API calls work in Bolt's preview but fail with CORS errors if called from the browser
Cause: Getty's API does not allow direct browser-to-API calls (CORS is blocked) — all calls must go through a server-side API route. If you accidentally called Getty's API directly from a React component (using fetch in a useEffect), the browser's CORS policy will block the request.
Solution: Move all Getty API calls to a Next.js API route (app/api/...) and have your React components call your own API route instead. Never call https://api.gettyimages.com directly from client-side code.
1// WRONG — calling Getty directly from browser (CORS error):2const data = await fetch('https://api.gettyimages.com/v3/search/images?phrase=nature');34// CORRECT — call your own API route from the browser:5const data = await fetch('/api/images/search?q=nature');6// The /api/images/search route calls Getty server-side with the API keyBest practices
- Never call Getty Images API directly from browser-side code — CORS will block it and the API key would be exposed in network requests; always proxy through a Next.js API route
- Store only Getty image IDs in your database, not the display URLs — Getty's signed preview URLs expire and storing them long-term leads to broken images
- Always display the editorial vs creative asset_type badge on images — editorial images can only be used in news/editorial contexts, not for commercial advertising or marketing
- Link to Getty's own licensing page (gettyimages.com/detail/photo/{id}) rather than trying to implement licensing on the free API tier — Getty's terms require proper licensing flow
- Request specific fields in the Getty API 'fields' parameter to reduce response payload size — the full image object contains dozens of fields you may not need
- Handle Getty API rate limits gracefully with retry logic — the free developer tier has strict rate limits and may return 429 Too Many Requests under high traffic
- During development in Bolt's WebContainer, Getty API calls via your Next.js API route work correctly — Getty's API is accessible over standard HTTP and does not require special network configuration
Alternatives
Shutterstock offers a public API with broader creative/commercial stock photography — easier to access than Getty, with a larger collection of royalty-free images for product and marketing use cases.
Pixabay provides a completely free API for openly licensed images (CC0) — no licensing fees, no approval process, and no restrictions on commercial use, making it ideal for projects that do not require premium editorial photography.
Canva's API provides access to their stock image library alongside design tools — simpler than Getty for non-editorial image needs and already integrated with Canva's design workflow.
Adobe Stock (part of Creative Cloud) offers a large royalty-free creative stock library with API access — strong for design-focused workflows already in the Adobe ecosystem.
Frequently asked questions
How do I get access to the Getty Images API?
Go to developer.gettyimages.com and apply for API access. Fill out the application form describing your project and use case — Getty reviews applications before granting API keys, typically within 1-3 business days. Once approved, you receive an API key by email. The free Developers tier provides access to search and watermarked preview endpoints. Licensed downloads require a Getty Partners agreement.
Do Getty Images API calls work in Bolt's WebContainer during development?
Yes, when called from a Next.js API route (server-side). Getty's API is accessible over HTTPS from Bolt's WebContainer. However, Getty's API blocks direct browser-to-API calls due to CORS restrictions — you must proxy all calls through a Next.js API route. Never call Getty's API from client-side React code.
What is the difference between Getty's editorial and creative images?
Editorial images document real events — news photography, celebrity events, sports, politics — and can only be used in editorial contexts (news articles, educational content, editorial commentary). They cannot be used for advertising, product promotion, or commercial purposes. Creative images are cleared for commercial use including advertising and marketing. Always filter by asset_type and display this distinction to users to help them choose appropriately licensed images.
Can I display full-resolution Getty Images on my website?
No — without a license, you can only display Getty's watermarked preview images (comp, preview, and thumb sizes). The watermarks are both visible and invisible (digital steganography). Serving un-watermarked Getty images without proper licensing violates Getty's terms of service, and Getty actively enforces licensing through reverse image search and legal action. Always link users to Getty's licensing page for purchasing rights.
Can I store Getty preview image URLs in my database?
No — Getty's preview URLs are signed and time-limited. Storing them leads to broken image links after the URLs expire. Instead, store only the Getty image ID in your database and re-fetch the display URLs from the Getty API each time you need to display the image. Getty's API response time is fast enough that fetching URLs on demand is practical.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation