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 authenticates with OAuth2. Before initializing the SDK, you need an OAuth client ID (and, optionally, a client secret) issued by MediaViz.

Don't have a client ID or secret? Reach out to MediaViz and we'll generate credentials for you.

Store your credentials in an environment file (.env) at the root of your project. The client secret is optional — include it only if MediaViz issued you one.

Create an Environment File

# .env
MEDIAVIZ_CLIENT_ID=YOUR_CLIENT_ID
# Optional — include only if MediaViz issued you a client secret
MEDIAVIZ_CLIENT_SECRET=YOUR_CLIENT_SECRET
# .env
MEDIAVIZ_CLIENT_ID=YOUR_CLIENT_ID
# Optional — include only if MediaViz issued you a client secret
MEDIAVIZ_CLIENT_SECRET=YOUR_CLIENT_SECRET
# .env
MEDIAVIZ_CLIENT_ID=YOUR_CLIENT_ID
# Optional — include only if MediaViz issued you a client secret
MEDIAVIZ_CLIENT_SECRET=YOUR_CLIENT_SECRET
# .env
MEDIAVIZ_CLIENT_ID=YOUR_CLIENT_ID
# Optional — include only if MediaViz issued you a client secret
MEDIAVIZ_CLIENT_SECRET=YOUR_CLIENT_SECRET
# .env
MEDIAVIZ_CLIENT_ID=YOUR_CLIENT_ID
# Optional — include only if MediaViz issued you a client secret
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',
});
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',
]);

Once initialized, the SDK handles OAuth for you — it acquires an access token, attaches it to every request, and refreshes it automatically. You never manage tokens directly. 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

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'
);
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'
);
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'
);
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'
)
# 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'
);
// $result['id'], $result['company_id']
curl -X POST 'https://api.mediaviz.ai/api/v1/users/new_company/' \
  -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"
}
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 project.create_project_and_run 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',
  null,  // private — optional; defaults to false
  null,  // type — optional project type id
  'Wedding photos 2026',
  null,  // directory — optional folder path
  2,
  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',
  null,  // private — optional; defaults to false
  null,  // type — optional project type id
  'Wedding photos 2026',
  null,  // directory — optional folder path
  2,
  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',
  null,  // private — optional; defaults to false
  null,  // type — optional project type id
  'Wedding photos 2026',
  null,  // directory — optional folder path
  2,
  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',
    None,  # private — optional; defaults to false
    None,  # type — optional project type id
    'Wedding photos 2026',
    None,  # directory — optional folder path
    2,
    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',
  null,  // private — optional; defaults to false
  null,  // type — optional project type id
  'Wedding photos 2026',
  null,  // directory — optional folder path
  2,
  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": null,
  "description": "Wedding photos 2026",
  "directory": null,
  "photo_upload_vector": 2,
  "thumbnail": null,
  "run_name": null
}
JSON

Response Sample

{
  "project_table_name": "z-photos-1024-a1b2c3d4",
  "outcomes": ["curation"],
  "models": ["blur", "colors", "face_recognition", "image_classification", "similarity", "evidence"],
  "status": "created"
}

Upload Photo

Send each photo to the upload endpoint. You must resize each photo to exactly 256×256 px and Base64-encode it before calling the SDK — the SDK does not resize for you. The SDK handles fetching the upload template for the collection automatically and caches it across calls.

Request Sample

const result = await mediaviz.photoUpload.uploadPhoto(
  'z-photos-1024-a1b2c3d4',
  1024,
  8507,
  0,
  {
    title: 'IMG_0001.jpg',
    fileContent: '<base64-encoded image data>',
    mimetype: 'image/jpeg',
    filePath: '/photos/IMG_0001.jpg'
  }
);
const result = await mediaviz.photoUpload.uploadPhoto(
  'z-photos-1024-a1b2c3d4',
  1024,
  8507,
  0,
  {
    title: 'IMG_0001.jpg',
    fileContent: '<base64-encoded image data>',
    mimetype: 'image/jpeg',
    filePath: '/photos/IMG_0001.jpg'
  }
);
const result = await mediaviz.photoUpload.uploadPhoto(
  'z-photos-1024-a1b2c3d4',
  1024,
  8507,
  0,
  {
    title: 'IMG_0001.jpg',
    fileContent: '<base64-encoded image data>',
    mimetype: 'image/jpeg',
    filePath: '/photos/IMG_0001.jpg'
  }
);
result = mediaviz.photo_upload.upload_photo(
    'z-photos-1024-a1b2c3d4',
    1024,
    8507,
    0,
    title='IMG_0001.jpg',
    file_content='<base64-encoded image data>',
    mimetype='image/jpeg',
    file_path='/photos/IMG_0001.jpg'
)
$result = $mediaviz->photoUpload->uploadPhoto(
  'z-photos-1024-a1b2c3d4',
  1024,
  8507,
  0,
  [
    'title' => 'IMG_0001.jpg',
    'file_content' => '<base64-encoded image data>',
    '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 via headers
curl -X POST 'https://upload.mediaviz.ai/photo_upload' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoidXNyXzAxYWJjMTIzIiwiZXhwIjoxNzQzNjMwMzI5fQ.RwJF-KLLr8K5JgEtIeFiKWELcv-FDLNzMPHJ2St_wAo' \
  -H 'x-company-id: 1024' \
  -H 'x-user-id: 8507' \
  -H 'x-project-table-name: z-photos-1024-a1b2c3d4' \
  -H 'x-title: IMG_0001.jpg' \
  -H 'Content-Type: application/json' \
  --data @- <<'JSON'
{
  "file_content": "<base64-encoded image data>",
  "mimetype": "image/jpeg",
  "file_path": "/photos/IMG_0001.jpg"
}
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');
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. The response includes an overall progress_percentage as well as an individual completion flag for each model that was configured for the collection.

progress_percentage is a fraction between 0 and 1. Each configured model also has its own _model_complete boolean. Continue polling until progress_percentage reaches 1 and every model flag is true before fetching results.

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');
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
}

progress_percentage is a decimal between 0 and 1 — a value of 1 means project processing is complete and results are ready to fetch.

Individual Photo Results

Retrieve detailed analysis for a single photo using photo.get_photo_from_project. 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 as a { label: confidence } map
  • 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);
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
}