Appearance
Generating Projects
API Type
PWA Backend API - Uses access keys in X-Albumstory header. See Authentication.
Generate photobook projects and launch the PWA editor webview.
Environment URLs:
- Development:
https://pwa-api-dev.photobook.ai/v2/* - Production:
https://pwa-api.photobook.ai/v2/*
Generate Project
Creates a new photobook project and returns a URL to launch the PWA editor in a webview.
Endpoint
POST https://pwa-api{-env}.photobook.ai/v2/generateAuthentication
See Authentication - PWA Backend
Request Parameters
json
{
"language": "en-US",
"sku": "PB001",
"psp": "PrinterName",
"marketId": 0,
"email": "user@example.com",
"photos": [
"https://example.com/photo1.jpg",
"https://example.com/photo2.jpg"
],
"metadata": {
"basePrice": 29.99,
"basePages": 24,
"extraCostPerPage": 0.50
},
"callback": "https://your-app.com/api/order-callback"
}| Parameter | Type | Required | Description |
|---|---|---|---|
email | string | Yes* | User's email address (plaintext, lowercase). XOR with userId - provide either email or userId, not both |
userId | string | Yes* | End user's identifier. Must match pattern: [-_]?(?:[A-Za-z0-9]+[-_]?)+. XOR with email - provide either email or userId, not both |
language | string | No | Language code. Accepts both full codes (e.g., en-US, fr-FR) or 2-character codes (e.g., en, fr). Defaults to en |
sku | string/number | Yes | Product SKU from Products API (sku or renderOptions.productId) |
psp | string | Yes | Printer name from Products API (specifications.psp.name or renderOptions.psp) |
marketId | string/number | Yes | Target market ID. Can be integer (e.g., 0) or string identifier (e.g., "printer.region") |
photos | array | No | Array of publicly accessible, high-resolution photo URLs |
metadata | object | No | Custom pricing and product metadata. Coordinate with PBAI team for specific fields |
layoutType | string | No | Layout algorithm. Valid values: fastbook, smartbook |
eCommercePlugin | boolean | No | Set to true if integrating with eCommerce plugin |
callback | string | No | Your endpoint URL for order completion callbacks (POST method) |
custom | object/array | No | Custom data structure. Coordinate with PBAI team for usage |
* Required Constraint: Must provide either email OR userId (not both, not neither).
⚠️ Photo Requirements
- URLs must be publicly accessible for downloading
- Photos should be high-resolution (suitable for printing)
- Ensure proper CORS headers if hosting on your own domain
User Identification
Provide either email or userId to identify the user:
- Use
emailif you want the PWA to send transactional emails directly to the user - Use
userIdif you handle user identification and communications yourself
Response
json
{
"url": "https://{frontend}.photobook.ai/editor?id=p-xyz789"
}| Field | Type | Description |
|---|---|---|
url | string | URL to launch in webview |
Implementation Guide
1. Gather Required Data
Before calling this API, you need:
- Product details: SKU, PSP name, and market ID
- User identification: email address OR user ID
- (Optional) User's selected photos (high-res URLs)
- (Optional) Custom metadata for pricing or other fields
2. Prepare the Request
javascript
async function generateProject(product, photos, userEmail, marketId) {
const requestData = {
language: 'en', // Can also use full codes like 'en-US'
sku: product.sku,
psp: product.specifications.psp.name,
marketId: marketId,
email: userEmail, // Provide email OR userId, not both
photos: photos,
callback: 'https://your-app.com/api/order-callback'
};
// Optional: Add metadata for custom pricing
if (product.customPricing) {
requestData.metadata = {
basePrice: product.basePrice,
basePages: product.basePages,
extraCostPerPage: product.extraCostPerPage
};
}
const response = await fetch('https://pwa-api-dev.photobook.ai/v2/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Albumstory': JSON.stringify({
accessKey: process.env.PWA_ACCESS_KEY,
accessSecret: process.env.PWA_ACCESS_SECRET
})
},
body: JSON.stringify(requestData)
});
const data = await response.json();
return data.url;
}3. Launch the Webview/iFrame
After receiving the URL:
- Open the URL in a webview
- Hide address bars for a seamless experience
- Implement navigation handling
- Listen for channel messages to track user progress
Webview Configuration
For Mobile Apps:
javascript
// React Native WebView example
<WebView
source={{ uri: editorUrl }}
onMessage={handleChannelMessage}
javaScriptEnabled={true}
domStorageEnabled={true}
/>For Web Applications:
javascript
// iframe example
const iframe = document.createElement('iframe');
iframe.src = editorUrl;
iframe.style.width = '100%';
iframe.style.height = '100vh';
iframe.style.border = 'none';
iframe.allow = 'fullscreen; clipboard-read; clipboard-write; web-share';
// Listen for messages
window.addEventListener('message', handleChannelMessage);
document.body.appendChild(iframe);Callback Endpoint
If you provide a callback URL, the PWA will POST to it when an order is completed.
Callback Request
The PWA will send a POST request with order details:
json
{
"orderId": "12345",
"email": "user@example.com",
"status": "completed",
"projectId": "abc123"
}Your Callback Handler
javascript
app.post('/api/order-callback', (req, res) => {
const { orderId, email, status, projectId } = req.body;
// Handle order completion
// - Update your database
// - Send notifications
// - Redirect user to confirmation page
res.status(200).json({ success: true });
});Suggested Practices
- Validate Photos: Ensure all photo URLs are accessible before calling the API (if providing photos)
- User Feedback: Show loading indicators while loading the project URL
- Cache Prevention: Add unique identifiers to photo URLs to prevent caching issues
- Product Coordination: Ensure SKU, PSP, and marketId are known to PBAI beforehand
- Metadata Usage: Coordinate with PBAI team before using custom metadata or custom fields
Common Issues
Photos Not Loading
- Ensure URLs are publicly accessible
- Check CORS headers on your CDN
- Verify URLs return actual image data
Invalid Product Configuration
- Double-check SKU matches exactly
- Verify PSP name is correct
- Ensure marketId is consistent across API calls
User Identification Errors
- Provide either
emailoruserId, not both - Ensure the identifier is consistent across API calls for the same user