Skip to content

Repository files navigation

Target Video CMS Client for PHP

Unofficial PHP client for the Target Video CMS API v3.

This package is not affiliated with, endorsed by, or maintained by Target Video.

Overview

  • Bearer-token authenticated client for https://api.target-video.com/apiv3
  • Typed API for common video and category management tasks
  • Raw resource API for endpoints that do not have typed wrappers yet
  • Default cURL transport plus optional PSR-18 transport support
  • Automatic request encoding for multipart/form-data and application/x-www-form-urlencoded
  • Notes for verified live API behavior that differs from the published docs: docs/live-api-differences.md

Installation

composer require werstreamtes/targetvideo-cms-client

The default transport uses PHP's curl extension. If your runtime does not provide curl, use a PSR-18 HTTP client instead.

Getting Started

<?php

require 'vendor/autoload.php';

use Werstreamtes\TargetVideoCmsClient\CmsClient;
use Werstreamtes\TargetVideoCmsClient\Config;

$client = new CmsClient(new Config(
    bearerToken: 'YOUR_TARGETVIDEO_BEARER_TOKEN',
));

$videos = $client->videos()->all(
    partnerId: 12345,
    queryParameters: [
        'page' => 1,
        'limit' => 25,
    ],
);

foreach ($videos->entries() as $entry) {
    echo $entry->videoId() . ': ' . ($entry->videoName() ?? 'unnamed') . PHP_EOL;
}

Video API

<?php

use Werstreamtes\TargetVideoCmsClient\Video\AddVideoRequest;
use Werstreamtes\TargetVideoCmsClient\Video\EditVideoRequest;
use Werstreamtes\TargetVideoCmsClient\Video\VideoCustomProperty;

$videos = $client->videos();

$created = $videos->add(new AddVideoRequest(
    partnerId: 12345,
    name: 'Example Video',
    sourceUrl: 'https://cdn.example.com/video.mp4',
    description: 'Created through the typed video API',
    credits: 'Reuters',
    tags: 'example,typed-client',
    customProperties: [
        new VideoCustomProperty('slot', 'pre-roll'),
    ],
));

$video = $videos->view($created->videoId());

$videos->edit($video->id(), new EditVideoRequest(
    name: 'Renamed Example Video',
    description: 'Updated description',
    credits: 'AP',
    clickthroughUrl: 'https://example.com/watch/' . $video->id(),
    customProperties: [
        new VideoCustomProperty('slot', 'mid-roll'),
    ],
));

$videos->delete($video->id(), 12345);

Category API

Category endpoints are available in the live API but are currently missing from the public Target Video docs index. They are supported from a Target Video Support-provided Postman collection and verified against the live API.

<?php

use Werstreamtes\TargetVideoCmsClient\Category\AddCategoryRequest;
use Werstreamtes\TargetVideoCmsClient\Category\AssignVideosRequest;
use Werstreamtes\TargetVideoCmsClient\Category\EditCategoryRequest;

$categories = $client->categories();

$categoryList = $categories->all(parentId: 0, queryParameters: ['page' => 1]);

foreach ($categoryList->entries() as $entry) {
    echo $entry->categoryId() . ': ' . ($entry->categoryName() ?? 'unnamed') . PHP_EOL;
}

$createdCategory = $categories->add(new AddCategoryRequest(
    name: 'Example Category',
));

$category = $categories->view($createdCategory->categoryId());

$categories->edit($category->id(), new EditCategoryRequest(
    name: 'Renamed Example Category',
    parentId: 0,
));

$categories->assignVideos(new AssignVideosRequest(
    categoryIds: [$category->id()],
    videoIds: [540690],
));

$categories->delete($category->id());

Raw Resource API

Use the raw API when a typed method does not exist yet or when you need direct control over Target Video's request shape.

<?php

$adSources = $client->adSources()->call(
    'all',
    pathParameters: ['partner_id' => 12345],
);

$video = $client->resource('video')->call(
    'view',
    pathParameters: ['video_id' => 540690],
);

$createdVideo = $client->resource('video')->call(
    'add',
    bodyParameters: [
        'partner_id' => 12345,
        'name' => 'Example Video',
        'mp4' => 'https://cdn.example.com/video.mp4',
    ],
);

$updatedVideo = $client->resource('video')->call(
    'edit',
    pathParameters: ['video_id' => 540690],
    bodyParameters: [
        'Video' => [
            'name' => 'Renamed Example Video',
            'description' => 'Updated description from the API client',
            'clickthroughUrl' => 'https://example.com/watch/540690',
        ],
    ],
);

$analytics = $client->callOperation(
    'Topvideosdata',
    pathParameters: ['partner_id' => 12345],
    bodyParameters: [
        'from' => '2026-06-01',
        'to' => '2026-06-16',
    ],
);

For actions that are ambiguous inside a resource, use callOperation() with the exact operation ID from the operation catalog.

PSR-18 Transport

Install a PSR-18 client if you do not want to use the default cURL transport:

composer require guzzlehttp/guzzle guzzlehttp/psr7
<?php

use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Psr7\HttpFactory;
use Werstreamtes\TargetVideoCmsClient\CmsClient;
use Werstreamtes\TargetVideoCmsClient\Config;

$httpClient = new GuzzleClient();
$httpFactory = new HttpFactory();

$client = CmsClient::withPsr18(
    config: new Config(bearerToken: 'YOUR_TARGETVIDEO_BEARER_TOKEN'),
    httpClient: $httpClient,
    requestFactory: $httpFactory,
    streamFactory: $httpFactory,
);

Per-request transport options are intentionally transport-specific. With the PSR-18 transport, configure timeouts and retries on the injected HTTP client.

Supported Entry Points

Typed entry points:

$client->videos();
$client->categories();

Common raw resource helpers:

$client->adSchedules();
$client->adSources();
$client->adUnits();
$client->adUnitTemplates();
$client->analytics();
$client->carousel();
$client->categories();
$client->exchangeRules();
$client->iabTaxonomies();
$client->livestreamChannel();
$client->livestreamSchedule();
$client->partners();
$client->players();
$client->playerTemplates();
$client->playlists();
$client->revenueDashboard();
$client->users();
$client->resource('video');
$client->resource('videos');
$client->resource('category');
$client->resource('categories');
$client->resource('adSources');

Documentation Notes

The client is based on the public Target Video CMS reference and additional live API verification:

Known live API differences include:

  • video/edit accepts Video[description] even though the published edit reference omits it.
  • video/add and video/edit accept credits even though the published docs do not document that field.
  • video/add succeeds without channel_id even though the request example labels it as required.
  • video/all accepts page and limit even though the published query parameter list omits them.
  • Category management endpoints are available in the live API but are not listed in the published documentation index.

Development

This section is for contributors to this package, not for normal package users.

Build the PHP toolchain:

docker compose build

Validate Composer metadata, lint PHP files, and run unit tests:

docker compose run --rm php composer validate --strict
docker compose run --rm php composer lint
docker compose run --rm php composer test

Regenerate the operation catalog from the live docs:

docker compose run --rm php php tools/generate-operations.php

When regenerating the operation catalog, re-verify every entry in docs/live-api-differences.md.

Integration Tests

Live integration tests call the real Target Video API. Credentials are loaded from .env by Docker Compose.

Read-only integration tests:

TARGETVIDEO_TEST_BEARER_TOKEN="your-token" \
TARGETVIDEO_TEST_PARTNER_ID="12345" \
docker compose run --rm php composer test:integration

Write integration tests create disposable videos, edit metadata/custom properties, verify the updated values through video/view, and delete the videos again.

TARGETVIDEO_TEST_BEARER_TOKEN="your-token" \
TARGETVIDEO_TEST_PARTNER_ID="12345" \
TARGETVIDEO_TEST_ENABLE_WRITE_TESTS="1" \
docker compose run --rm php composer test:integration-write

If the partner account has no existing videos, set TARGETVIDEO_TEST_VIDEO_SOURCE_URL explicitly so the write suite has a source video URL to import. TARGETVIDEO_TEST_CHANNEL_ID is optional.

Releasing

Packagist versions are created from Git tags, not from a version field in composer.json.

git tag v0.1.0
git push origin main --tags

After the GitHub repository is connected to Packagist, new tags become installable Composer versions.

About

Unofficial PHP API client for the Target Video CMS API v3.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages