Skip to main content

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

ArgumentDescription
tenantTenant ID (iten...)
objectPermissions object ID (iq__...)

Options

OptionTypeDefaultDescription
--ntp_classnumber4NTP class
--max_ticketsnumber10Max tickets to issue (0 = unlimited)
--max_redemptionsnumber100Max redemptions per ticket
--start_timestringValidity start time (ISO 8601, e.g. 2024-01-01) — required
--end_timestringValidity end time (ISO 8601, e.g. 2025-01-01) — required
--ticket_lengthnumber6Number 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

ArgumentDescription
tenantTenant ID
otpNTP instance ID (QOTP...)

Options

OptionTypeDefaultDescription
--max_ticketsnumber10New max tickets to issue (0 = unlimited)
--max_redemptionsnumber100New max redemptions per ticket
--start_timestringNew start time (ISO 8601) — required
--end_timestringNew 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

ArgumentDescription
tenantTenant ID
otpNTP 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

ArgumentDescription
tenantTenant ID
otpNTP 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
ArgumentDescription
tenantTenant ID

Options

OptionTypeDefaultDescription
--countnumber10Number of results to return
--offsetnumber0Pagination 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

ArgumentDescription
tenantTenant ID
otpNTP 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

ArgumentDescription
tenantTenant ID
otpNTP instance ID

Options

OptionTypeDescription
--passwordstringEncrypt the report with a password (optional)
--emailstringEmail address to associate with this report (optional)

Example

./elv-live otp report iten4TXq2en3qtu3JREnE5tSLRf9zLod QOTPdWejsPFuSAC
FieldDescription
CntIssuedTotal number of ticket codes issued from this instance
CntRedeemedNumber of distinct codes that have been redeemed at least once
TotalRedemptionsTotal 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

ArgumentDescription
tenantTenant ID
otpNTP instance ID
codeTicket code to check

Options

OptionTypeDescription
--emailstringEmail 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

ArgumentDescription
tenantTenant ID
otpNTP instance ID

Options

OptionTypeDescription
--emailstringEmail address to bind to this ticket
--max_redemptionsnumberPer-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

ArgumentDescription
tenantTenant ID
otpNTP instance ID

Options

OptionTypeDescription
--emailstringEmail address to bind to this ticket
--max_redemptionsnumberPer-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

ArgumentDescription
tenantTenant ID
otpNTP instance ID
codeThe ticket code to redeem

Options

OptionTypeDefaultDescription
--emailstringEmail bound to this ticket — required if the ticket was issued with an email
--include_ntp_idbooleanfalseInclude 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

ArgumentDescription
tenantTenant ID
otpNTP instance ID

Options

OptionTypeDescription
--quantitynumberNumber of anonymous codes to generate
--emailsstringPath 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

ArgumentDescription
tenantTenant ID
otpNTP instance ID
objectPlayable object ID — live stream or on-demand (iq__...)
codes_filePath 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.