Skip to content

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/generate

Authentication

See Authentication - PWA Backend

Request Parameters

json
{
  "language": "en-US",
  "sku": "PB001",
  "psp": "PrinterName",
  "marketId": 0,
  "email": "user@example.com",
  "photos": [ // string or object
    "https://example.com/photo1.jpg", 
    {
      "id": "abc-1234",
      "url": "https://example.com/photo2.jpg",
    }
  ],
  "metadata": {
    "basePrice": 29.99,
    "basePages": 24,
    "extraCostPerPage": 0.50
  },
  "custom": {
    "key": "value"
  }
}
ParameterTypeRequiredDescription
emailstringNo*User's email address (plaintext, lowercase). OXOR with userId - provide either email or userId, not both. If both are not defined, an ID is generated. Note that this means a user that owns more than 1 project would have different owners, which can affect APIs like List Projects
userIdstringNo*End user's identifier. Must match pattern: [-_]?(?:[A-Za-z0-9]+[-_]?)+. OXOR with email - provide either email or userId, not both. If both are not defined, an ID is generated. Note that this means a user that owns more than 1 project would have different owners, which can affect APIs like List Projects
languagestringNoLanguage code. Accepts both full codes (e.g., en-US, fr-FR) or 2-character codes (e.g., en, fr). Defaults to en
skustring/numberYesProduct SKU from Products API (sku or renderOptions.productId)
pspstringYesPrinter name from Products API (specifications.psp.name or renderOptions.psp)
marketIdstring/numberYesTarget market ID. Can be integer (e.g., 0) or string identifier (e.g., "printer.region")
photosstring or object arrayNoArray of publicly accessible photo URLs
metadataobjectNoCustom pricing and product metadata. Coordinate with PBAI team for specific fields
layoutTypestringNoLayout algorithm. Valid values: fastbook, smartbook
eCommercePluginbooleanNoSet to true if integrating with eCommerce plugin
customobject/arrayNoCustom data structure. Coordinate with PBAI team for usage. Examples below.

* 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 email if you want the PWA to send transactional emails directly to the user
  • Use userId if you handle user identification and communications yourself

Response

json
{
  "url": "https://{frontend}.photobook.ai/editor?id=p-xyz789"
}
FieldTypeDescription
urlstringURL 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) Metadata for pricing or other fields

1.1. About Custom Data

The custom data object serves as dynamic overrides to populate, or replace existing pre-filled data, on generation/initialization. For example:

  1. custom.title would populate the template asset with ID title
  2. It is also possible to pass image URLs. Just ensure that they are PUBLICLY ACCESSIBLE!
json
{
  ...
  "custom": {
    "title": "My New Title",
    "logo": "https://path.to.my/public-image.jpg"
  }
}

Important notes about using the custom object

  1. It is imperative to align with the PBAI team on what properties are available for use. The example above assumes that the client and PBAI has aligned that title and logo are the properties available.
  2. For strings, make sure that its length can be rendered nicely in its given target area, otherwise it may crop.
  3. For images, other than needing to be publicly accessible, it is also important to align with the PBAI team on its expected dimensions, otherwise renders may be skewed.
  4. Make sure to test creating and launching some projects with your intended values to verify.

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,
    custom: {
      title: newTitle // An aligned property with PBAI
    }
  };
  
  // Optional: Add metadata for custom pricing
  if (product.customPricing) {
    requestData.metadata = {
      basePrice: product.basePrice,
      basePages: product.basePages,
      extraCostPerPage: product.extraCostPerPage
    };
  }

  // Optional: Select a starting template for the project
  requestData.metadata = {
    ...(requestData.metadata || {})
    template: myTargetTemplate
  }

  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:

  1. Open the URL in a webview
  2. Hide address bars for a seamless experience
  3. Implement navigation handling
  4. 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';
iframe.sandbox = 'allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-storage-access-by-user-activation allow-same-origin';

// Listen for messages
window.addEventListener('message', handleChannelMessage);

document.body.appendChild(iframe);

Suggested Practices

  1. Validate Photos: Ensure all photo URLs are accessible before calling the API (if providing photos)
  2. User Feedback: Show loading indicators while loading the project URL
  3. Cache Prevention: Add unique identifiers to photo URLs to prevent caching issues
  4. Product Coordination: Ensure SKU, PSP, and marketId are known to PBAI beforehand
  5. 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 email or userId, not both
  • Ensure the identifier is consistent across API calls for the same user

photobook.ai Developer Documentation