MLCG.RestControl is the public C# client for reading MLCG sessions, updating graphics data and controlling scene animation through REST. Use it in a desktop controller, newsroom application, scoreboard integration or automation service.
This guide targets public version 1.0.2. Source code and release notes are available in the public GitHub repository. For designing graphics, see the MLCG Editor documentation on GitBook.
Understand the three components
| Component | Responsibility |
|---|---|
| MLCG web editor | Design templates, expose data bindings and publish sessions. |
| MLCG.RestControl | Authenticate REST calls, discover sessions, update values and send playback commands. |
| HTML output / SDK HTML5 plugin | Render a session's graphics. The plugin composites that HTML output over SDK video. |
The REST package itself does not decode video or render an overlay. It can be used without the Video SDK. Rendering over SDK video requires the corresponding installed SDK and HTML5 plugin. For complete MPlatform and MFormats examples, see MLCG HTML5 Graphics Samples.
1. Install the public package
dotnet add package MLCG.RestControl --version 1.0.2
For a project that uses PackageReference:
<PackageReference Include="MLCG.RestControl" Version="1.0.2" />
Version 1.0.2 provides .NET Framework 4.7.2 and .NET 9.0 library targets. It includes Demo Workspace operations, named animation helpers, session timing metadata and typed REST errors. A private preview package or a checkout of the wrapper source is not required.
2. Publish a session and authenticate
In the web editor, open a template, expose the fields your application should change, and publish the session. Generate a REST token with access to that session. Store the token in your application's secure configuration; do not embed a real token in source code, screenshots, logs or HTML output URLs.
The hosted REST base address is https://cg.medialooks.com. Use a configured local/on-premises address only when that service is actually running. A successful health check does not establish that a token is authorized to list or control sessions.
3. List sessions and read their bindings
An interactive controller should keep its client for the controller's lifetime and dispose it when closing. The following complete method is a one-shot lookup example, so it owns and disposes a client for that operation. It reads the sessions and binding values without changing any graphics:
using System;
using System.Threading;
using System.Threading.Tasks;
using MLCG.RestControl;
public static async Task ListSessionsAsync(
string tokenFromSecureConfiguration,
CancellationToken cancellationToken)
{
using (var client = new MlcgRestClient("https://cg.medialooks.com"))
{
client.ApiToken = tokenFromSecureConfiguration;
var sessions = await client.GetSessionsAsync(cancellationToken);
foreach (var session in sessions)
{
Console.WriteLine(session.Id + ": " + session.Name);
var bindings = await client.GetBindingsAsync(
session.Id, cancellationToken);
foreach (var binding in bindings)
Console.WriteLine(binding.Key + " = " + binding.Value);
}
}
}
Select a session ID returned by the service in your application UI. Do not substitute a Library template ID. Account mode lists the published sessions visible to that token, not the entire design Library.
4. Build a transparent HTML overlay URL
The following fragments assume your controller has an authenticated client, a selectedSessionId chosen from the returned sessions, and a cancellationToken.
string outputUrl = client.BuildOverlayUrl(
outputBaseUrl: "https://cg.medialooks.com",
sessionId: selectedSessionId,
autoplay: false,
loop: false);
Load this URL into the SDK HTML5 plugin with BrowserPageLoad, or another supported browser-overlay consumer. BuildOverlayUrl creates a transparent, read-only output URL without placing the REST control token in it.
Read-only does not mean private: anyone with a usable output link may be able to view its graphics and displayed data. Share it only with intended viewers, and never share the control token.
Load and start are different steps. For the SDK sample workflow, keep the local overlay hidden, load the URL with autoplay disabled, and wait for the actual MLCG scene and its fonts/images to become ready. Then send one Restart command and reveal the prepared local overlay:
await client.RestartAnimationAsync(
selectedSessionId, loop: false,
cancellationToken: cancellationToken);
HTML loading, readiness detection and local visibility belong to the SDK integration, not to the REST wrapper. Completion of the HTTP request does not prove that the browser has painted an exact frame. Avoid loading with autoplay enabled and immediately sending Restart, which can produce two visible starts.
5. Change graphics data
First read the session's bindings and use keys that actually exist in that design. For example, if the published session exposes headline:
await client.UpdateBindingAsync(
sessionId: selectedSessionId,
key: "headline",
value: "Updated from our C# application",
cancellationToken: cancellationToken);
Send related values in one request when the session exposes all of these keys:
using System.Collections.Generic;
await client.UpdateBindingsAsync(
selectedSessionId,
new Dictionary<string, string>
{
["player_name"] = "MARTA KOVACS",
["team_name"] = "RIVER CITY FC",
["score"] = "2 - 1"
},
cancellationToken);
Only send values changed by your operator or application. Normal value updates should use UpdateBindingAsync or UpdateBindingsAsync; replacing the entire binding list is a different operation and should be reserved for applications that own the complete list.
Changes are session-wide. Every viewer subscribed to that session receives its updated bindings and animation commands. For independent graphics or independent operators, use separate sessions rather than changing a shared session accidentally.
6. Control animation
Version 1.0.2 provides named helpers for common controls:
// Start again from zero.
await client.RestartAnimationAsync(selectedSessionId, loop: false,
cancellationToken: cancellationToken);
// Pause at the current graphics position.
await client.PauseAnimationAsync(selectedSessionId,
cancellationToken: cancellationToken);
// One atomic command: seek to 1.5 seconds AND remain paused.
await client.SeekAnimationAsync(selectedSessionId, positionMs: 1500,
cancellationToken: cancellationToken);
// Resume without an implicit seek to zero.
await client.PlayAnimationAsync(selectedSessionId,
cancellationToken: cancellationToken);
await client.SetAnimationLoopAsync(selectedSessionId, enabled: true,
cancellationToken: cancellationToken);
var timing = await client.GetSessionAnimationInfoAsync(
selectedSessionId, cancellationToken);
int maximumSliderPositionMs = timing.DurationMs;
Build a seek slider from the returned timing metadata and send a command when the user commits a seek, not on every UI refresh. This metadata describes the scene's range; it is not a remote current-playhead or paint acknowledgement. Scene Loop is separate from intrinsic ticker/layer loops.
REST animation control does not itself synchronize graphics with a video's source clock. Pausing SDK video does not automatically pause a session that other HTML viewers are also displaying. The samples deliberately keep these controls independent.
Temporary Demo Workspaces
For a sample that should work without an account token, use a temporary Demo Workspace instead of distributing a shared user's password. The application starts a workspace, uses the returned temporary token, reads the demo catalog and creates a private session instance:
var demoClient = new MlcgRestClient("https://cg.medialooks.com");
var launchId = Guid.NewGuid().ToString("D");
var workspace = await demoClient.StartDemoWorkspaceAsync(
launchId, "my-sample", "1.0.0", cancellationToken); // Your application's version.
demoClient.ApiToken = workspace.ApiToken;
var catalog = await demoClient.GetDemoTemplatesAsync(cancellationToken);
// selectedTemplateId comes from this catalog.
var instanceKey = Guid.NewGuid().ToString("D");
var instance = await demoClient.CreateDemoSessionAsync(
workspace.Id, selectedTemplateId, instanceKey, cancellationToken);
string privateSessionId = instance.Session.Id;
Use a new, dedicated client for this demo flow, not a client already carrying an account token. Keep the same launch/instance IDs when retrying the same intended creation; generate fresh IDs for a genuinely new launch or instance.
While controlling the workspace, renew it with HeartbeatDemoWorkspaceAsync at the service's returned HeartbeatIntervalSeconds, adopting updated expiry/interval values. Keep the original token: renewal responses do not issue another token. The wrapper does not run an automatic heartbeat or manage a template cache for your application.
On normal shutdown, call ReleaseDemoWorkspaceAsync with a separate bounded cleanup cancellation token, then dispose the client. Release relinquishes control; read-only viewers may remain until expiry. EndDemoWorkspaceAsync explicitly ends the workspace and its outputs, so it is not interchangeable with Release. Demo edits are temporary; handle expiry, capacity limits and lease-renewal errors in your UI. The complete SDK samples demonstrate this lifecycle.
Handle errors without hiding them
try
{
await client.UpdateBindingAsync(selectedSessionId, "headline",
"New headline", cancellationToken);
}
catch (OperationCanceledException)
{
// Cancellation or request timeout: report it to your UI.
}
catch (MlcgRestException ex)
{
string status = ex.StatusCode.HasValue
? ((int)ex.StatusCode.Value).ToString()
: "transport";
Console.WriteLine("MLCG REST request failed: " + status);
// ex.RetryAfter may provide a delay for capacity/rate-limit responses.
}
Check the endpoint and status: 401/403 usually require checking token/access; 404 may indicate a missing session or route; 429 may indicate a rate or capacity limit. Do not parse an exception's text to determine the HTTP status. A request without an HTTP response may have no status code. Mutating commands are not automatically retried: avoid blindly replaying an operation whose outcome is uncertain.
Further reading
Still have questions?
Tell us what didn’t work or what you’d like clarified.