HappyOysterEngine configures the Open Platform host and model, updates the Model Studio temporary API Key token, and creates Travel sessions. Travel is the session object returned by createTravel(); the session is entered and started only after calling travel.start(). Supports the adventure, directing, and acting modes.
HappyOysterEngine configures the Open Platform host, updates the Model Studio temporary API-key token, and creates Travel sessions.
Travel is the session object returned by createTravel(). The session is entered and started only after travel.start() is called.
Core Terminology
Term | Meaning | Notes |
|---|---|---|
token | Model Studio temporary API-key token: when calling Model Studio services from untrusted environments such as browsers or mobile apps, generate a temporary API Key through a secure backend to avoid exposing a permanent API Key. The SDK sends this token to Open Platform as an HTTP Bearer credential. | |
ticket | HappyOyster world Travel credential: your backend calls the credential API using AK authentication (gateway header) to obtain a short-lived Travel credential ( |
Overview
The SDK provides the following primary objects:
HappyOysterEngine
API | Description |
|---|---|
| Creates an Engine instance. |
| Updates the Model Studio temporary API-key token used by subsequent Open Platform API requests. |
| Creates a Travel session. |
| The current SDK version. |
| The current SDK package name, version, and package channel. |
Travel
API | Description |
|---|---|
| Starts the current Travel session. |
| Subscribes to session status changes. |
| Subscribes to first-frame URL notifications. |
| Subscribes to session metadata available immediately after enter-travel. |
| Subscribes to session runtime errors. |
| Checks whether the specified action can currently be called. |
| Gets available session metadata; returns |
| Sends a real-time control command. |
| Sends Directing instructions or prompt content. |
| Pauses the current session. |
| Resumes a paused session. |
| Rewinds a Directing session to the specified time. |
| Ends the current session and releases its resources. |
Other Exports
Export | Description |
|---|---|
| The error-code constant object exported by the SDK. |
| Checks whether an unknown error is a standard SDK error. |
Types | Public types such as |
Example
import { HappyOysterEngine, isSdkError } from '@happy-oyster/js-sdk'
const engine = new HappyOysterEngine({
APIHost: 'open-platform.example.com',
model: 'happyoyster-1.0-adventure', // Required; Adventure model shown as an example
token: 'bailian-temporary-api-key-token',
logLevel: 'warn',
streamReadyTimeout: 15_000,
})
const videoElement = document.getElementById('player') as HTMLVideoElement
const travel = engine.createTravel({
ticket: 'travel-ticket',
videoElement,
maxExperienceTimeSec: 90,
})
const unsubscribeStatus = travel.on('statusChanged', (status) => {
console.log('Travel status:', status)
})
const unsubscribeFirstFrame = travel.on('firstFrameGenerated', (firstFrame) => {
console.log('First frame URL:', firstFrame)
})
const unsubscribeInfo = travel.on('travelInfoReady', (info) => {
console.log('Travel info is ready before RTC playback:', info)
})
const unsubscribeError = travel.onError((error) => {
console.error('Travel error:', error)
})
try {
const { encryptedTravelId, mode, creationModel, firstFrame, maxExperienceTimeSec, aspectRatio } = await travel.start()
// Adventure (mode 1)
await travel.sendCommand({
translation: 'Front',
rotation: 'Mouse_Left',
interaction: 'Jump',
})
// Directing (mode 2) or Acting (mode 3; not scriptlist)
await travel.sendInstruct({ content: 'Turn the camera toward the castle and have the protagonist start running' })
await travel.pause()
await travel.resume()
} catch (err) {
if (isSdkError(err)) {
console.error('SDK error:', err.code, err.message)
} else {
console.error('Unexpected error:', err)
}
} finally {
unsubscribeStatus()
unsubscribeFirstFrame()
unsubscribeInfo()
unsubscribeError()
await travel.end()
}
engine.updateToken('new-bailian-temporary-api-key-token')
HappyOysterEngine
HappyOysterEngine is the Web SDK entry point. It configures the Open Platform host, manages the Model Studio temporary API-key token used by subsequent requests, and creates Travel sessions.
NoteAn Engine instance currently manages only one active Travel at a time. End the current Travel before starting a new session.
After a token is set either in the constructor or through updateToken(), the SDK internally fetches Feature Gate configuration. This allows the platform to remotely disable the SDK or require older versions to upgrade. If the request fails, the SDK fails open and does not block the normal experience.
API | Description |
|---|---|
| Creates an Engine instance with the required API host and model, and optional token and log level. |
| Updates the Model Studio temporary API-key token used by subsequent Open Platform requests. |
| Creates a Travel session that has not yet started. |
new HappyOysterEngine
Creates a HappyOysterEngine instance.
Signature
new HappyOysterEngine(config: SDKConfig)
Parameters
SDKConfig
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Open Platform API host. It must be a bare host, such as |
|
| Yes | Identifier of the Open Platform model to use. Required, with no default. Fixed for this Engine and shared by all its Travels. |
|
| No | Model Studio temporary API-key token set during construction. It can also be set later with |
|
| No | SDK log level. Defaults to |
|
| No | Timeout for waiting for |
Set model to a model identifier, such as happyoyster-1.0-adventure, an Adventure model. Use the model identifier for your target service environment. The SDK does not choose a model from the experience mode or infer it from the ticket.
An Engine has a fixed APIHost + model. Reuse it for successive Travels targeting the same service and model. Before switching either value, end the active Travel and use an Engine configured for the new target. Create the world and issue its ticket against the same service target.
Returns
Returns a HappyOysterEngine instance.
Errors
If config is missing, or if APIHost, model, token, logLevel, or streamReadyTimeout has an invalid type or value, an SdkError with code ErrorCode.INVALID_ARGUMENT (10010001) is thrown synchronously. Passing a full URL, an empty string, or a value with a path as APIHost is invalid.
model is required and must be a non-empty string after trimming; null, non-string values, and whitespace-only strings are invalid. Omitting it or passing undefined also raises an argument error; the SDK has no default model.
HappyOysterEngine.updateToken
Updates the Model Studio temporary API-key token used by subsequent Open Platform API requests.
Signature
updateToken(token: string): void
Parameters
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Model Studio temporary API-key token. Passing a blank string clears the current token. |
Returns
Returns nothing.
Errors
If token is not a string, an SdkError with code ErrorCode.INVALID_ARGUMENT (10010001) is thrown synchronously.
HappyOysterEngine.createTravel
Creates a Travel session instance without starting it.
Signature
createTravel(config: CreateTravelConfig): Travel
Parameters
CreateTravelConfig
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Ticket used to start the Travel later. |
|
| Yes | The |
|
| No | Maximum Adventure experience duration, in seconds. Directing and Acting sessions ignore this field. When omitted, the server applies its default. |
Returns
Returns a created but not yet started Travel session. The caller must then run await travel.start() to enter the session and wait for the video to become playable.
Each HappyOysterEngine instance may have only one active Travel at a time. Call await travel.end() before creating another Travel.
Errors
createTravel() throws an SdkError synchronously in the following cases:
ErrorCode | Description |
|---|---|
|
|
| A Travel is already active; call |
Startup errors are exposed by travel.start().
Travel
Travel represents a session created by HappyOysterEngine.createTravel(). It is initially inactive. After travel.start() is called, the SDK enters the session and waits for the video to become playable.
Travel supports starting, pausing, resuming, rewinding, and ending a session; sending real-time controls and prompts; and subscribing to status changes and runtime errors.
Methods
Method | Description |
|---|---|
| Starts the current Travel session. |
| Subscribes to session status changes. |
| Subscribes to first-frame URL notifications. |
| Subscribes to session metadata available immediately after enter-travel. |
| Subscribes to session runtime errors. |
| Checks whether the specified action can currently be called. |
| Gets available session metadata; returns |
| Sends a real-time control command. |
| Sends Directing instructions or prompt content. |
| Pauses the current session. |
| Resumes a paused session. |
| Rewinds the current session to the specified time. |
| Ends the current session and releases its resources. |
Status
Status | Description |
|---|---|
| The session has not started. |
| The session is starting and waiting for the video to become playable. |
| The session is running. |
| The session is paused and can be resumed or rewound. |
| The session has ended normally and its resources have been released. |
Events
Subscribe to events with travel.on(event, handler). The method returns an unsubscribe function.
Event | Callback | Description |
|---|---|---|
|
| The session status changed. |
|
| Emitted during |
|
| Emitted after enter-travel returns and before RTC connects. |
|
| A session runtime error. |
Travel.can
Checks whether an action is available for the current status and session capability.
Signature
can(action: TravelAction): boolean
Parameters
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Action to check: |
Returns
Returns a boolean. true means the action is currently available; false means the current status, mode, or session capability does not meet its preconditions.
Availability
action | Availability |
|---|---|
| Travel is still |
|
|
|
|
|
|
|
|
|
|
| Travel has not been closed. |
Errors
This method does not throw business errors. Unknown actions return false.
Travel.start
Starts the current Travel session.
Signature
start(): Promise<StartTravelResult>
Parameters
No parameters.
Returns
Returns a Promise<StartTravelResult>, which resolves after the session starts and the video becomes playable.
After enter-travel returns, the SDK emits travelInfoReady before connecting RTC. Late subscribers can call travel.getInfo(); it returns null before the metadata is available. If the response includes a non-empty firstFrame, firstFrameGenerated still follows.
StartTravelResult
Field | Type | Description |
|---|---|---|
|
| Current Travel session ID. |
|
| Session mode: |
|
| World creation model; common values are |
|
| First-frame image URL; |
|
| Maximum Adventure experience duration, in seconds. |
|
| Acting aspect ratio; |
Errors
start() rejects and emits an error event in the following cases. Use isSdkError(err) to check the error and read err.code and err.message.
ErrorCode | Description |
|---|---|
| SDK feature is disabled ( |
| Unable to start: the current status does not allow it, Open Platform is not configured, or entering the session failed |
| Unable to start: the session configuration returned by the server is incomplete |
| Unable to start: video stream connection failed or the SDK feature-flag request failed |
| Unable to start: timed out waiting for the video stream (uses the greater of |
| Unable to start: timed out waiting for the video to become playable (controlled by |
| Open Platform parameter, resource, or server error |
Travel.on("statusChanged")
Subscribes to session status changes.
Signature
on("statusChanged", handler: (status: TravelStatus) => void): () => void
Parameters
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Callback invoked when the status changes. |
Returns
Returns an unsubscribe function. TravelStatus is one of idle / prepare / running / paused / completed.
Errors
This method does not throw business errors.
Travel.on("firstFrameGenerated")
Subscribes to first-frame URL notifications.
Signature
on("firstFrameGenerated", handler: (firstFrame: string) => void): () => void
Parameters
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Callback invoked when the first-frame URL is available. |
Returns
Returns an unsubscribe function.
Behavior
Emitted only during travel.start(). After the SDK calls Open Platform enter-travel and receives a non-empty firstFrame, it emits the event immediately—usually after statusChanged("prepare") but before start() resolves and the video becomes playable. The event is not emitted if the response contains no first-frame URL.
Errors
This method does not throw business errors.
Travel.onError
Subscribes to session runtime errors.
Signature
onError(handler: (error: unknown) => void): () => void
Parameters
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Callback invoked when a runtime error occurs. |
Returns
Returns an unsubscribe function. Use isSdkError to narrow the error object to SdkError.
Errors
This method does not throw business errors.
Travel.sendCommand
Sends a real-time control command.
Signature
sendCommand(params: AdventureCommand): Promise<void>
Parameters
AdventureCommand
Field | Type | Required | Description |
|---|---|---|---|
|
| No | Movement direction. Defaults to |
|
| No | View rotation. Defaults to |
|
| No | Interaction action. Defaults to |
Control Command Reference
translation — Movement Direction
Describes character movement, supporting eight directions and combinations.
Value | Direction |
|---|---|
| Forward |
| Backward |
| Left |
| Right |
| Forward-left |
| Forward-right |
| Backward-left |
| Backward-right |
| Stationary |
rotation — View Rotation
Simulates mouse-based view rotation in eight directions.
Value | Direction |
|---|---|
| Up |
| Down |
| Left |
| Right |
| Up-left |
| Up-right |
| Down-left |
| Down-right |
| None |
interaction — Interaction Action
Value | Action |
|---|---|
| Jump |
| Attack |
| Crouch |
| Sprint |
| None |
Returns
Returns a Promise<void> that resolves after the command is submitted.
Errors
sendCommand() rejects in the following cases:
ErrorCode | Description |
|---|---|
|
|
| The current status or session mode does not allow commands, or the video-stream command failed |
Travel.sendInstruct
Sends Directing instructions or prompt content.
Signature
sendInstruct(params: InstructData): Promise<void>
Parameters
InstructData
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Prompt content to send. |
Returns
Returns a Promise<void> that resolves after Open Platform receives and processes the instruction.
Errors
sendInstruct() rejects and emits an error event in the following cases:
ErrorCode | Description |
|---|---|
| The session has not started |
| Failed to send the Directing instruction |
| Open Platform parameter, resource, or server error |
Travel.pause
Pauses the current session.
Signature
pause(): Promise<void>
Parameters
No parameters.
Returns
Returns a Promise<void> that resolves after video playback stops.
Errors
pause() rejects in the following cases:
ErrorCode | Description |
|---|---|
| The current status, session mode, or session capability does not allow pausing, or the pause request failed |
| Timed out waiting for the backend to report the video stream as paused (15 seconds) |
| Open Platform parameter, resource, or server error |
Travel.resume
Resumes a paused session.
Signature
resume(): Promise<void>
Parameters
No parameters.
Returns
Returns a Promise<void> that resolves after the video becomes playable again.
Errors
resume() rejects in the following cases:
ErrorCode | Description |
|---|---|
| The current status, session mode, or session capability does not allow resuming, or the resume request failed |
| Timed out waiting for the video to become playable again (15 seconds) |
| Open Platform parameter, resource, or server error |
Travel.rewind
Rewinds the current session to the specified time.
Signature
rewind(params: RewindTravelParams): Promise<RewindTravelResult>
Parameters
RewindTravelParams
Field | Type | Required | Description |
|---|---|---|---|
|
| Yes | Target time in seconds. Only multiples of 4 are supported (for example, |
Returns
Returns a Promise<RewindTravelResult> that resolves after rewind completes and playback resumes.
RewindTravelResult
Field | Type | Description |
|---|---|---|
|
| The actual time in seconds at which the server resumed playback. |
Errors
rewind() rejects and emits an error event in the following cases:
ErrorCode | Description |
|---|---|
| The session has not started |
| Unable to rewind: the session must first be paused and video playback stopped, or the rewind request or RTC reconnection failed |
| Timed out waiting for video to resume after rewind (15 seconds) |
| Open Platform parameter, resource, or server error |
Travel.end
Ends the current session and releases its resources.
Signature
end(): Promise<void>
Parameters
No parameters.
Returns
Returns a Promise<void> that resolves after cleanup finishes.
Errors
Cleanup errors are not thrown to the caller; end() makes a best effort to release resources.
Error Handling
The SDK exposes runtime errors through Promise rejections or error events. Errors are SdkError objects; use isSdkError(err) and read err.code and err.message.
Recognized Open Platform errors map to the 10000001–10000012 range, and err.message contains the platform message. See each Travel API's Errors section for method-specific codes.
ErrorCode Reference
Error-code ranges:
100000xx: Mapped Open Platform errors1001xxxx: Engine client errors1002xxxx: Travel client errors
code | name | Description |
|---|---|---|
|
| Invalid request parameters (returned by Open Platform) |
|
| Resource not found (Travel missing, not owned, in another workspace, or artifact not ready) |
|
| World does not exist, was deleted, or does not belong to the current developer |
|
| System error |
|
| Ticket is invalid or expired |
|
| Ticket has already been used (one-time credential) |
|
| World is not ready and cannot be entered |
|
| Inference resource allocation failed (insufficient capacity, stream creation failure, session initialization failure, etc.) |
|
| This API accepts only the primary API Key (temporary API Keys are not supported) |
|
| Input rejected by content moderation |
|
| Input image violates copyright or IP policy |
|
| Request conflicts with the current resource state |
|
| SDK client argument validation failed (not mapped from Open Platform) |
|
| SDK feature is disabled |
|
| A Travel is already active |
|
| Video stream disconnected during playback |
|
| Session start request failed |
|
| Video stream configuration missing during startup |
|
| Video stream connection failed |
|
| Timed out waiting for the video stream |
|
| Timed out waiting for the video to become playable |
|
| Pause request failed |
|
| Timed out waiting for video to pause |
|
| Resume request failed |
|
| Timed out waiting for video to resume |
|
| Rewind request failed |
|
| Timed out waiting for video to resume after rewind |
|
| Failed to send the real-time control command |
|
| Failed to send the Directing instruction |
|
| Session end request failed |
Other Exports
Runtime exports
Export | Type | Description |
|---|---|---|
|
| SDK client that configures Open Platform, updates the token, and creates Travel sessions. |
|
| The current SDK version. |
|
| The current SDK package name, version, and package channel. |
|
| The error-code constant object exported by the SDK. |
|
| Checks whether an unknown error is a standard SDK error. |
ErrorCode
The error-code constant object exported by the SDK. Compare it with SdkError.code instead of scattering numeric literals through application code.
import { ErrorCode } from '@happy-oyster/js-sdk'
isSdkError
Checks whether an unknown error is a standard SDK error. When it returns true, TypeScript narrows the error to SdkError, allowing safe access to code and message.
isSdkError(error: unknown): error is SdkError
try {
await travel.start()
} catch (err) {
if (isSdkError(err) && err.code === ErrorCode.OPEN_PLATFORM_TICKET_INVALID) {
// Request a new Travel ticket, then create a new Travel.
}
}
Public Types
The following types are exported from the package entry point and can be imported directly from @happy-oyster/js-sdk. They exist only at TypeScript compile time and produce no runtime code.
Type | Description |
|---|---|
|
|
| SDK log levels: |
| SDK package metadata: |
| SDK package channels: |
|
|
|
|
| Session metadata used by |
| Acting aspect ratio: |
|
|
| Local SDK session states: |
|
|
|
|
|
|
|
|
|
|
| SDK error shape containing |
| Error type combining runtime |
| Union of all error-code values in the |