Basic SDK Usage

A complete guide to the MediaViz API — from creating your account to viewing AI-powered photo curation results.

Initialize SDK Client

The MediaViz API uses OAuth2. You need a client ID issued by MediaViz — ask us if you don't have one.

First-party clients (your own backend) also get a client secret, and the SDK authenticates as itself with the client-credentials grant. Third-party clients get a client ID only and authenticate each user with PKCE.

React Native and Expo: never ship a client secret. Anything EXPO_PUBLIC_ is readable in the bundle, so a mobile app is always third-party — the SDK uses PKCE.

Both host URLs are required: MEDIAVIZ_BASE_URL for the API, MEDIAVIZ_PHOTO_UPLOAD_URL for photo uploads, which run on a separate host.

Create an Environment File

# .env
# Both hosts are required — photo uploads run on a separate host.
MEDIAVIZ_BASE_URL=https://api.mediaviz.ai
MEDIAVIZ_PHOTO_UPLOAD_URL=https://upload.mediaviz.ai

MEDIAVIZ_CLIENT_ID=YOUR_CLIENT_ID
# First-party clients only — include this line only if MediaViz issued
# you a client secret. Third-party clients omit it and use PKCE.
MEDIAVIZ_CLIENT_SECRET=YOUR_CLIENT_SECRET
# .env
# Both hosts are required — photo uploads run on a separate host.
MEDIAVIZ_BASE_URL=https://api.mediaviz.ai
MEDIAVIZ_PHOTO_UPLOAD_URL=https://upload.mediaviz.ai

MEDIAVIZ_CLIENT_ID=YOUR_CLIENT_ID
# First-party clients only — include this line only if MediaViz issued
# you a client secret. Third-party clients omit it and use PKCE.
MEDIAVIZ_CLIENT_SECRET=YOUR_CLIENT_SECRET
# .env
# Both hosts are required — photo uploads run on a separate host.
MEDIAVIZ_BASE_URL=https://api.mediaviz.ai
MEDIAVIZ_PHOTO_UPLOAD_URL=https://upload.mediaviz.ai

MEDIAVIZ_CLIENT_ID=YOUR_CLIENT_ID
# First-party clients only — include this line only if MediaViz issued
# you a client secret. Third-party clients omit it and use PKCE.
MEDIAVIZ_CLIENT_SECRET=YOUR_CLIENT_SECRET
# .env — Expo reads EXPO_PUBLIC_* into the app bundle
EXPO_PUBLIC_MEDIAVIZ_BASE_URL=https://api.mediaviz.ai
EXPO_PUBLIC_MEDIAVIZ_PHOTO_UPLOAD_URL=https://upload.mediaviz.ai

EXPO_PUBLIC_MEDIAVIZ_CLIENT_ID=YOUR_CLIENT_ID
EXPO_PUBLIC_MEDIAVIZ_REDIRECT_URI=yourapp://callback
# No client secret here — a mobile app is always a third-party client.
# Anything EXPO_PUBLIC_ is readable in the shipped app, so a mobile
# client authenticates with PKCE instead.
# .env
# Both hosts are required — photo uploads run on a separate host.
MEDIAVIZ_BASE_URL=https://api.mediaviz.ai
MEDIAVIZ_PHOTO_UPLOAD_URL=https://upload.mediaviz.ai

MEDIAVIZ_CLIENT_ID=YOUR_CLIENT_ID
# First-party clients only — include this line only if MediaViz issued
# you a client secret. Third-party clients omit it and use PKCE.
MEDIAVIZ_CLIENT_SECRET=YOUR_CLIENT_SECRET
# .env
# Both hosts are required — photo uploads run on a separate host.
MEDIAVIZ_BASE_URL=https://api.mediaviz.ai
MEDIAVIZ_PHOTO_UPLOAD_URL=https://upload.mediaviz.ai

MEDIAVIZ_CLIENT_ID=YOUR_CLIENT_ID
# First-party clients only — include this line only if MediaViz issued
# you a client secret. Third-party clients omit it and use PKCE.
MEDIAVIZ_CLIENT_SECRET=YOUR_CLIENT_SECRET

Now that your OAuth client is configured, you can initialize the SDK.

Initialize the SDK Client

import { MediaViz } from '@mediaviz/sdk';

const mediaviz = new MediaViz({
  baseUrl: 'https://api.mediaviz.ai',
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
  redirectUri: 'http://localhost:3000/callback',
});
import { MediaViz, MediaVizConfig } from '@mediaviz/sdk';

const config: MediaVizConfig = {
  baseUrl: 'https://api.mediaviz.ai',
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
  redirectUri: 'http://localhost:3000/callback',
};

const mediaviz = new MediaViz(config);
const { MediaViz } = require('@mediaviz/sdk');

const mediaviz = new MediaViz({
  baseUrl: 'https://api.mediaviz.ai',
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
  redirectUri: 'http://localhost:3000/callback',
});
import {
  MediaViz, configureCrypto, createCryptoProvider, createSecureTokenStore,
} from '@mediaviz/react-native-sdk';
import { MediaVizProvider } from '@mediaviz/react-native-sdk/react';
import * as Crypto from 'expo-crypto';
import * as SecureStore from 'expo-secure-store';
import { openAuthSessionAsync } from 'expo-web-browser';

// Hermes ships no SubtleCrypto, so PKCE needs a native provider.
configureCrypto(createCryptoProvider(Crypto));

export function App() {
  return (
    <MediaVizProvider
      MediaViz={MediaViz}
      config={{
        baseUrl: 'https://api.mediaviz.ai',
        clientId: 'YOUR_CLIENT_ID',
        redirectUri: 'yourapp://callback',
      }}
      store={createSecureTokenStore(SecureStore)}
      openAuthSession={openAuthSessionAsync}
    >
      <RootNavigator />
    </MediaVizProvider>
  );
}
from mediaviz_sdk import MediaVizClient

mediaviz = MediaVizClient(
    base_url='https://api.mediaviz.ai',
    client_id='YOUR_CLIENT_ID',
    client_secret='YOUR_CLIENT_SECRET',
    redirect_uri='http://localhost:3000/callback',
)
require_once __DIR__ . '/vendor/autoload.php';

use MediaVizSdk\MediaVizClient;

$mediaviz = new MediaVizClient([
  'baseUrl'      => 'https://api.mediaviz.ai',
  'clientId'     => 'YOUR_CLIENT_ID',
  'clientSecret' => 'YOUR_CLIENT_SECRET',
  'redirectUri'  => 'http://localhost:3000/callback',
]);

After initializing, get your first access token: first-party clients call authenticate(), and third-party clients call getAuthorizationUrl() and then handleCallback() after the user signs in. From then on, the SDK attaches the token to every request and refreshes it automatically. If you instead plan to use raw HTTP requests rather than the SDK, refer to the Direct HTTP authentication walkthrough in Full Overview for the full token flow.

Creating Your Account

Create the First Company User

To register a new company and its owner, call users.createUserAndCompany. This creates both the user and the associated company in a single call.

Required fields:

  • Name — the user's full name
  • Email — a valid email address (used for verification)
  • Password — account password
  • Company name — the name of your organization
  • Company creation token — issued by MediaViz for this email address. Contact us to request one; see User & Company Management for details.

Accounts created this way are automatically assigned the Company Owner role (account_type 3) — there is no account-type parameter to set.

A successful response triggers an email verification message to the provided address and returns the new user's id and company_id (both integers). Record both — you will need them for subsequent requests.

Request Sample

const { id, company_id } = await mediaviz.users.createUserAndCompany(
  'Jane Smith',
  'jane@example.com',
  's3cur3P@ss',
  null,  // companyId — omit to create a new company
  null,  // profilePicture — optional avatar URL
  null,  // paymentPlanType — optional billing plan
  'Acme Photography',
  null,  // credits — optional
  {
    inviteToken: 'YOUR_COMPANY_CREATION_TOKEN'
  }
);
import type { UserDisplay } from '@mediaviz/sdk';

const { id, company_id }: UserDisplay = await mediaviz.users.createUserAndCompany(
  'Jane Smith',
  'jane@example.com',
  's3cur3P@ss',
  null,  // companyId — omit to create a new company
  null,  // profilePicture — optional avatar URL
  null,  // paymentPlanType — optional billing plan
  'Acme Photography',
  null,  // credits — optional
  {
    inviteToken: 'YOUR_COMPANY_CREATION_TOKEN'
  }
);
const { id, company_id } = await mediaviz.users.createUserAndCompany(
  'Jane Smith',
  'jane@example.com',
  's3cur3P@ss',
  null,  // companyId — omit to create a new company
  null,  // profilePicture — optional avatar URL
  null,  // paymentPlanType — optional billing plan
  'Acme Photography',
  null,  // credits — optional
  {
    inviteToken: 'YOUR_COMPANY_CREATION_TOKEN'
  }
);
const { client } = useMediaViz();

const { id, company_id } = await client.users.createUserAndCompany(
  'Jane Smith',
  'jane@example.com',
  's3cur3P@ss',
  null,  // companyId — omit to create a new company
  null,  // profilePicture — optional avatar URL
  null,  // paymentPlanType — optional billing plan
  'Acme Photography',
  null,  // credits — optional
  {
    inviteToken: 'YOUR_COMPANY_CREATION_TOKEN'
  }
);
result = mediaviz.users.create_user_and_company(
    'Jane Smith',
    'jane@example.com',
    's3cur3P@ss',
    None,  # companyId — omit to create a new company
    None,  # profilePicture — optional avatar URL
    None,  # paymentPlanType — optional billing plan
    'Acme Photography',
    None,  # credits — optional
    invite_token='YOUR_COMPANY_CREATION_TOKEN'
)
# result['id'], result['company_id']
$result = $mediaviz->users->createUserAndCompany(
  'Jane Smith',
  'jane@example.com',
  's3cur3P@ss',
  null,  // companyId — omit to create a new company
  null,  // profilePicture — optional avatar URL
  null,  // paymentPlanType — optional billing plan
  'Acme Photography',
  null,  // credits — optional
  [
    'inviteToken' => 'YOUR_COMPANY_CREATION_TOKEN'
  ]
);
// $result['id'], $result['company_id']
curl -X POST 'https://api.mediaviz.ai/api/v1/users/new_company/?invite_token=YOUR_COMPANY_CREATION_TOKEN' \
  -H 'Content-Type: application/json' \
  --data @- <<'JSON'
{
  "name": "Jane Smith",
  "email": "jane@example.com",
  "company_id": null,
  "profile_picture": null,
  "payment_plan_type": null,
  "password": "s3cur3P@ss",
  "company_name": "Acme Photography",
  "credits": null
}
JSON

Response Sample

{
  "id": 8507,
  "company_id": 1024,
  "name": "Jane Smith",
  "email": "jane@example.com",
  "account_type": 3
}

To add additional users to an existing company, call POST /api/v1/users/ with a name, email, account_type (1 = standard user, 2 = company admin), and the existing company_id.

Create Collection

A collection is a container for a set of photos that will be processed together by MediaViz AI models. Each collection is identified by a unique project_table_name in the format z-photos-{company_id}-{uuid}.

Collections are scoped to an outcome — the type of analysis you want performed. To create a collection, call projects.createProjectAndRun specifying the outcomes (e.g., curation) and the models to run. The response returns the project_table_name you will use for all subsequent operations on this collection.

Request Sample

const { project_table_name } = await mediaviz.projects.createProjectAndRun(
  'My Wedding Collection',
  1,     // type — 1 = standard collection only
  null,  // private — optional; defaults to false
  'Wedding photos 2026',
  null,  // directory — optional folder path
  1,     // photoUploadVector — should match type
  null,  // thumbnail — optional cover image URL
  null,  // runName — optional label for this run
  {
    outcomes: 'curation'
  }
);
import type { ProjectRunDisplay } from '@mediaviz/sdk';

const { project_table_name }: ProjectRunDisplay = await mediaviz.projects.createProjectAndRun(
  'My Wedding Collection',
  1,     // type — 1 = standard collection only
  null,  // private — optional; defaults to false
  'Wedding photos 2026',
  null,  // directory — optional folder path
  1,     // photoUploadVector — should match type
  null,  // thumbnail — optional cover image URL
  null,  // runName — optional label for this run
  {
    outcomes: 'curation'
  }
);
const { project_table_name } = await mediaviz.projects.createProjectAndRun(
  'My Wedding Collection',
  1,     // type — 1 = standard collection only
  null,  // private — optional; defaults to false
  'Wedding photos 2026',
  null,  // directory — optional folder path
  1,     // photoUploadVector — should match type
  null,  // thumbnail — optional cover image URL
  null,  // runName — optional label for this run
  {
    outcomes: 'curation'
  }
);
const { client } = useMediaViz();

const { project_table_name } = await client.projects.createProjectAndRun(
  'My Wedding Collection',
  1,     // type — 1 = standard collection only
  null,  // private — optional; defaults to false
  'Wedding photos 2026',
  null,  // directory — optional folder path
  1,     // photoUploadVector — should match type
  null,  // thumbnail — optional cover image URL
  null,  // runName — optional label for this run
  {
    outcomes: 'curation'
  }
);
result = mediaviz.projects.create_project_and_run(
    'My Wedding Collection',
    1,     # type — 1 = standard collection only
    None,  # private — optional; defaults to false
    'Wedding photos 2026',
    None,  # directory — optional folder path
    1,     # photoUploadVector — should match type
    None,  # thumbnail — optional cover image URL
    None,  # runName — optional label for this run
    outcomes='curation'
)
# result['project_table_name']
$result = $mediaviz->projects->createProjectAndRun(
  'My Wedding Collection',
  1,     // type — 1 = standard collection only
  null,  // private — optional; defaults to false
  'Wedding photos 2026',
  null,  // directory — optional folder path
  1,     // photoUploadVector — should match type
  null,  // thumbnail — optional cover image URL
  null,  // runName — optional label for this run
  'curation'
);
// $result['project_table_name']
curl -X POST 'https://api.mediaviz.ai/api/v1/project_outcome/?outcomes=curation' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidXNyXzAxYWJjMTIzIiwiZXhwIjoxNzQzNjMwMzI5fQ.RwJF-KLLr8K5JgEtIeFiKWELcv-FDLNzMPHJ2St_wAo' \
  -H 'Content-Type: application/json' \
  --data @- <<'JSON'
{
  "name": "My Wedding Collection",
  "private": null,
  "type": 1,
  "description": "Wedding photos 2026",
  "directory": null,
  "photo_upload_vector": 1,
  "thumbnail": null,
  "run_name": null
}
JSON

Response Sample

{
  "id": "a1b2c3d4-0000-0000-0000-000000000000",
  "name": "My Wedding Collection",
  "project_table_name": "z-photos-1024-a1b2c3d4-0000-0000-0000-000000000000",
  "run_name": "My Wedding Collection_run_1",
  "similarity_level": "medium",
  "blur_model": true,
  "colors_model": true,
  "face_recognition_model": true,
  "image_classification_model": true,
  "image_comparison_model": true,
  "image_describe_model": false,
  "ocr_model": false,
  "similarity_model": true,
  "evidence_model": true,
  "personhood_model": false,
  ...
}

This sample creates a standard collection (type 1). For continuous upload collections (type 2) and the models they support, see Collection Creation & Model Selection.

Uploading Photos

Send each photo to the upload endpoint. You must resize each photo and Base64-encode it before calling the SDK — the SDK does not resize for you. We recommend resizing photos to fit within 512×512 px. Before uploading:

  • Preserve the aspect ratio. Don't crop or stretch photos to make them square. The Resize and Encode a Photo sample below handles this for you.
  • Send only the Base64 data. Don't include a data:image/jpeg;base64, prefix in fileContent of the Request Sample below.

The SDK fetches the collection's upload template automatically and caches it across calls.

Resize and Encode a Photo Sample

// Browser: resize a File or Blob with a canvas
const bitmap = await createImageBitmap(file, { imageOrientation: 'from-image' });
const scale = Math.min(1, 512 / Math.max(bitmap.width, bitmap.height));
const canvas = document.createElement('canvas');
canvas.width = Math.round(bitmap.width * scale);
canvas.height = Math.round(bitmap.height * scale);
canvas.getContext('2d').drawImage(bitmap, 0, 0, canvas.width, canvas.height);
const fileContent = canvas.toDataURL('image/jpeg', 0.85).split(',')[1];
// Browser: resize a File or Blob with a canvas
const bitmap = await createImageBitmap(file, { imageOrientation: 'from-image' });
const scale = Math.min(1, 512 / Math.max(bitmap.width, bitmap.height));
const canvas = document.createElement('canvas');
canvas.width = Math.round(bitmap.width * scale);
canvas.height = Math.round(bitmap.height * scale);
canvas.getContext('2d').drawImage(bitmap, 0, 0, canvas.width, canvas.height);
const fileContent = canvas.toDataURL('image/jpeg', 0.85).split(',')[1];
// Node.js: resize with sharp
const sharp = require('sharp');

const buffer = await sharp(inputPath)
  .rotate()
  .resize({ width: 512, height: 512, fit: 'inside', withoutEnlargement: true })
  .jpeg({ quality: 85 })
  .toBuffer();
const fileContent = buffer.toString('base64');
// React Native (Expo): resize with expo-image-manipulator
import * as ImageManipulator from 'expo-image-manipulator';

// uri, width, height come from the expo-image-picker asset
const resize = width >= height
  ? { width: Math.min(width, 512) }
  : { height: Math.min(height, 512) };
const result = await ImageManipulator.manipulateAsync(uri, [{ resize }], {
  compress: 0.85,
  format: ImageManipulator.SaveFormat.JPEG,
  base64: true,
});
const fileContent = result.base64;
# Python: resize with Pillow
from PIL import Image, ImageOps
import base64, io

img = ImageOps.exif_transpose(Image.open(input_path)).convert("RGB")
img.thumbnail((512, 512))  # preserves aspect ratio; never upscales
buf = io.BytesIO()
img.save(buf, format="JPEG", quality=85)
file_content = base64.b64encode(buf.getvalue()).decode()
// PHP: resize with GD
$img = imagecreatefromstring(file_get_contents($inputPath));

$exif = @exif_read_data($inputPath);
switch ($exif['Orientation'] ?? 1) {
  case 3: $img = imagerotate($img, 180, 0); break;
  case 6: $img = imagerotate($img, -90, 0); break;
  case 8: $img = imagerotate($img, 90, 0); break;
}

$w = imagesx($img);
$h = imagesy($img);
$scale = min(1, 512 / max($w, $h));
$resized = imagescale($img, (int) round($w * $scale), (int) round($h * $scale));

ob_start();
imagejpeg($resized, null, 85);
$fileContent = base64_encode(ob_get_clean());
# Shell: resize with ImageMagick, then Base64-encode for the request body
magick input.jpg -auto-orient -resize '512x512>' -quality 85 resized.jpg
base64 -i resized.jpg > resized.b64

Request Sample

const result = await mediaviz.photoUpload.uploadPhoto(
  1024,
  8507,
  'z-photos-1024-a1b2c3d4',
  {
    fileContent: '/9j/4AAQSkZJRgABAQAAAQABAAD...',
    mimetype: 'image/jpeg',
    filePath: '/photos/IMG_0001.jpg'
  }
);
const result = await mediaviz.photoUpload.uploadPhoto(
  1024,
  8507,
  'z-photos-1024-a1b2c3d4',
  {
    fileContent: '/9j/4AAQSkZJRgABAQAAAQABAAD...',
    mimetype: 'image/jpeg',
    filePath: '/photos/IMG_0001.jpg'
  }
);
const result = await mediaviz.photoUpload.uploadPhoto(
  1024,
  8507,
  'z-photos-1024-a1b2c3d4',
  {
    fileContent: '/9j/4AAQSkZJRgABAQAAAQABAAD...',
    mimetype: 'image/jpeg',
    filePath: '/photos/IMG_0001.jpg'
  }
);
const { client } = useMediaViz();

const result = await client.photoUpload.uploadPhoto(
  1024,
  8507,
  'z-photos-1024-a1b2c3d4',
  {
    fileContent: '/9j/4AAQSkZJRgABAQAAAQABAAD...',
    mimetype: 'image/jpeg',
    filePath: '/photos/IMG_0001.jpg'
  }
);
result = mediaviz.photo_upload.upload_photo(
    1024,
    8507,
    'z-photos-1024-a1b2c3d4',
    file_content='/9j/4AAQSkZJRgABAQAAAQABAAD...',
    mimetype='image/jpeg',
    file_path='/photos/IMG_0001.jpg'
)
$result = $mediaviz->photoUpload->uploadPhoto(
  '1024',
  '8507',
  'z-photos-1024-a1b2c3d4',
  [
    'file_content' => '/9j/4AAQSkZJRgABAQAAAQABAAD...',
    'mimetype' => 'image/jpeg',
    'file_path' => '/photos/IMG_0001.jpg'
  ]
);
# Step 1: get_project_prelim_model_request_template
curl -X GET 'https://api.mediaviz.ai/api/v1/project_outcome/z-photos-1024-a1b2c3d4' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidXNyXzAxYWJjMTIzIiwiZXhwIjoxNzQzNjMwMzI5fQ.RwJF-KLLr8K5JgEtIeFiKWELcv-FDLNzMPHJ2St_wAo'

# Step 2: Upload a preprocessed photo with metadata in the JSON body
curl -X POST 'https://upload.mediaviz.ai/photo_upload' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidXNyXzAxYWJjMTIzIiwiZXhwIjoxNzQzNjMwMzI5fQ.RwJF-KLLr8K5JgEtIeFiKWELcv-FDLNzMPHJ2St_wAo' \
  -H 'Content-Type: application/json' \
  --data @- <<'JSON'
{
  "file_content": "/9j/4AAQSkZJRgABAQAAAQABAAD...",
  "file_path": "/photos/IMG_0001.jpg",
  "mimetype": "image/jpeg",
  "company_id": 1024,
  "user_id": 8507,
  "project_table_name": "z-photos-1024-a1b2c3d4",
  "blur": "<BLUR>",
  "colors": "<COLORS>",
  "face_recognition": "<FACE_RECOGNITION>",
  "image_classification": "<IMAGE_CLASSIFICATION>",
  "image_comparison": "<IMAGE_COMPARISON>",
  "image_describe": "<IMAGE_DESCRIBE>",
  "ocr": "<OCR>"
}
JSON

Mark Photo Upload Complete

Once all photos have been uploaded, signal to MediaViz that the upload phase is finished. This triggers the AI processing pipeline to begin.

After this call, the collection transitions to a processing state and the models begin running.

Request Sample

const result = await mediaviz.projects.markProjectUploadComplete('z-photos-1024-a1b2c3d4');
const result = await mediaviz.projects.markProjectUploadComplete('z-photos-1024-a1b2c3d4');
const result = await mediaviz.projects.markProjectUploadComplete('z-photos-1024-a1b2c3d4');
const { client } = useMediaViz();

const result = await client.projects.markProjectUploadComplete('z-photos-1024-a1b2c3d4');
result = mediaviz.projects.mark_project_upload_complete('z-photos-1024-a1b2c3d4')
$result = $mediaviz->projects->markProjectUploadComplete('z-photos-1024-a1b2c3d4');
curl -X POST 'https://api.mediaviz.ai/api/v1/project/z-photos-1024-a1b2c3d4/upload_complete/' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidXNyXzAxYWJjMTIzIiwiZXhwIjoxNzQzNjMwMzI5fQ.RwJF-KLLr8K5JgEtIeFiKWELcv-FDLNzMPHJ2St_wAo'

Check Run Status

Poll for processing progress. progress_percentage is a fraction between 0 and 1 — not a 0-100 percent, so 0.72 means 72% done. Each model configured for the collection also has its own <model>_model_complete flag.

Request Sample

const result = await mediaviz.projects.checkProjectStatus('z-photos-1024-a1b2c3d4');
const result = await mediaviz.projects.checkProjectStatus('z-photos-1024-a1b2c3d4');
const result = await mediaviz.projects.checkProjectStatus('z-photos-1024-a1b2c3d4');
const { client } = useMediaViz();

const result = await client.projects.checkProjectStatus('z-photos-1024-a1b2c3d4');
result = mediaviz.projects.check_project_status('z-photos-1024-a1b2c3d4')
$result = $mediaviz->projects->checkProjectStatus('z-photos-1024-a1b2c3d4');
curl -X GET 'https://api.mediaviz.ai/api/v1/project/status/z-photos-1024-a1b2c3d4' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidXNyXzAxYWJjMTIzIiwiZXhwIjoxNzQzNjMwMzI5fQ.RwJF-KLLr8K5JgEtIeFiKWELcv-FDLNzMPHJ2St_wAo'

Response Sample

{
  "progress_percentage": 0.72,
  "blur_model_complete": true,
  "colors_model_complete": true,
  "face_recognition_model_complete": false,
  "image_classification_model_complete": false,
  "similarity_model_complete": false,
  "evidence_model_complete": false
}

Keep polling until progress_percentage reaches 1 and every model flag is true, then fetch results.

Individual Photo Results

Retrieve detailed analysis for a single photo using photos.getPhotoFromProject. The response includes the full set of model outputs for that photo, including:

  • blur_value — sharpness score
  • main_color_palette — dominant colors extracted from the image
  • labels_from_classifications_model — image classification tags, always an object keyed by label with a 0-1 confidence value ({ "Sky": 0.99, "Beach": 0.95 }), never a plain array; read the keys for a bare tag list. null until image classification has run.
  • bounding_boxes_from_faces_model — detected face regions
  • similar_photo_ids_high / _medium / _low — similar photos grouped by similarity strength
  • evidence_score — overall curation score
  • face_score — quality score for face content
  • content_score — subject matter quality score
  • aesthetic_score — compositional and aesthetic quality score
  • similarity_set_ranking — rank within its similarity cluster

Request Sample

const result = await mediaviz.photos.getPhotoFromProject('z-photos-1024-a1b2c3d4', 1035601);
import type { PhotoDisplay } from '@mediaviz/sdk';

const result: PhotoDisplay = await mediaviz.photos.getPhotoFromProject('z-photos-1024-a1b2c3d4', 1035601);
const result = await mediaviz.photos.getPhotoFromProject('z-photos-1024-a1b2c3d4', 1035601);
const { client } = useMediaViz();

const result = await client.photos.getPhotoFromProject('z-photos-1024-a1b2c3d4', 1035601);
result = mediaviz.photos.get_photo_from_project('z-photos-1024-a1b2c3d4', 1035601)
$result = $mediaviz->photos->getPhotoFromProject('z-photos-1024-a1b2c3d4', 1035601);
curl -X GET 'https://api.mediaviz.ai/api/v1/photos/z-photos-1024-a1b2c3d4/1035601' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidXNyXzAxYWJjMTIzIiwiZXhwIjoxNzQzNjMwMzI5fQ.RwJF-KLLr8K5JgEtIeFiKWELcv-FDLNzMPHJ2St_wAo'

Response Sample

{
  "id": 1035601,
  "blur_value": 0.95,
  "main_color_palette": ["#3a5a8c", "#f0e6d2", "#2c2c2c"],
  "labels_from_classifications_model": {
    "outdoor": 0.98,
    "portrait": 0.95,
    "natural light": 0.89
  },
  "bounding_boxes_from_faces_model": [
    { "x": 120, "y": 45, "width": 80, "height": 90 }
  ],
  "similar_photo_ids_high": [1035607],
  "similar_photo_ids_medium": [1035612, 1035619],
  "similar_photo_ids_low": [1035631],
  "evidence_score": 0.91,
  "face_score": 0.88,
  "content_score": 0.84,
  "aesthetic_score": 0.79,
  "similarity_set_ranking": 1
}