OTP (NTP) Ticket Management
NTP (N-Time Password) instances gate access to content objects by issuing short-lived ticket codes. Class 4 NTP instances are managed directly via KMS — no authority service is required. These docs serve as reference for all elv-live otp subcommands.
Prerequisites
Set the PRIVATE_KEY environment variable to the tenant admin private key before running any command that creates or modifies an NTP instance:
export PRIVATE_KEY=<your-private-key>
Typical workflow
# 1. Create an NTP instance scoped to a permissions object
./elv-live otp create <tenant> <object> \
--start_time 2024-01-01 --end_time 2025-01-01 \
--max_tickets 0 --max_redemptions 3
# 2. Generate codes and save to file
./elv-live otp generate_codes <tenant> <otp> \
--quantity 50 > codes.json
# 3. Build embed URLs for each code
./elv-live otp make_embed_urls \
<tenant> <otp> \
<object> codes.json > urls.txt
# 4. Check usage at any time
./elv-live otp report <tenant> <otp>
# 5. Extend the window if needed
./elv-live otp update <tenant> <otp> \
--start_time 2024-01-01 --end_time 2025-06-01
# 6. Suspend when the event is over (reactivatable)
./elv-live otp suspend <tenant> <otp>
# 7. Or permanently remove the instance
./elv-live otp delete <tenant> <otp>
otp create
Create a new NTP instance tied to a permissions object.
./elv-live otp create <tenant> <object> [options]
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID (iten...) |
object | Permissions object ID (iq__...) |
Options
| Option | Type | Default | Description |
|---|---|---|---|
--ntp_class | number | 4 | NTP class |
--max_tickets | number | 10 | Max tickets to issue (0 = unlimited) |
--max_redemptions | number | 100 | Max redemptions per ticket |
--start_time | string | Validity start time (ISO 8601, e.g. 2024-01-01) — required | |
--end_time | string | Validity end time (ISO 8601, e.g. 2025-01-01) — required | |
--ticket_length | number | 6 | Number of characters in each ticket code |
Example
./elv-live otp create iten4TXq2en3qtu3JREnE5tSLRf9zLod iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs \
--start_time 2025-01-01 \
--end_time 2027-01-01 \
--max_tickets 100 \
--max_redemptions 5
Example response
QOTPdWejsPFuSAC
{{% alert %}}
startTime and endTime in the response are Unix epoch milliseconds.
{{% /alert %}}
otp update
Update parameters of an existing NTP instance. Only the fields you specify are changed.
./elv-live otp update <tenant> <otp> [options]
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
otp | NTP instance ID (QOTP...) |
Options
| Option | Type | Default | Description |
|---|---|---|---|
--max_tickets | number | 10 | New max tickets to issue (0 = unlimited) |
--max_redemptions | number | 100 | New max redemptions per ticket |
--start_time | string | New start time (ISO 8601) — required | |
--end_time | string | New end time (ISO 8601) — required |
Example
./elv-live otp update iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdWejsPFuSAC \
--start_time 2025-03-01 \
--end_time 2027-01-01 \
--max_redemptions 10
Example response
ntpId: QOTPdWejsPFuSAC
ntpClass: Class 4
tenantId: iten4TXq2en3qtu3JREnE5tSLRf9zLod
kmsId: ikms27hsDr6QtmWnJKVFkNzroSGEgjjq
objectId: iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs
updatedAt: 1782430038115
startTime: 1740787200000
endTime: 1798761600000
ticketLength: '6'
maxRedemptions: '10'
maxTickets: 10
otp suspend
Suspend an NTP instance. All tickets issued for this instance are immediately treated as expired. To reactivate, call otp update with a new future --end_time.
./elv-live otp suspend <tenant> <otp>
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
otp | NTP instance ID |
Example
./elv-live otp suspend iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdWejsPFuSAC
Example response
NTP instance suspended.
otp delete
Permanently delete an NTP instance. This cannot be undone — all issued tickets will stop working.
./elv-live otp delete <tenant> <otp>
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
otp | NTP instance ID |
Example
./elv-live otp delete iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdDvet9vGeUt
Example response
NTP instance deleted.
otp list
List all NTP instances for a tenant, with pagination support.
./elv-live otp list <tenant> [options]
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
Options
| Option | Type | Default | Description |
|---|---|---|---|
--count | number | 10 | Number of results to return |
--offset | number | 0 | Pagination offset |
Example
./elv-live otp list iten4TXq2en3qtu3JREnE5tSLRf9zLod --count 5 --offset 0
Example response
ntpInstances:
- ntpId: QOTPPvs1Men7PQv
ntpClass: Class 4
tenantId: iten4TXq2en3qtu3JREnE5tSLRf9zLod
kmsId: ikms27hsDr6QtmWnJKVFkNzroSGEgjjq
objectId: iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs
updatedAt: 1702006820726
startTime: .nan
endTime: .nan
ticketLength: '6'
maxRedemptions: '10'
maxTickets: 0
issuedTickets: 4
- ntpId: QOTPLznozufnUVC
ntpClass: Class 4
tenantId: iten4TXq2en3qtu3JREnE5tSLRf9zLod
kmsId: ikms27hsDr6QtmWnJKVFkNzroSGEgjjq
objectId: iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs
updatedAt: 1704824134216
startTime: .nan
endTime: .nan
ticketLength: '6'
maxRedemptions: '100'
maxTickets: 0
issuedTickets: 15
- ntpId: QOTPUjbbZ9QqKpg
ntpClass: Class 4
tenantId: iten4TXq2en3qtu3JREnE5tSLRf9zLod
kmsId: ikms27hsDr6QtmWnJKVFkNzroSGEgjjq
objectId: iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs
updatedAt: 1706905977525
startTime: .nan
endTime: .nan
ticketLength: '6'
maxRedemptions: '1000'
maxTickets: 0
issuedTickets: 5
- ntpId: QOTP2vx7X7uKeWQ
ntpClass: Class 4
tenantId: iten4TXq2en3qtu3JREnE5tSLRf9zLod
kmsId: ikms27hsDr6QtmWnJKVFkNzroSGEgjjq
objectId: iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs
updatedAt: 1706920943546
startTime: 1706911200000
endTime: .nan
ticketLength: '6'
maxRedemptions: '100'
maxTickets: 0
issuedTickets: 17
- ntpId: QOTPL7zKXy142dx
ntpClass: Class 4
tenantId: iten4TXq2en3qtu3JREnE5tSLRf9zLod
kmsId: ikms27hsDr6QtmWnJKVFkNzroSGEgjjq
objectId: iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs
updatedAt: 1707969656193
startTime: 946684800000
endTime: 32503680000000
ticketLength: '6'
maxRedemptions: '100'
maxTickets: 0
issuedTickets: 0
start: 0
end: 5
total: 32
The response includes start, end, and total for paginating through large result sets.
otp show
Show full details of a single NTP instance.
./elv-live otp show <tenant> <otp>
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
otp | NTP instance ID |
Example
./elv-live otp show iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdWejsPFuSAC
Example response
ntpId: QOTPdWejsPFuSAC
ntpClass: Class 4
tenantId: iten4TXq2en3qtu3JREnE5tSLRf9zLod
kmsId: ikms27hsDr6QtmWnJKVFkNzroSGEgjjq
objectId: iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs
updatedAt: 1782430038115
startTime: 1735689600000
endTime: 1798761600000
ticketLength: '6'
maxRedemptions: '5'
maxTickets: 100
issuedTickets: 0
{{% alert %}}
startTime: .nan and endTime: .nan indicate that no time window has been set — the instance is open-ended. maxTickets: 0 means unlimited.
{{% /alert %}}
otp report
Show a usage report for an NTP instance: how many codes have been issued, how many have been redeemed, and the total number of redemptions across all codes.
./elv-live otp report <tenant> <otp> [options]
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
otp | NTP instance ID |
Options
| Option | Type | Description |
|---|---|---|
--password | string | Encrypt the report with a password (optional) |
--email | string | Email address to associate with this report (optional) |
Example
./elv-live otp report iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdWejsPFuSAC
| Field | Description |
|---|---|
CntIssued | Total number of ticket codes issued from this instance |
CntRedeemed | Number of distinct codes that have been redeemed at least once |
TotalRedemptions | Total redemption events across all codes |
otp status
Check whether a specific ticket code is valid without consuming a redemption. Useful for support workflows or pre-flight checks.
./elv-live otp status <tenant> <otp> <code> [options]
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
otp | NTP instance ID |
code | Ticket code to check |
Options
| Option | Type | Description |
|---|---|---|
--email | string | Email bound to this ticket — required if the code was issued with an email |
Example
./elv-live otp status iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdWejsPFuSAC 8tmTRX \
--email viewer@example.com
{{% alert %}}
A 403 with redemptions exceed configured maximum means the code has been fully used — it is a valid code that has reached its redemption limit, not an invalid one.
{{% /alert %}}
otp issue_code
Issue a single ticket code from an NTP instance. The code can optionally be bound to an email address so only that address can redeem it.
./elv-live otp issue_code <tenant> <otp> [options]
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
otp | NTP instance ID |
Options
| Option | Type | Description |
|---|---|---|
--email | string | Email address to bind to this ticket |
--max_redemptions | number | Per-ticket redemption limit (overrides the instance default) |
Example
./elv-live otp issue_code iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdWejsPFuSAC \
--email viewer@example.com \
--max_redemptions 100
Example response
token: 8tmTRX
user_id: iusr2LAxXvBiqiXtf4gBa5sPgHvrSC65
otp issue_signed_code
Issue a ticket code signed by the caller's private key. The signature is appended to the token and can be verified by the content access layer. Use this when downstream services need cryptographic proof of who issued the ticket.
./elv-live otp issue_signed_code <tenant> <otp> [options]
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
otp | NTP instance ID |
Options
| Option | Type | Description |
|---|---|---|
--email | string | Email address to bind to this ticket |
--max_redemptions | number | Per-ticket redemption limit (overrides the instance default) |
Example
./elv-live otp issue_signed_code iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdWejsPFuSAC \
--email viewer@example.com \
--max_redemptions 100
Example response
token: >-
UNDFt1.RVMyNTZLX0ptQkVqS2h3TDRMZjVMVVBKQTRtNFFidEs1WkN4eGhranRLV3ZqYmZXcW5pWkdoS3N4VVdzYXp6RUpTb3lWcDI2dHk0SmZIVzlkS1A0bjFlWll6NDlCVzZ2
user_id: iusrWmJQm9XXbT65ApSNGNPW7myPTcH
The token field contains the ticket code followed by a . and the base64-encoded signature.
otp redeem_code
Redeem a ticket code to authorize the client for the target content object. Each redemption counts against the code's maxRedemptions limit.
./elv-live otp redeem_code <tenant> <otp> <code> [options]
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
otp | NTP instance ID |
code | The ticket code to redeem |
Options
| Option | Type | Default | Description |
|---|---|---|---|
--email | string | Email bound to this ticket — required if the ticket was issued with an email | |
--include_ntp_id | boolean | false | Include the NTP instance ID in the response alongside the object ID |
Example
./elv-live otp redeem_code iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdWejsPFuSAC 8tmTRX \
--email viewer@example.com \
--include_ntp_id
Example response (without --include_ntp_id)
iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs
Example response (with --include_ntp_id)
objectId: iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs
ntpId: QOTPdWejsPFuSAC
otp generate_codes
Generate multiple ticket codes in bulk from an NTP instance. Use --quantity for anonymous codes, or --emails to bind each code to a specific email address.
./elv-live otp generate_codes <tenant> <otp> [options]
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
otp | NTP instance ID |
Options
| Option | Type | Description |
|---|---|---|
--quantity | number | Number of anonymous codes to generate |
--emails | string | Path to a plain-text file with one email address per line — one code is generated per address |
Exactly one of --quantity or --emails must be provided.
Example — anonymous codes
./elv-live otp generate_codes iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdWejsPFuSAC \
--quantity 3
Example response
- token: 7Rc2HF
user_id: iusrWyArMHE8BWTou7M62mN2J3aFzRG
- token: 8PmSVY
user_id: iusr2XpyPUYpZBRYqZPbixhUE9ubSRhP
- token: EHHFNe
user_id: iusr24F62kzRE5uLxjBtrLZFkfygm7Xj
Example — email-bound codes
# viewers.txt contains one email per line:
# alice@example.com
# bob@example.com
./elv-live otp generate_codes iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdWejsPFuSAC \
--emails viewers.txt
Redirect output to a file to use with otp make_embed_urls:
./elv-live otp generate_codes iten... QOTP... --quantity 50 > codes.json
{{% alert %}} The output format when redirected is JSON (one object per code), even though the console displays YAML. {{% /alert %}}
otp make_embed_urls
Generate a playback embed URL for each code in a codes file. Each URL embeds the ticket code so a viewer can open it directly in a browser without entering the code manually. Accepts the JSON output file produced by otp generate_codes.
./elv-live otp make_embed_urls <tenant> <otp> <object> <codes_file>
Arguments
| Argument | Description |
|---|---|
tenant | Tenant ID |
otp | NTP instance ID |
object | Playable object ID — live stream or on-demand (iq__...) |
codes_file | Path to the JSON codes file produced by otp generate_codes |
Example
./elv-live otp make_embed_urls \
iten4TXq2en3qtu3JREnE5tSLRf9zLod \
QOTPdWejsPFuSAC \
iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs \
codes.json
Example response
- >-
https://embed.v3.contentfabric.io/?p=&net=demo&oid=iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs&mt=v&ptk=&ten=iten4TXq2en3qtu3JREnE5tSLRf9zLod&ntp=QOTPdWejsPFuSAC&tk=Tlk2Sjhv&ct=h&ath=aessjcFHX8p9vvCY7of9yap8v69ttgWRGH3wgXwy77sm4TgLoFhGNKs9iFxnH9tJFhuPGcpx88MuYmq9P6Bbr8nH3rjrtaocNNDZ1RTD3L24w6vdodeuRETkM5xvcijzHF8CcTb9jVKuLVHDN2PkeLyZs82zDnpLSGP8YdetvF1Tgmaczy69ZbaJfk2ZZJ5hHxFKrH8m9kn9hxkMEEgX2For8wGBvqkbGokJkKVgpt6qwZ7xDNRt4PknuBjyJ7XCH2vAh1uQazkbghC9Cd3tp9UAcjszixKDBxLb43PvkFnrXiVu7G8KbxaKh9MQc4iHMwRyrxZ3iy4cC3LGg43tSsaq2hgsR7eZPGQ7prwHxFw2orDjPcKkaXbY7Wp3E53CCEUUtQh4K9GWhHTaE
- >-
https://embed.v3.contentfabric.io/?p=&net=demo&oid=iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs&mt=v&ptk=&ten=iten4TXq2en3qtu3JREnE5tSLRf9zLod&ntp=QOTPdWejsPFuSAC&tk=R1VDa1hz&ct=h&ath=aessjcqr3zXiiEuB2f37gcgUCwaUX7GjvdEZ4McStRfQvhudjQJaU3uAvorM2Dc6DWhjSVAXGPogUQboumZQodcuVJKddJcupGa4THoDJKLkS77y1Dwert2RAP5v7gpP9wC3jDDWSBrcftx8ayc12Q66exZfUbLVcLPuPL3SGkiC3FyPgqTt6huCU4VGSGq16WWagTCja3CvSjo8YRRunjnv4NcpCNJbgb5vT1tchxNZG86foCEK9GSgTu3HLU9tUzXBHPsUqkmdBGZPzMDXJPRuCJP98PE2DEDHvvyR8ntEp5SD3b9v14ooG7AR3CGcwPitWQtCDgbWs5iw3MNDt6rR6H1HDn94ymmy51b1jWAJax7HQmAWxUw5fdCm4wCSdjUDddZvvS8vJUFaPc
- >-
https://embed.v3.contentfabric.io/?p=&net=demo&oid=iq__2G8JtbyLVUQvG73LWWDMWgBDXvTs&mt=v&ptk=&ten=iten4TXq2en3qtu3JREnE5tSLRf9zLod&ntp=QOTPdWejsPFuSAC&tk=Q1R5c2M2&ct=h&ath=aessjcEXqEkoDwamffDLuQyMcx93qc2wcdFCBTU5okcMfmfxxZoynNJYcZyNozGZ9Qvrj5EvFhkorf2G8AKm3xgTuRxXueuNjQwYg399iBAmuswNE66oZSGH1VhMPYAYhwJv6E8NyzumAEntAfJPNdLpEv7RyoagHDfKQa7sTubAjGYyTncoTDsHTxoZqpNMSgwDrca8E95sbgXeyAKGjidWfVnzN2JZ85u6SA1N3paXywYLBAMrmKbY6sSHaLHHvoERujFDsErwCz8quhzdEDymY9L2z2RxsNcHG2Aff5XSf5Agdrr859F2uZzCM25C5jnN2kYUXGo9RjZKYsiVJ5fPzpsCDVenBhYUw4TBEt7R5z8CyaJMz3dP9TA4Qe5nub5QAHBuvyzjDQk6z
One URL is produced for each entry in codes_file. Each URL is ready to share with the corresponding viewer. When a viewer opens the URL, the ticket is automatically redeemed.