Skip to content

Commands for your organization

All szenera commands that run with a key or account of your organization: media, scenes, playlists, programs, devices, team, apps, package.

21 minute readCLIUpdated: 10/25/2026

On this page

Before you start

For
Anyone who wants to trigger an operation of their organization from a script or the terminal and needs to know which command requires which route and permission
Prerequisite
a profile with a key or account of the organization. The credential must carry the permissions named in the “Route and permission” column.

All commands of the szenera command line. They run with an API key ak_… or an account of your organization. Each table names, per command, the route, the permission required, whether an API key may carry the permission (“Key”), and whether the command changes something. The “Key” column follows the platform’s permission catalog: a permission reserved for accounts is never granted to a key. The command then answers with 403 (exit 4), and you need a profile with password sign-in.

szenera <befehl> --help shows the positional arguments, flags, and examples of every command. The description there is the source of these tables. This page follows the registry of szenera with 136 commands, and all of them are listed here. 21 of them also serve platform operations and partly take a different route there. Those routes, and the commands that serve operations only, are described under Commands for platform operations.

Flags valid everywhere

Flag Effect
--help Show help for the command without doing anything. Never signs in
--profile=<name> Which profile applies (environment, credential, service addresses)
--json Force output as JSON
--table Force output as a table
--raw If a response breaks the contract, print the raw response

A flag carries its value after the equals sign (--limit=20), and --limit 20 does not exist. An unknown flag is an error (exit 1), not a silent hint. List commands page through results with --limit=<anzahl> (1 to 200, up to 100 for filtered lists), --cursor=<marke>, and --all (follow all pages). Commands that wait for an operation accept --timeout=<dauer> (90s, 20m, 2h, or a number in seconds) and some also --interval=<dauer> and --no-wait. Irreversible actions require --yes. Without the flag, the command aborts with exit 1 and says what would happen.

Environment and credential

Command Purpose Route and permission Key Modifies
health Whether the environment reports ready, and which check says what GET /health/ready, no credential needed, exit 9 on 503 — no
health public What the status page shows publicly: state per component, maintenance windows, public incidents GET /v1/public/status, no credential needed — no
whoami Who your own credential is: account, organization, permissions GET /v1/me, sign-in only, no permission of its own yes no
hygiene get What has been left lying around: six numbers, and for each number the command that shows the rows behind it GET /v1/analytics/hygiene · analytics.query.run. --offline-since (default P7D) and --dormant-since (default P90D) set the two thresholds yes no

Media and folders

Command Purpose Route and permission Key Modifies
asset list The media of the media library. --usage=unused finds what is in no scene, no playlist, and no brand mark GET /v1/assets · asset.list yes no
asset get <ast_…> One media item with its variants. --usages names where it is used GET /v1/assets/{id}, GET /v1/assets/{id}/usage · asset.read yes no
asset upload --file=<pfad> Upload a file to the media library and wait until it is usable POST /v1/assets/upload-precheck → bytes → POST /v1/assets/upload-complete · asset.upload. Waits until ready, default --timeout=10m, --no-wait yes yes
asset download <ast_…> --output=<pfad> Fetch a media item or one of its variants POST /v1/assets/{id}/download-url (variant: /variant-url) → bytes · asset.read yes no
asset update <ast_…> Change the name, tags, or folder of a media item PATCH /v1/assets/{id} · asset.update yes yes
asset reprocess <ast_…> Regenerate the variants of a media item and wait POST /v1/assets/{id}/reprocess · asset.update. Waits as with uploading yes yes
asset delete <ast_…> --yes Move a media item to the trash DELETE /v1/assets/{id} · asset.delete yes yes
asset restore <ast_…> Bring a media item back from the trash POST /v1/assets/{id}/restore · asset.update yes yes
asset purge <ast_…> --yes Delete a media item permanently POST /v1/assets/{id}/purge · asset.delete yes yes
asset bulk-update --assets=<ast_…,…> Move or tag many media items (up to 100) POST /v1/assets/bulk-move or POST /v1/assets/bulk-tag · asset.update yes yes
folder list The folder tree of the media library GET /v1/folders · asset.folder.list yes no
folder create --name=<name> Create a folder POST /v1/folders · asset.folder.create yes yes
folder update <fld_…> Rename or move a folder PATCH /v1/folders/{id} (--name), POST /v1/folders/{id}/move (--parent) · asset.folder.update yes yes
folder delete <fld_…> --yes Delete a folder. The media move up one level DELETE /v1/folders/{id} · asset.folder.delete yes yes

If the same content is already there, the byte stream is skipped on upload: the precheck recognizes it by its sha256 checksum. From 50 MiB on, the stream runs in 8 MiB chunks.

Scenes, versions, and layouts

Command Purpose Route and permission Key Modifies
scene list The organization’s scenes. --assignment=none finds those that no program, no schedule, and no assigned playlist points to (useful with --status=published) GET /v1/scenes · scene.list yes no
scene get <scn_…> A scene with its open findings GET /v1/scenes/{id}, GET /v1/scenes/{id}/integrity-issues · scene.read yes no
scene create --name=<name> Create an empty scene POST /v1/scenes · scene.create yes yes
scene create-from-template --template=<sct_…> --name=<name> Create a scene from a curated template POST /v1/scenes/from-template · scene.create yes yes
scene update <scn_…> Change the draft of a scene. Without --version, the command reads the version beforehand PATCH /v1/scenes/{id} · scene.update yes yes
scene publish <scn_…> Publish the draft as a new version. Names findings instead of swallowing them POST /v1/scenes/{id}/publish · scene.publish yes yes
scene recheck <scn_…> Re-check the integrity and name the findings POST /v1/scenes/{id}/integrity-issues/recheck · scene.read yes yes
scene resolve-issue <sii_…> --scene=<scn_…> --resolution=manual-fixed|ignored Close a finding as fixed or ignored POST /v1/scenes/{id}/integrity-issues/{iid}/resolve · scene.update yes yes
scene archive <scn_…> Archive a scene POST /v1/scenes/{id}/archive · scene.archive yes yes
scene restore <scn_…> Bring back an archived or deleted scene POST /v1/scenes/{id}/restore · scene.update yes yes
scene delete <scn_…> --yes Move a scene to the trash DELETE /v1/scenes/{id} · scene.delete yes yes
scene bulk-update --entries=<pfad> Change up to 50 scenes in one call POST /v1/scenes/bulk-update · scene.update yes yes
layout list The layout templates, built-in and custom GET /v1/layout-templates · layout-template.list yes no
scene-template list The curated scene templates. --orientation=landscape|portrait filters GET /v1/scene-templates · scene.read yes no
scene-version list --scene=<scn_…> The published versions of a scene GET /v1/scenes/{id}/versions · scene.read yes no
scene-version get <scv_…> --scene=<scn_…> A version with its snapshot GET /v1/scenes/{id}/versions/{vid} · scene.read yes no
scene-version diff <scv_…> --scene=<scn_…> --against=<scv_…> Compare two versions GET /v1/scenes/{id}/versions/{vid}/diff/{vid2} · scene.read yes no
scene-version revert <scv_…> --scene=<scn_…> Reset the draft to an older version. Publishes nothing POST /v1/scenes/{id}/versions/{vid}/revert · scene.publish yes yes
scene-version thumbnail <scv_…> --scene=<scn_…> Store the preview image (--file) or fetch its address POST …/versions/{vid}/thumbnail · scene.update, POST …/thumbnail-url · scene.read yes yes

The version of a scene appears twice in the response: as the field version in the body and as the header ETag. The command line reads it itself when --version is missing. For scene publish, two refusals mean different things: Scene.PublishValidationFailed (422, exit 7) is a cause to fix, and Scene.PublishBlocked (409, exit 6) means blocking findings that --ignore-issues closes.

Playlists and programs

Command Purpose Route and permission Key Modifies
playlist list The organization’s playlists GET /v1/playlists · playlist.list yes no
playlist get <pll_…> A playlist with its items GET /v1/playlists/{id} · playlist.read yes no
playlist create --name=<name> Create a playlist: --items (sequence) or --folder/--tags (rule) POST /v1/playlists · playlist.create yes yes
playlist update <pll_…> Change a playlist. --items replaces the whole sequence PATCH /v1/playlists/{id} · playlist.update yes yes
playlist delete <pll_…> --yes Delete a playlist. The API refuses assigned ones DELETE /v1/playlists/{id} · playlist.delete yes yes
playlist preview-source Resolve an automatic source on a trial basis POST /v1/playlists/source-preview · playlist.read and asset.read yes no
schedule list The organization’s programs GET /v1/schedules · schedule.list yes no
schedule get <sch_…> A program with its entries. --players names the devices that play it GET /v1/schedules/{id}, GET /v1/schedules/{id}/players · schedule.read yes no
schedule create --name=<name> Create a program. Without --base, its base is off air POST /v1/schedules · schedule.create yes yes
schedule update <sch_…> Change the name or base of a program PATCH /v1/schedules/{id} · schedule.update yes yes
schedule delete <sch_…> --yes Delete a program. The API refuses assigned ones DELETE /v1/schedules/{id} · schedule.delete yes yes
schedule create-item --schedule=<sch_…> --content=… --recurrence=… Create a program entry (once:, daily:, weekly:, monthly:) POST /v1/schedules/{id}/items · schedule.update yes yes
schedule update-item <sci_…> --schedule=<sch_…> Change a program entry, disable it (--disabled), or enable it (--enabled) PATCH /v1/schedules/{id}/items/{itemId} · schedule.update yes yes
schedule delete-item <sci_…> --schedule=<sch_…> Delete a program entry DELETE /v1/schedules/{id}/items/{itemId} · schedule.update yes yes
player get-program <ply_…> What is assigned to a display, including the override GET /v1/players/{id}/program · fleet.player.read yes no
player set-program <ply_…> --content=… Assign something to a display. --clear removes the assignment. Idempotent PUT /v1/players/{id}/program · schedule.update yes yes
display-group set-program <dgr_…> --content=… Assign something to a video wall, and with it to all of its displays. --clear removes the assignment. Idempotent PUT /v1/display-groups/{id}/program · schedule.update yes yes
player set-override <ply_…> --content=… Show something else on a display right now (--until or --indefinite) PUT /v1/players/{id}/override · schedule.update yes yes
player clear-override <ply_…> End the override of a display DELETE /v1/players/{id}/override · schedule.update yes yes

Content is passed in short form: schedule:sch_…, scene:scn_…, playlist:pll_…, asset:ast_…, and for the base of a program also pause.

Playback and widgets

Command Purpose Route and permission Key Modifies
playback now What is playing on all displays right now (play, pause, gap) GET /v1/players/now-playing · fleet.player.list yes no
playback timeline <ply_…> The resolved playback timeline of a display (window from now, 4 hours to 7 days) GET /v1/players/{id}/timeline · fleet.player.read yes no
playback history <ply_…> --date=<datum> The recorded daily history of a display (retained for 90 days) GET /v1/players/{id}/playback-history · fleet.playback-history.read no no
playback refresh <ply_…> Recompute the snapshot of a display POST /v1/players/{id}/snapshot/refresh · fleet.player.update yes yes
widget preview --widget=<pfad> Resolve a widget’s data for a preview POST /v1/widget-data/preview · scene.read yes no

Advertising

Advertisers, ad campaigns, bookings, and creatives of your own advertising business. Reading works in every package. Creating and approving additionally require the advertisingDirect capability of the package. Without it, the server answers with 403 and Billing.FeatureNotEntitled (exit 4). Ad campaigns of the ad network appear in campaign list as soon as they reach displays of your organization, without price and without the operator’s note.

Command Purpose Route and permission Key Modifies
advertiser list The advertisers, filterable by --status, --industry, and --search GET /v1/advertising/advertisers · advertising.advertiser.read yes no
advertiser get <adv_…> One advertiser with brands, contacts, and note GET /v1/advertising/advertisers/{id} · advertising.advertiser.read yes no
advertiser create --name=<name> --industry=<branche> Create an advertiser. --brand may be repeated POST /v1/advertising/advertisers · advertising.advertiser.manage yes yes
campaign list The ad campaigns with phase, period, number of bookings, and displays reached. --owner=tenant or --owner=network separates your own business from the network GET /v1/advertising/campaigns · advertising.campaign.read yes no
campaign get <acp_…> One ad campaign with phase, period, goal, and price GET /v1/advertising/campaigns/{id} · advertising.campaign.read yes no
booking list --campaign=<acp_…> The bookings of an ad campaign with spot length, frequency, and commitment GET /v1/advertising/campaigns/{id}/booking-lines · advertising.campaign.read yes no
creative list The creatives. --approval=pending gives the list awaiting review GET /v1/advertising/creatives · advertising.campaign.read, advertising.creative.manage, or advertising.creative.approve yes no
creative approve <crv_…> Approve a creative. If the industry requires a mandatory text, --text-present and --text-legible confirm that it is in the creative and legible POST /v1/advertising/creatives/{id}/approval · advertising.creative.approve yes yes

A creative is rejected in the portal, where the note for the advertiser is written. Which displays a booking reaches, and why others are not reached, is answered by GET /v1/advertising/booking-lines/{id}/reach through the escape hatch szenera api get.

Devices

Command Purpose Route and permission Key Modifies
player list The organization’s displays. --program=none finds those without content, --offline-since=P7D those that have reported nothing for that long (one that never reported counts too) GET /v1/players · fleet.player.list, plus --status, --search yes no
device list The devices: what is out in the field, and does it still check in GET /v1/devices · identity.device.list no no
device get <dev_…> One device in detail: certificate and surfaces GET /v1/devices/{id} · identity.device.list no no
device send-command <dev_…> <kind> Issue a remote maintenance command to a device (reboot, locate, tail-log, mark-good, check-ota) or to a surface (screenshot, identify, set-config, display-power, display-source, refresh-snapshot, with --screen=<n>). A 201 response means accepted, and --wait stays attached POST /v1/devices/{id}/commands, POST /v1/players/{id}/commands · fleet.player.command.issue. Surface kinds also resolve through identity.device.list. That permission is not key-capable, so only the machine kinds run with a key yes yes
device list-commands <dev_…> The latest remote maintenance commands of a device GET /v1/devices/{id}/commands · fleet.player.read yes no
device screenshot <dev_…> Request a screenshot, wait for it, and fetch it (--file) POST /v1/players/{id}/commands → GET …/commands/{cid}/output · fleet.player.command.issue, fleet.player.read, and identity.device.list. The last one is not key-capable, so this command stays reserved for sessions. Default --timeout=5m, --interval=5s no yes

Searching by serial number, releasing and blocking a device, and looking up a single command are commands of platform operations and not part of szenera. See Commands for platform operations.

To re-pair a device, reset it to factory state, remove it from the organization, or report it as lost, there is no command of its own under an organization profile. Use the Lifecycle card in the portal, or api post against POST /v1/devices/{id}/release with {"reason":"reconnect"}, "factory", or "removed", or against POST /v1/devices/{id}/block with a reason (identity.device.lifecycle, not key-capable). If a paired device reports in with a new key, POST /v1/devices/{id}/reregistration decides, with {"decision":"keep"}, "reconnect", or {"decision":"block","reason":"…"}. There is no remote maintenance command for a factory reset.

Locations

Command Purpose Route and permission Key Modifies
location list The organization’s locations. The last column counts the displays at the location GET /v1/locations · location.list, complete, without paging yes no
location get <loc_…> A location with address, time zone, position, note, and version GET /v1/locations/{id} · location.read yes no
location create --name=<name> --timezone=<IANA> Create a location. The address comes through --street, --postal-code, --city, --country, the position through --latitude/--longitude, plus --note POST /v1/locations · location.create, needs the Locations capability yes yes
location update <loc_…> Change the name, time zone, address, position, or note. --clear-address and --clear-coordinates remove the value PATCH /v1/locations/{id} · location.update yes yes
location delete <loc_…> --yes Delete an empty location. With displays attached, the API answers 409 Location.HasPlayers DELETE /v1/locations/{id} · location.delete yes yes
player assign-location <ply_…> --location=<loc_…> Attach a display to a location. A second call moves it instead of duplicating it PATCH /v1/players/{id} · fleet.player.update yes yes
player unassign-location <ply_…> Detach a display from its location. It keeps its program, settings, and license PATCH /v1/players/{id} · fleet.player.update yes yes

A location is a folder for displays: it carries no permissions and no inventory of its own, and deleting it never takes a display with it. The fields and error codes are under Locations.

Analytics

Command Purpose Route and permission Key Modifies
analytics overview The overview: per display the availability within the planned time, and above it gaps, planned hours reported on time, and plays. --location (repeatable) restricts it to locations GET /v1/analytics/overview · analytics.query.run yes no
analytics explore --measure=<kennzahl> Analyze metrics ad hoc: --measure and --by are repeatable, plus --sort, --ascending, --limit, --perspective, and --granularity. --query=<pfad> takes the complete query, including filters, as JSON POST /v1/analytics/explore · analytics.query.run yes no
analytics delivery <acp_…> The delivery of an ad campaign: per booking the commitment, what was delivered, fulfillment, pacing, forecast with range, and the finding GET /v1/analytics/campaigns/{id}/delivery · advertising.campaign.read yes no

Without --from and --to, the last seven days up to yesterday apply. Without a window, an ad campaign shows its run up to yesterday. The table gives hours instead of seconds and percent instead of share, and next to a value stands its upper bound as long as open gaps can still be reported late. Which metric can be calculated with which dimension is shown by szenera api get /v1/analytics/catalog.

Proofs

Command Purpose Route and permission Key Modifies
proof list The organization’s proofs, newest first: closings, addenda, and interim statements with number, period, ad campaign, booking, valid plays, and fulfillment. --campaign, --advertiser, --line, --kind, --from, and --to narrow the list GET /v1/analytics/proofs · analytics.proof.read yes no
proof show <prf_…> One proof with check code, signature, and its files including checksum. --json shows the figures, the addenda, and the status of each delivery GET /v1/analytics/proofs/{id} · analytics.proof.read yes no
proof download <prf_…> --output=<pfad> Fetch a file: --kind=pdf (default), csv, manifest, or capture with --file=<pfi_…>. If the checksum does not match, the file is removed again GET /v1/analytics/proofs/{id}/files/{kind} · analytics.proof.read yes no

With the number and check code from proof show, anyone can verify a proof on the verification page, even without an account. Interim statements and links for advertisers are created in the portal or through the API.

Event targets

Command Purpose Route and permission Key Modifies
webhook list The organization’s event targets. --status=dead shows those that delivery itself gave up on (disabled and with an error chain longer than twenty) GET /v1/webhooks · webhook.list no no

A target that was switched off by hand is under --status=disabled and is something different. Targets are created and changed in the portal or through the API. See Create a webhook endpoint.

Team, roles, and grants

Command Purpose Route and permission Key Modifies
user list The organization’s members. --last-login-before=<zeitpunkt mit Zone> finds dormant accounts, including ones that never signed in GET /v1/users · identity.user.list no no
user get <usr_…> One member in detail GET /v1/users/{id} · identity.user.read no no
user create --email=… --name=… --role=<rol_…> Create a member directly (without an invitation), with --password or --federated POST /v1/users · identity.user.create no yes
user update <usr_…> Change a member’s profile PATCH /v1/users/{id} · identity.user.update no yes
user set-role <usr_…> --role=<rol_…> --reason=… Set the role of a member. It replaces the previous one PATCH /v1/users/{id}/roles · identity.user.assign-roles no yes
user suspend <usr_…> --reason=… Suspend a member POST /v1/users/{id}/suspend · identity.user.suspend no yes
user reactivate <usr_…> Lift the suspension of a member POST /v1/users/{id}/reactivate · identity.user.reactivate no yes
user delete <usr_…> --reason=<kategorie> --yes Delete a member. The reason is one of the API’s five categories DELETE /v1/users/{id} · identity.user.delete no yes
invitation list The organization’s invitations, with --pending only the open ones GET /v1/invitations · identity.invitation.list no no
invitation create --email=… --role=<rol_…> Invite someone to the organization POST /v1/invitations · identity.user.invite no yes
invitation resend <ivt_…> Send an invitation again. That extends the deadline POST /v1/invitations/{id}/resend · identity.user.invite no yes
invitation revoke <ivt_…> Withdraw an invitation DELETE /v1/invitations/{id} · identity.invitation.revoke no yes
role list The organization’s roles, custom and built-in GET /v1/roles · access.role.list no no
role get <rol_…> A role with its permissions GET /v1/roles/{id} · access.role.read no no
role create --name=… --permissions=<a,b,c> Create a role. Permissions are exact catalog keys, not wildcards POST /v1/roles · access.role.create no yes
role update <rol_…> Change a role. --permissions replaces the list, If-Match comes from the version, and a conflict is exit 6 PATCH /v1/roles/{id} · access.role.update no yes
role delete <rol_…> --yes Delete a role. With accounts attached, the API refuses DELETE /v1/roles/{id} · access.role.delete no yes
grant list Permissions attached to individual resources GET /v1/grants · access.grant.list no no
grant create --user=<usr_…> --resource-type=… --resource=… --permissions=… Give a permission on exactly one resource, or block it with --deny POST /v1/grants · access.grant.create no yes
grant revoke <grn_…> Withdraw a grant DELETE /v1/grants/{id} · access.grant.revoke no yes

Keys

Command Purpose Route and permission Key Modifies
api-key list Your own access keys, with --organization all keys of the organization GET /v1/me/api-keys (session only), with --organization GET /v1/api-keys · identity.api-key.list no no
api-key issue --name=… --permissions=<a,b,c> Issue a key. The secret value appears exactly once. --list-allowed shows the permissions that are allowed POST /v1/me/api-keys · identity.api-key.create no yes
api-key rotate <akm_…> Renew a key. The old one stays valid for a grace period (0–72 hours) POST /v1/me/api-keys/{id}/rotate · identity.api-key.create no yes
api-key revoke <akm_…> --yes Revoke a key, immediately and permanently. --compromised records in the log the suspicion that the secret value fell into the wrong hands DELETE /v1/me/api-keys/{id} · identity.api-key.revoke no yes

A key can never do more than its issuer, and it can never carry a permission that is not allowed for keys. The CLI checks the second condition before the call.

Package, invoices, and apps

Command Purpose Route and permission Key Modifies
subscription get The package and the licensing status of your own organization GET /v1/me/subscription · billing.subscription.read, GET /v1/me/licensing · billing.usage.read no no
subscription set-licenses --count=<n> Change the number of booked licenses, but not below the number in use PUT /v1/me/licensing/licenses · billing.subscription.update no yes
subscription cancel --yes Cancel the contract: at the end of the period, or immediately with --immediately POST /v1/me/subscription/cancel · billing.subscription.update no yes
subscription reactivate Withdraw a cancellation that is already scheduled POST /v1/me/subscription/reactivate · billing.subscription.update no yes
app subscribe <app> Book a priced app for billing POST /v1/me/licensing/apps/{appId} · billing.subscription.update no yes
app unsubscribe <app> --yes Cancel a booked app, effective at the end of the period DELETE /v1/me/licensing/apps/{appId} · billing.subscription.update no yes
invoice list Your own invoices GET /v1/me/invoices · billing.invoice.read no no
invoice get <inv_…> An invoice with its line items. --pdf fetches the address of the PDF GET /v1/me/invoices/{id} · billing.invoice.download no no
app list The apps in the store, with --installed only the installed ones GET /v1/me/apps/store, no permission of its own yes no
app get <app> One app in detail: permissions, data access, widgets GET /v1/me/apps/store/{appId}, no permission of its own, session only no no
app install <app> Install an app. The manifest hash travels along as proof GET /v1/me/apps/store/{appId} → POST /v1/marketplace/apps/{appId}/install · marketplace.app.install no yes
app upgrade <app> --version=<semver> Switch an installed app to a different version POST /v1/marketplace/apps/{appId}/upgrade · marketplace.app.upgrade no yes
app uninstall <app> Preview the consequences first, then uninstall with --yes POST …/uninstall/preview → POST /v1/marketplace/apps/{appId}/uninstall · marketplace.app.uninstall no yes
app accept <app> Accept the update of an app. The command shows where the update leads and what it adds. --yes accepts it GET /v1/me/apps/{appId}/update → POST /v1/me/apps/{appId}/update/accept · marketplace.app.accept no yes
app reject <app> --yes Reject the update of an app. Until a higher version appears, the platform does not ask again. If a deadline applies, rejecting works only until it passes GET /v1/me/apps/{appId}/update → POST /v1/me/apps/{appId}/update/reject · marketplace.app.accept no yes

Log, permission catalog, and escape hatch

Command Purpose Route and permission Key Modifies
audit list Read the audit log: append-only, payloads redacted GET /v1/audit · audit.read or audit.read.self (then only your own operations) no no
audit get <aud_…> One log entry with its payload GET /v1/audit/{id} · audit.read or audit.read.self no no
permission catalog The permission catalog as the running environment knows it, with --key-eligible the allowlist GET /v1/permission-catalog, sign-in only n/a no
api get <path> A GET on any path of the API the route of the path and its permission per route no
api post <path> <body> A POST on any path, plus --idempotency-key=<schluessel> the route of the path and its permission per route yes
api put <path> <body> A PUT on any path, plus --idempotency-key=<schluessel> the route of the path and its permission per route yes
api patch <path> <body> A PATCH on any path, plus --idempotency-key=<schluessel> the route of the path and its permission per route yes
api delete <path> [body] A DELETE on any path, plus --idempotency-key=<schluessel> the route of the path and its permission per route yes

api … is the escape hatch to every route that has no command of its own. The path begins with a slash and may carry a query. The body is JSON directly or @datei.json. This way also goes through the generated client, so headers, trace ID, and error kinds apply as everywhere, but it does not check the response against a contract: no one knows which schema belongs to a freely typed path.

szenera api get "/v1/devices?limit=5" --json | jq -r '.items[].id'
szenera api post /v1/playlists @playlist.json --idempotency-key=import-2026-09-08-01