Code Examples
Real-world integration examples for stock photos and AI generation in popular languages and frameworks
✨ New: All examples now include AI generation support. Add provider=ai&style=photo to any URL for AI-generated images.
JavaScript / TypeScript
Vanilla JavaScript
// Simple image fetch
async function getImage(query, width = 800, height = 600) {
const url = new URL('/api/image', window.location.origin);
url.searchParams.set('query', query);
url.searchParams.set('width', width);
url.searchParams.set('height', height);
const response = await fetch(url, {
headers: {
'X-API-Key': process.env.PLACEWISE_API_KEY // Server-side only!
}
});
if (response.status === 302) {
return response.url; // Followed redirect URL
}
throw new Error(`Failed to fetch image: ${response.status}`);
}
// Usage
const imageUrl = await getImage('mountains');
document.getElementById('myImage').src = imageUrl;React with AI Support
import { useState, useEffect } from 'react';
function PlacewiseImage({
query,
width = 800,
height = 600,
alt,
provider = 'unsplash', // 'unsplash', 'pexels', 'pixabay', or 'ai'
style = 'photo' // AI only: 'photo', 'minimal', 'dark', 'illustration'
}) {
const [imageUrl, setImageUrl] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchImage() {
try {
setLoading(true);
setError(null);
const params = new URLSearchParams({
query,
width: width.toString(),
height: height.toString(),
provider
});
// Add AI-specific parameters
if (provider === 'ai') {
params.set('style', style);
}
const response = await fetch(`/api/image?${params}`);
if (response.status === 302) {
setImageUrl(response.url);
} else {
const error = await response.json();
throw new Error(error.error);
}
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}
fetchImage();
}, [query, width, height, provider, style]);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<img
src={imageUrl}
alt={alt}
width={width}
height={height}
loading="lazy"
/>
);
}
// Usage - Stock Photos
function App() {
return (
<PlacewiseImage
query="sunset beach"
width={1200}
height={800}
alt="Beautiful sunset at the beach"
/>
);
}
// Usage - AI Generated
function AppWithAI() {
return (
<>
<PlacewiseImage
query="modern office workspace"
width={800}
height={600}
provider="ai"
style="photo"
alt="AI generated office"
/>
<PlacewiseImage
query="minimal coffee cup"
width={800}
height={600}
provider="ai"
style="minimal"
alt="Minimal coffee design"
/>
</>
);
}Next.js (Server Components)
// app/api/proxy-image/route.ts - Secure server-side proxy
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const query = searchParams.get('query');
if (!query) {
return NextResponse.json(
{ error: 'Query parameter required' },
{ status: 400 }
);
}
const params = new URLSearchParams({
query,
width: searchParams.get('width') || '800',
height: searchParams.get('height') || '600'
});
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/api/image?${params}`,
{
headers: {
'X-API-Key': process.env.PLACEWISE_API_KEY! // Server-side only
},
redirect: 'manual'
}
);
if (response.status === 302) {
const imageUrl = response.headers.get('Location');
return NextResponse.json({ imageUrl });
}
return NextResponse.json(
{ error: 'Failed to fetch image' },
{ status: response.status }
);
}
// components/PlacewiseImage.tsx - Client component
'use client';
import { useEffect, useState } from 'react';
export default function PlacewiseImage({
query,
width = 800,
height = 600
}: {
query: string;
width?: number;
height?: number;
}) {
const [imageUrl, setImageUrl] = useState<string | null>(null);
useEffect(() => {
fetch(`/api/proxy-image?query=${encodeURIComponent(query)}&width=${width}&height=${height}`)
.then(res => res.json())
.then(data => setImageUrl(data.imageUrl))
.catch(console.error);
}, [query, width, height]);
if (!imageUrl) return <div>Loading...</div>;
return <img src={imageUrl} alt={query} width={width} height={height} />;
}Python
Using requests
import requests
import os
from urllib.parse import urlencode
def get_image_url(query: str, width: int = 800, height: int = 600) -> str:
"""Fetch image URL from Placewise API."""
params = {
'query': query,
'width': width,
'height': height
}
headers = {
'X-API-Key': os.getenv('PLACEWISE_API_KEY')
}
response = requests.get(
'https://yourdomain.com/api/image',
params=params,
headers=headers,
allow_redirects=False
)
if response.status_code == 302:
return response.headers['Location']
elif response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
raise Exception(f'Rate limit exceeded. Retry after {retry_after} seconds')
else:
error = response.json()
raise Exception(f"API error: {error.get('error')}")
# Usage
try:
image_url = get_image_url('mountains', width=1920, height=1080)
print(f'Image URL: {image_url}')
except Exception as e:
print(f'Error: {e}')Flask API Endpoint
from flask import Flask, request, jsonify
import requests
import os
app = Flask(__name__)
@app.route('/api/images/search')
def search_images():
"""Proxy endpoint for Placewise API."""
query = request.args.get('query')
if not query:
return jsonify({'error': 'Query parameter required'}), 400
width = request.args.get('width', 800, type=int)
height = request.args.get('height', 600, type=int)
# Validate dimensions
if not (100 <= width <= 4000) or not (100 <= height <= 4000):
return jsonify({'error': 'Invalid dimensions'}), 400
try:
response = requests.get(
'https://yourdomain.com/api/image',
params={'query': query, 'width': width, 'height': height},
headers={'X-API-Key': os.getenv('PLACEWISE_API_KEY')},
allow_redirects=False,
timeout=10
)
if response.status_code == 302:
image_url = response.headers['Location']
return jsonify({
'imageUrl': image_url,
'query': query,
'dimensions': {'width': width, 'height': height}
})
elif response.status_code == 429:
return jsonify({
'error': 'Rate limit exceeded',
'retryAfter': int(response.headers.get('Retry-After', 60))
}), 429
else:
error_data = response.json()
return jsonify(error_data), response.status_code
except requests.Timeout:
return jsonify({'error': 'Request timeout'}), 504
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(debug=True)PHP
cURL Implementation
<?php
class PlacewiseClient {
private $apiKey;
private $baseUrl;
public function __construct($apiKey, $baseUrl = 'https://yourdomain.com') {
$this->apiKey = $apiKey;
$this->baseUrl = $baseUrl;
}
public function getImageUrl($query, $width = 800, $height = 600) {
$params = http_build_query([
'query' => $query,
'width' => $width,
'height' => $height
]);
$url = $this->baseUrl . '/api/image?' . $params;
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => false,
CURLOPT_HEADER => true,
CURLOPT_HTTPHEADER => [
'X-API-Key: ' . $this->apiKey
]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 302) {
// Extract Location header
preg_match('/Location: (.+)/', $response, $matches);
return trim($matches[1]);
}
if ($httpCode === 429) {
throw new Exception('Rate limit exceeded');
}
throw new Exception('Failed to fetch image: HTTP ' . $httpCode);
}
}
// Usage
try {
$client = new PlacewiseClient(getenv('PLACEWISE_API_KEY'));
$imageUrl = $client->getImageUrl('mountains', 1920, 1080);
echo "Image URL: " . $imageUrl . "\n";
} catch (Exception $e) {
echo "Error: " . $e->getMessage() . "\n";
}
?>Ruby
Using Net::HTTP
require 'net/http'
require 'uri'
require 'json'
class PlacewiseClient
def initialize(api_key, base_url = 'https://yourdomain.com')
@api_key = api_key
@base_url = base_url
end
def get_image_url(query, width: 800, height: 600)
params = URI.encode_www_form(
query: query,
width: width,
height: height
)
uri = URI("#{@base_url}/api/image?#{params}")
request = Net::HTTP::Get.new(uri)
request['X-API-Key'] = @api_key
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
case response.code.to_i
when 302
response['Location']
when 429
raise "Rate limit exceeded. Retry after #{response['Retry-After']} seconds"
else
error = JSON.parse(response.body)
raise "API error: #{error['error']}"
end
end
end
# Usage
begin
client = PlacewiseClient.new(ENV['PLACEWISE_API_KEY'])
image_url = client.get_image_url('mountains', width: 1920, height: 1080)
puts "Image URL: #{image_url}"
rescue => e
puts "Error: #{e.message}"
endGo
HTTP Client
package main
import (
"fmt"
"io"
"net/http"
"net/url"
"os"
"strconv"
)
type PlacewiseClient struct {
APIKey string
BaseURL string
}
func NewClient(apiKey string) *PlacewiseClient {
return &PlacewiseClient{
APIKey: apiKey,
BaseURL: "https://yourdomain.com",
}
}
func (c *PlacewiseClient) GetImageURL(query string, width, height int) (string, error) {
params := url.Values{}
params.Add("query", query)
params.Add("width", strconv.Itoa(width))
params.Add("height", strconv.Itoa(height))
reqURL := fmt.Sprintf("%s/api/image?%s", c.BaseURL, params.Encode())
req, err := http.NewRequest("GET", reqURL, nil)
if err != nil {
return "", err
}
req.Header.Set("X-API-Key", c.APIKey)
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode == 302 {
location := resp.Header.Get("Location")
return location, nil
}
if resp.StatusCode == 429 {
return "", fmt.Errorf("rate limit exceeded")
}
body, _ := io.ReadAll(resp.Body)
return "", fmt.Errorf("API error: %s", string(body))
}
func main() {
client := NewClient(os.Getenv("PLACEWISE_API_KEY"))
imageURL, err := client.GetImageURL("mountains", 1920, 1080)
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
fmt.Printf("Image URL: %s\n", imageURL)
}cURL
Command Line Examples
Get redirect location:
curl -I -H "X-API-Key: pk_live_YOUR_KEY" \ "https://yourdomain.com/api/image?query=mountains&width=800&height=600"
Download image directly:
curl -L -H "X-API-Key: pk_live_YOUR_KEY" \ -o image.jpg \ "https://yourdomain.com/api/image?query=mountains&width=1920&height=1080"
With query parameter authentication:
curl -L -o sunset.jpg \ "https://yourdomain.com/api/image?query=sunset&width=800&height=600&api_key=pk_live_YOUR_KEY"
Advanced Examples
TypeScript with Retry Logic
interface FetchOptions {
maxRetries?: number;
retryDelay?: number;
}
async function fetchImageWithRetry(
query: string,
width: number,
height: number,
options: FetchOptions = {}
): Promise<string> {
const { maxRetries = 3, retryDelay = 1000 } = options;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const params = new URLSearchParams({
query,
width: width.toString(),
height: height.toString()
});
const response = await fetch(`/api/image?${params}`, {
headers: {
'X-API-Key': process.env.PLACEWISE_API_KEY!
},
redirect: 'manual'
});
if (response.status === 302) {
return response.headers.get('Location')!;
}
if (response.status === 429) {
const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
continue;
}
if (response.status >= 500) {
const delay = retryDelay * Math.pow(2, attempt);
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
const error = await response.json();
throw new Error(error.error);
} catch (error) {
if (attempt === maxRetries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, retryDelay));
}
}
throw new Error('Max retries exceeded');
}Client-Side Caching
class PlacewiseCache {
private cache = new Map<string, { url: string; timestamp: number }>();
private ttl = 24 * 60 * 60 * 1000; // 24 hours
private getCacheKey(query: string, width: number, height: number): string {
return `${query}:${width}:${height}`;
}
async getImage(query: string, width: number, height: number): Promise<string> {
const key = this.getCacheKey(query, width, height);
const cached = this.cache.get(key);
// Check if cached and not expired
if (cached && Date.now() - cached.timestamp < this.ttl) {
console.log('Cache hit');
return cached.url;
}
// Fetch fresh image
console.log('Cache miss');
const params = new URLSearchParams({ query, width: width.toString(), height: height.toString() });
const response = await fetch(`/api/image?${params}`);
const imageUrl = response.url;
// Cache the result
this.cache.set(key, {
url: imageUrl,
timestamp: Date.now()
});
return imageUrl;
}
clear(): void {
this.cache.clear();
}
}
// Usage
const imageCache = new PlacewiseCache();
const imageUrl = await imageCache.getImage('mountains', 800, 600);On This Page