Whitelabel Integration

The Whitelabel API allows you to embed HeadshotPro functionality directly into your own application. Users interact with the HeadshotPro interface through a signed URL without needing to create HeadshotPro accounts.

Prerequisites

  • Whitelabel feature enabled on your organization
  • Webhook URL configured in your organization settings
  • Sufficient credits in your organization account

Contact sales@headshotpro.com to enable whitelabel for your organization.

Integration Flow

1. Your app calls POST /organization/models with user email
2. API returns a signed URL
3. You embed the signed URL in an iframe or redirect user
4. User completes onboarding and uploads photos
5. HeadshotPro sends webhook notifications as status changes
6. When complete, your app fetches photos via API

Creating a Whitelabel Session

curl -X POST "https://server.headshotpro.com/api/v2/organization/models" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "teamId": "team_xyz789",
    "isDevelopment": false
  }'

Response

{
  "success": true,
  "modelId": "507f1f77bcf86cd799439011",
  "status": "onboarding",
  "signedUrl": "https://yourproheadshots.com/auth/social?token=AUTH_TOKEN&anonymous=1"
}

Embedding the Interface

Option 1: Iframe

<iframe
  src="https://yourproheadshots.com/auth/social?token=AUTH_TOKEN&anonymous=1"
  width="100%"
  height="800"
  frameborder="0"
  allow="camera"
></iframe>

Option 2: Redirect

// Redirect user to HeadshotPro
window.location.href = signedUrl;

Option 3: New Window

// Open in new window/tab
window.open(signedUrl, '_blank');

Signed URL Behavior

  • URLs are temporary and tied to the user's session
  • Users can upload photos, view headshots, and select favorites
  • No HeadshotPro account creation required
  • Session persists until the user completes the flow

Development Mode

For testing your integration without consuming credits:

{
  "email": "test@example.com",
  "isDevelopment": true
}

Development mode:

  • Processes in ~3 minutes instead of ~1 hour
  • Uses test data instead of actual AI training
  • No credits consumed
  • Returns isDevelopment: true in responses

Retrieving Results

After receiving the model.photos_ready webhook:

# Get the user's favorite photo
curl -X GET "https://server.headshotpro.com/api/v2/organization/models/507f1f77bcf86cd799439011/photos/favorite" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Or get all photos
curl -X GET "https://server.headshotpro.com/api/v2/organization/models/507f1f77bcf86cd799439011/photos" \
  -H "Authorization: Bearer YOUR_API_KEY"

Email Handling

If a user with the provided email already exists, the API returns an error. To work around this for returning users:

// Append a unique identifier
const uniqueEmail = `${baseEmail.split('@')[0]}+${Date.now()}@${baseEmail.split('@')[1]}`;
// Results in: user+1704067200000@example.com

Complete Integration Example

async function startHeadshotSession(userEmail, teamId) {
  // 1. Create the model
  const response = await fetch('https://server.headshotpro.com/api/v2/organization/models', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.HEADSHOTPRO_API_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      email: userEmail,
      teamId: teamId,
      isDevelopment: process.env.NODE_ENV !== 'production'
    })
  });

  const { modelId, signedUrl } = await response.json();

  // 2. Store modelId in your database linked to the user
  await db.users.update(userId, { headshotModelId: modelId });

  // 3. Return the signed URL for embedding/redirect
  return signedUrl;
}

// Webhook handler
app.post('/webhooks/headshotpro', async (req, res) => {
  const { event, object } = req.body;

  if (event === 'model.photos_ready') {
    // Fetch the favorite photo
    const photo = await fetchFavoritePhoto(object._id);

    // Update your user's profile
    await db.users.update(
      { headshotModelId: object._id },
      { profilePhoto: photo.urls.main }
    );
  }

  res.status(200).send('OK');
});

Legacy Endpoints

The following endpoints are maintained for backwards compatibility:

Legacy EndpointCurrent Equivalent
POST /organization/whitelabel/model/createPOST /organization/models
GET /organization/whitelabel/model/get/:modelIdGET /organization/models/:modelId
DELETE /organization/whitelabel/model/delete/:modelIdDELETE /organization/models/:modelId

We recommend migrating to the current endpoints for new integrations.