AI Media API for Mobile Apps — Image Generation in React Native & Swift
You're building a photo-editing or creative app on iOS and Android. You want to let users generate or transform images with AI — avatar creation, product mockups, style transfer, or background replacement. The question isn't whether to use an AI image API; it's how to call one cleanly from a mobile client without leaking credentials or blocking the UI thread.
This guide walks through integrating GenRelay's image generation API into a React Native app, with equivalent patterns for Swift (iOS). It covers authentication best practices for mobile, model selection, handling base64 responses, and what the API costs per generated image.
Why Does Mobile API Integration Require Different Patterns?
Mobile apps have two constraints that server-side integrations don't: you cannot ship secrets in the app binary (reverse-engineering exposes them), and API calls must be non-blocking to keep the UI responsive.
The right architecture for a mobile image generation feature is:
- Your backend holds the GenRelay API key and makes the actual API call.
- Your mobile app calls your backend, displays a loading state, then renders the image.
For prototyping or internal tools where security is less critical, you can call the GenRelay API directly from the client — just be aware the key is extractable from the bundle.
How Do I Authenticate with the GenRelay API in a Mobile Context?
GenRelay uses standard Bearer token authentication. Every request needs an Authorization header with your API key:
Authorization: Bearer gr-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Secure pattern (production): Store the key server-side. Your mobile app authenticates to your own backend (Firebase Auth, Supabase, JWT — whatever you use), and your backend calls GenRelay. The GenRelay key never leaves your server.
Prototype pattern: If you're testing locally, pass the key as an environment variable and inject it at build time. Use Expo's extra config or React Native's react-native-config to avoid hardcoding it in source.
For a deep dive on token storage and rotation, see the Image Generation API Authentication Guide.
Which Image Model Should I Use in a Mobile App?
As of August 2026, GenRelay offers three image models relevant for mobile use cases:
| Model | Best for | Price | Output |
|---|---|---|---|
| Nano Banana Pro | High-fidelity generation, product imagery | $0.030/image (1K–2K px), $0.042/image (4K) | Up to 4K |
| Nano Banana 2 | Faster iteration, lower cost | $0.020/image (1K), $0.036/image (4K) | Up to 4K |
| GPT-image-2 | Text-in-image, instruction-following edits | $0.014/image | Up to 1K |
For a consumer mobile app where users generate avatars or creative images, Nano Banana 2 hits a good balance of quality and cost. For product mockup generation where accuracy matters more, use Nano Banana Pro. For apps that let users edit or composite images with text instructions, GPT-image-2 is the most capable at its price point.
See the full comparison at /nano and /gpt-image-2.
How Do I Call the Image Generation API from React Native?
The GenRelay API is a standard HTTPS REST API — you can call it with fetch or axios. Here's a minimal working example in React Native:
// imageService.js — call from your backend or a secure proxy
const GENRELAY_API_KEY = process.env.GENRELAY_API_KEY; // never hardcode
export async function generateImage(prompt, model = 'nano-banana-2') {
const response = await fetch('https://genrelay.ai/v1/images/generations', {
method: 'POST',
headers: {
'Authorization': `Bearer ${GENRELAY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model,
prompt,
n: 1,
size: '1024x1024',
response_format: 'url', // 'b64_json' also available
}),
});
if (!response.ok) {
const err = await response.json();
throw new Error(err.error?.message || `API error ${response.status}`);
}
const data = await response.json();
return data.data[0].url; // or data.data[0].b64_json if using base64
}
In your React Native component, call this inside a useEffect or on button press, wrapped with a loading state:
// AvatarGenerator.jsx
import React, { useState } from 'react';
import { View, TextInput, TouchableOpacity, Image, ActivityIndicator, Text, StyleSheet } from 'react-native';
import { generateImage } from './imageService';
export default function AvatarGenerator() {
const [prompt, setPrompt] = useState('');
const [imageUrl, setImageUrl] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const handleGenerate = async () => {
if (!prompt.trim()) return;
setLoading(true);
setError(null);
try {
const url = await generateImage(prompt, 'nano-banana-pro');
setImageUrl(url);
} catch (e) {
setError(e.message);
} finally {
setLoading(false);
}
};
return (
<View style={styles.container}>
<TextInput
style={styles.input}
value={prompt}
placeholder="Describe your image..."
/>
<TouchableOpacity style={styles.button} disabled={loading}>
<Text style={styles.buttonText}>{loading ? 'Generating…' : 'Generate'}</Text>
</TouchableOpacity>
{loading && <ActivityIndicator size="large" style={styles.spinner} />}
{error && <Text style={styles.error}>{error}</Text>}
{imageUrl && (
<Image
source={{ uri: imageUrl }}
style={styles.preview}
resizeMode="contain"
/>
)}
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, padding: 16 },
input: { borderWidth: 1, borderColor: '#ccc', borderRadius: 8, padding: 12, marginBottom: 12 },
button: { backgroundColor: '#0070f3', borderRadius: 8, padding: 14, alignItems: 'center' },
buttonText: { color: '#fff', fontWeight: '600' },
spinner: { marginTop: 24 },
error: { color: 'red', marginTop: 12 },
preview: { width: '100%', height: 320, marginTop: 20, borderRadius: 12 },
});
How Do I Handle Base64 Images in Swift (iOS)?
When calling from a native iOS app, you can use URLSession. Set response_format to b64_json to get the image as a base64 string — no need to manage temporary URL expiry.
// GenRelayImageService.swift
import Foundation
import UIKit
struct ImageGenerationRequest: Codable {
let model: String
let prompt: String
let n: Int
let size: String
let response_format: String
}
struct ImageGenerationResponse: Codable {
struct ImageData: Codable {
let b64_json: String?
let url: String?
}
let data: [ImageData]
}
func generateImage(prompt: String, completion: @escaping (UIImage?, Error?) -> Void) {
let url = URL(string: "https://genrelay.ai/v1/images/generations")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let body = ImageGenerationRequest(
model: "nano-banana-2",
prompt: prompt,
n: 1,
size: "1024x1024",
response_format: "b64_json"
)
request.httpBody = try? JSONEncoder().encode(body)
URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else {
completion(nil, error)
return
}
guard let result = try? JSONDecoder().decode(ImageGenerationResponse.self, from: data),
let b64 = result.data.first?.b64_json,
let imageData = Data(base64Encoded: b64),
let image = UIImage(data: imageData) else {
completion(nil, NSError(domain: "GenRelay", code: -1))
return
}
completion(image, nil)
}.resume()
}
The apiKey variable should come from your Keychain or a backend-issued short-lived token — never from a hardcoded string in your source.
How Much Does It Cost to Run Image Generation in a Mobile App?
Image generation API costs are per-image, not per-user-session. Your COGS depends on how many images users generate and which model you use.
Cost examples (Nano Banana 2, 1024×1024):
| Daily active users | Avg. images/user/day | Daily API cost | Monthly |
|---|---|---|---|
| 100 | 2 | $4.00 | ~$120 |
| 1,000 | 2 | $40.00 | ~$1,200 |
| 10,000 | 1 | $200.00 | ~$6,000 |
At $0.020/image (Nano Banana 2, 1K output), you can set a free tier at 5 images/day per user and charge $4.99/month for 50/day — the math works at any meaningful scale.
For batch or background generation workflows in your mobile backend, see Batch Image Generation via API.
Frequently Asked Questions
Can I call the GenRelay image API directly from a React Native app?
Yes — technically there's no SDK requirement; it's a standard REST endpoint. For production apps, route calls through your backend so the API key isn't shipped in the app bundle.
Does the image API support streaming in mobile?
Image generation APIs return a complete response when the image is ready — there's no streaming stream like text models. Plan for 3–15 seconds of latency depending on model and output size; always show a loading indicator.
What image sizes can I request?
Supported sizes include 256x256, 512x512, 1024x1024, and 1024x1792 / 1792x1024 for landscape/portrait. Nano Banana Pro supports up to 4K output; specify size: "4096x4096" or similar.
How do I cache generated images on-device?
For React Native, use react-native-fast-image which supports disk caching by URI. For Swift, URLCache or a library like Kingfisher handles caching. Since GenRelay returns short-lived URLs, download and cache the raw image data rather than caching the URL itself.
Does GenRelay have a mobile SDK?
No native SDK is required — the API is fully REST-compatible. Use any HTTP client (fetch, axios, URLSession, OkHttp). GenRelay provides an OpenAI-compatible endpoint so any existing OpenAI image SDK also works by pointing to https://genrelay.ai/v1.