Getting Started
A complete guide to the MediaViz API — from creating your account to viewing AI-powered photo curation results.
Creating Your Account
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',
});
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',
});
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',
]);
Before making any API calls, you need a user account. MediaViz uses a company-based account model — each account belongs to an organization, and one user must be designated as the company owner.
Create the First Company User
To register a new company and its owner, send a request to POST /api/v1/users/new_company. This endpoint 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
- Account type — set to
3for company owner - Company name — the name of your organization
A successful response triggers an email verification message to the provided address and returns a user_id and company_id. Record both — you will need them for subsequent requests.
Request Sample
const { user_id, company_id } = await mediaviz.users.createUserAndCompany(
'Jane Smith',
'[email protected]',
3,
's3cur3P@ss',
null,
null,
null,
'Acme Photography'
);
const { user_id, company_id } = await mediaviz.users.createUserAndCompany(
'Jane Smith',
'[email protected]',
3,
's3cur3P@ss',
null,
null,
null,
'Acme Photography'
);
$result = $mediaviz->users->createUserAndCompany(
'Jane Smith',
'[email protected]',
3,
's3cur3P@ss',
null,
null,
null,
'Acme Photography'
);
// $result['user_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": "[email protected]",
"company_id": null,
"profile_picture": null,
"payment_plan_type": null,
"password": "s3cur3P@ss",
"company_name": "Acme Photography"
}
JSON
Response Sample
{
"user_id": "usr_01abc123",
"company_id": "cmp_01xyz456",
"email": "[email protected]",
"message": "Verification email sent."
}
To add additional users to an existing company, use the same endpoint with account_type set to 1 (standard user) or 2 (company admin), and include the existing company_id.
Authentication & Access Tokens
The MediaViz API uses OAuth2 JWT tokens for authentication. To obtain tokens, exchange your credentials at POST /api/v1/token/.
Required fields:
- Email address — the email used during registration
- Password — your account password
The response includes both an access_token and a refresh_token, each with a 24-hour TTL. Use the refresh token when authenticating API calls — not the access token.
Request Sample
const { access_token, refresh_token } = await mediaviz.oAuthToken.token('[email protected]', 's3cur3P@ss');
const { access_token, refresh_token } = await mediaviz.oAuthToken.token('[email protected]', 's3cur3P@ss');
$result = $mediaviz->oAuthToken->token('[email protected]', 's3cur3P@ss');
// $result['access_token'], $result['refresh_token']
curl -X POST 'https://api.mediaviz.ai/oauth/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=<GRANT_TYPE>' \
--data-urlencode 'code=<CODE>' \
--data-urlencode 'redirect_uri=<REDIRECT_URI>' \
--data-urlencode 'client_id=<CLIENT_ID>' \
--data-urlencode 'code_verifier=<CODE_VERIFIER>' \
--data-urlencode 'refresh_token=<REFRESH_TOKEN>' \
--data-urlencode 'client_secret=<CLIENT_SECRET>'
Response Sample
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer",
"user_id": "usr_01abc123"
}
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 POST /api/v1/project_outcome/ with query parameters 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,
null,
'Wedding photos 2026',
null,
2,
null,
null,
{
outcomes: 'curation'
}
);
const { project_table_name } = await mediaviz.projects.createProjectAndRun(
'My Wedding Collection',
null,
null,
'Wedding photos 2026',
null,
2,
null,
null,
{
outcomes: 'curation'
}
);
$result = $mediaviz->projects->createProjectAndRun(
'My Wedding Collection',
null,
null,
'Wedding photos 2026',
null,
2,
null,
null,
'curation'
);
// $result['project_table_name']
curl -X POST 'https://api.mediaviz.ai/api/v1/project_outcome/?outcomes=curation' \
-H 'Authorization: Bearer mvz_sk_live_7K2wQ9pL3mR8xN4vBjH1cT6yF0dZaEuS' \
-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-cmp_01xyz456-a1b2c3d4",
"outcomes": ["curation"],
"models": ["blur", "colors", "face_recognition", "image_classification", "similarity", "evidence"],
"status": "created"
}
Uploading Photos
Upload each photo in the collection with uploadPhoto. The SDK fetches the collection's upload template on the first call, caches it, and posts the photo to the dedicated upload service.
Photos must be Base64-encoded and resized to 256×256 px before upload. Call uploadPhoto once per photo, passing a zero-based photo_index.
Request Sample
const result = await mediaviz.photoUpload.uploadPhoto(
'z-photos-cmp_01xyz456-a1b2c3d4',
'cmp_01xyz456',
'usr_01abc123',
0,
{
title: 'beach-sunset.jpg',
fileContent: '<base64-encoded photo>',
mimetype: 'image/jpeg',
filePath: 'beach-sunset.jpg'
}
);
const result = await mediaviz.photoUpload.uploadPhoto(
'z-photos-cmp_01xyz456-a1b2c3d4',
'cmp_01xyz456',
'usr_01abc123',
0,
{
title: 'beach-sunset.jpg',
fileContent: '<base64-encoded photo>',
mimetype: 'image/jpeg',
filePath: 'beach-sunset.jpg'
}
);
$result = $mediaviz->photoUpload->uploadPhoto(
'z-photos-cmp_01xyz456-a1b2c3d4',
'cmp_01xyz456',
'usr_01abc123',
0,
[
'title' => 'beach-sunset.jpg',
'file_content' => '<base64-encoded photo>',
'mimetype' => 'image/jpeg',
'file_path' => 'beach-sunset.jpg'
]
);
curl -X POST 'https://api.mediaviz.ai/photo_upload' \
-H 'Authorization: Bearer mvz_sk_live_7K2wQ9pL3mR8xN4vBjH1cT6yF0dZaEuS' \
-H 'x-bucket-name: <BUCKET_NAME>' \
-H 'x-photo-index: 0' \
-H 'x-company-id: cmp_01xyz456' \
-H 'x-user-id: usr_01abc123' \
-H 'x-project-table-name: z-photos-cmp_01xyz456-a1b2c3d4' \
-H 'x-title: <TITLE>' \
-H 'Content-Type: application/json' \
--data @- <<'JSON'
{
"file_content": "<FILE_CONTENT>",
"mimetype": "<MIMETYPE>",
"file_path": "<FILE_PATH>"
}
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. Call:
POST /v1/project/{project_table_name}/upload_complete/
Include your refresh_token in the Authorization header. 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-cmp_01xyz456-a1b2c3d4');
const result = await mediaviz.projects.markProjectUploadComplete('z-photos-cmp_01xyz456-a1b2c3d4');
$result = $mediaviz->projects->markProjectUploadComplete('z-photos-cmp_01xyz456-a1b2c3d4');
curl -X POST 'https://api.mediaviz.ai/api/v1/project/z-photos-cmp_01xyz456-a1b2c3d4/upload_complete/' \
-H 'Authorization: Bearer mvz_sk_live_7K2wQ9pL3mR8xN4vBjH1cT6yF0dZaEuS'
Check Run Status
Poll the status endpoint to track processing progress. The response includes an overall progress_percentage as well as individual status fields for each model that was configured for the collection.
GET /v1/project/status/{project_table_name}
Continue polling until progress_percentage reaches 100 and all model statuses indicate completion before fetching results.
Response Sample
{
"project_table_name": "z-photos-cmp_01xyz456-a1b2c3d4",
"progress_percentage": 72,
"models": {
"blur": "complete",
"colors": "complete",
"face_recognition": "processing",
"image_classification": "processing",
"similarity": "pending",
"evidence": "pending"
}
}
View Analysis Results
Once processing is complete, retrieve results at the collection level or for individual photos.
Get all photos sorted by score — use GET /api/v1/photos/{table_name}/sort/asc to retrieve every photo in the collection. Change the final path segment to desc to reverse the sort order.
Request Sample — All Photos Sorted
const result = await mediaviz.photos.getAllProjectPhotoIds(
'z-photos-cmp_01xyz456-a1b2c3d4',
{
ascOrDesc: 'asc'
}
);
const result = await mediaviz.photos.getAllProjectPhotoIds(
'z-photos-cmp_01xyz456-a1b2c3d4',
{
ascOrDesc: 'asc'
}
);
$result = $mediaviz->photos->getAllProjectPhotoIds(
'z-photos-cmp_01xyz456-a1b2c3d4',
[
'ascOrDesc' => 'asc'
]
);
curl -X GET 'https://api.mediaviz.ai/api/v1/photos/z-photos-cmp_01xyz456-a1b2c3d4/?asc_or_desc=asc' \
-H 'Authorization: Bearer mvz_sk_live_7K2wQ9pL3mR8xN4vBjH1cT6yF0dZaEuS'
Response Sample
[
{ "photo_id": "ph_001", "evidence_score": 0.91 },
{ "photo_id": "ph_002", "evidence_score": 0.87 },
{ "photo_id": "ph_003", "evidence_score": 0.54 }
]
Get top photos by tier — use GET /api/v1/photos_top/{table_name} to retrieve photos grouped into three tiers based on their evidence_score: best (top 15%), middle (middle 70%), and worst (bottom 15%).
Request Sample — Photos by Tier
const { best, middle, worst } = await mediaviz.photos.getTopMiddleBottomProjectPhotosByTableNameSortedByDateRankedKeysetPaginated('z-photos-cmp_01xyz456-a1b2c3d4');
const { best, middle, worst } = await mediaviz.photos.getTopMiddleBottomProjectPhotosByTableNameSortedByDateRankedKeysetPaginated('z-photos-cmp_01xyz456-a1b2c3d4');
$result = $mediaviz->photos->getTopMiddleBottomProjectPhotosByTableNameSortedByDateRankedKeysetPaginated('z-photos-cmp_01xyz456-a1b2c3d4');
// $result['best'], $result['middle'], $result['worst']
Response Sample
{
"best": ["ph_001", "ph_002"],
"middle": ["ph_003", "ph_004", "ph_005", "ph_006", "ph_007"],
"worst": ["ph_008", "ph_009"]
}
Individual Photo Results
Retrieve detailed analysis for a single photo using GET /api/v1/photos/{table_name}/{photo_id}. 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
- 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-cmp_01xyz456-a1b2c3d4', 'ph_001');
const result = await mediaviz.photos.getPhotoFromProject('z-photos-cmp_01xyz456-a1b2c3d4', 'ph_001');
$result = $mediaviz->photos->getPhotoFromProject('z-photos-cmp_01xyz456-a1b2c3d4', 'ph_001');
curl -X GET 'https://api.mediaviz.ai/api/v1/photos/z-photos-cmp_01xyz456-a1b2c3d4/ph_001' \
-H 'Authorization: Bearer mvz_sk_live_7K2wQ9pL3mR8xN4vBjH1cT6yF0dZaEuS'
Response Sample
{
"photo_id": "ph_001",
"blur_value": 0.95,
"main_color_palette": ["#3a5a8c", "#f0e6d2", "#2c2c2c"],
"labels_from_classifications_model": ["outdoor", "portrait", "natural light"],
"bounding_boxes_from_faces_model": [
{ "x": 120, "y": 45, "width": 80, "height": 90 }
],
"similar_photo_ids_high": ["ph_007"],
"similar_photo_ids_medium": ["ph_012", "ph_019"],
"similar_photo_ids_low": ["ph_031"],
"evidence_score": 0.91,
"face_score": 0.88,
"content_score": 0.84,
"aesthetic_score": 0.79,
"similarity_set_ranking": 1
}