The first CLI deploy of an existing function moves it to CLI management, which turns off the web editor, rollback from the dashboard and the Assistant for it. sinch functions deploy now says so before packaging. Interactively it asks to continue (default: yes), and declining deploys nothing. With --non-interactive, CI, --json or no terminal, it prints the notice and deploys; --json includes it in warnings.
- No notice for a new function, a function already managed from the CLI, or a deploy with
SINCH_CLIENT=ai-builder. - A function deployed from the CLI before this change may show the notice once more.
- Warnings about the recorded function and the notice are no longer dropped from
--jsonwarningswhen validation runs.
sinch functions versions lists a function's versions, and sinch functions rollback <version> restores an earlier version's code as a new version. <version> is the number versions shows or the version's id.
- Rollback restores code only, not environment variables or database data. It confirms first when it can prompt, waits for the build (
--no-waitskips that), and refuses a version whose build failed with exit code103. - Rollback doesn't change
sinch.json. Runsinch functions downloadto pull the restored code; a deploy from the old copy is refused as stale until you do. - Errors from the API now show the API's detail in the CLI's message.
sinch functions deploy now updates the function recorded in sinch.json by its id, and sends the recorded versionId as the base version. If the function changed since your copy was taken, deploy asks before overwriting it, or exits with code 103 when it can't ask (--non-interactive, CI, --json). A copied folder deployed under a new name creates that function instead of touching the original, with a warning that the recorded function wasn't used.
--overwritedeploys without the base-version check.--forcedoes not skip it.--message <text>(-m) saves a note on the new version.- Deploy records
versionIdinsinch.json, and includes it in--jsonoutput. - A deploy under a different
--nameno longer overwritesfunctionIdinsinch.json. Before, a preview deploy moved the project to the preview function.
sinch functions download records the live version's versionId in sinch.json, and fails without leaving files behind when the function's configuration can't be fetched. sinch functions list shows a Display Name column and sinch functions status prints the display name.
Released 2026-10-19.
sinch functions deploy now sends a filled .env or appsettings.json value as a secret when its name looks like a credential. Before, every filled value was sent as plain configuration and showed in the dashboard. The function reads both kinds from its environment as before, and deploy's list of variables marks these (secret). See Configuration and secrets.
A name looks like a credential when its last word is KEY, KEYS, APIKEY, SECRET, SECRETS, TOKEN, PASSWORD, PASSWD, PASS, PWD, PASSPHRASE, CREDENTIAL or CREDENTIALS, and none of its words is PUBLIC or PUBLISHABLE. Names are split into words on non-alphanumeric characters and where a lowercase letter is followed by an uppercase one. An all-caps run is not split.
- Sent as secrets:
OPENAI_API_KEY,GITHUB_TOKEN,SMTP_PASS. - Kept plain:
MAX_TOKENS,TOKEN_URL,AWS_ACCESS_KEY_ID,PUBLIC_KEY,OpenAIKey, and a filledPROJECT_ID_API_KEYorVOICE_APPLICATION_KEY.
For C#, only top-level appsettings.json keys count. Because the file also ships inside the package, deploy warns with the key names (not under --json) and points you to dotnet user-secrets.
A value that has deployed as a secret stays a secret, so renaming the key is the only way to make it plain again. sinch functions download treats it like any other secret: it is blank in .env, with an offer to fetch its value into your keychain. If you decline, or the run cannot prompt, a later deploy from that folder warns and leaves the key out of the function.
The offer to install the Sinch developer skills now asks This project only (followed by the folder's path), Globally (all projects) or Skip, instead of yes or no for a global install.
- After
sinch auth login, the project choice shows only when the current folder has asinch.json. sinch functions initandsinch functions downloadmake the offer at the end, for the folder they created.- Skip is saved as
skipSkillsPromptin~/.sinch/config.jsonand stops the offer everywhere.sinch skills installstill installs the skills later. --json,--non-interactiveand runs with no terminal never ask.
A project install writes .agents, .claude and skills-lock.json, so sinch functions deploy now leaves files and folders with those names out of the package, anywhere in the function folder.
sinch functions logs -n <N> now returns at most N entries (the API caps it at 500). Before, the CLI sent a parameter the API never read, so -n had no effect. Without -n the API still returns up to 100 entries, and the help text now says 100 (it said 50). -n now rejects anything that is not a positive whole number, with exit 64. With --follow it is still checked but has no effect.
After a login retry, sinch functions list, download <function-id>, delete, logs, storage and db, and sinch templates list and show, now exit when the retried command finishes. Before, if you ran one of them logged out (or with stored credentials that no longer work) and logged in at the prompt, it did its work and then kept spinning until Ctrl+C. logs --follow still streams until Ctrl+C.
sinch functions docs --updateno longer fails every time with a.find is not a functionerror. It looks up the function named after the current folder on every page of the function list.- Download errors from
sinch functions download,storage downloadanddb download, and from the template download insinch functions init, now show the API's message when the error has one, instead ofRequest failed with status code N. Exit codes and message prefixes are unchanged.
Released 2026-10-08.
The interactive voice picker now offers "Create a new one" first, and it is the default whenever the project has services; picking an existing service is opt-in. Non-interactive runs are unchanged.
- A service or number that init creates is saved in
sinch.jsonascreatedResources, with the name of the function init created it for. A picked service, or one passed with--voice-service-id, is never recorded. - A
sinch functions deployof that function sends them, so deleting the function releases them. Deploy removes each one fromsinch.jsononce the API reports it as recorded for the function. - A deploy under another name (
--name) does not send them. If the API does not record them, they stay insinch.jsonand the next deploy sends them again.
If the API rejects a deploy because another function already records one of these resources as created, the error names that function and says to remove createdResources from sinch.json. A failed deploy now prints "Failed to deploy function:" once instead of twice.
When TRACEPARENT (W3C trace context, version 00) is set, every Functions API request forwards it unchanged, together with TRACESTATE, and the run's telemetry uses that trace id. SINCH_CLIENT and SINCH_BUILDER_SESSION_ID are sent as the X-Sinch-Client and X-Sinch-Builder-Session headers; they label diagnostics only, and invalid values are dropped. AI Builder sets these so each deploy is filed under its builder session. Without them the CLI behaves as before.
Released 2026-10-05.
Breaking for scripts: a project's sinch.json can no longer set projectId, apiUrl, oauthUrl, keyId, or any credential or oauth* field; those values are ignored. If a folder's sinch.json names a different project than your active profile, commands now use the profile's project. To target another project, run sinch config profile use <name> (only auth login and config get|set|list honor the --profile flag; see Configuration). In CI, set SINCH_KEY_ID, SINCH_KEY_SECRET and SINCH_PROJECT_ID together. functions download no longer writes projectId. Folders downloaded earlier still work when your active profile is on the project they came from.
Released 2026-09-30.
Voice templates now offer to create a Voice v2 service and, after showing the price and asking, rent a US LOCAL number linked to it. VOICE_SERVICE_ID and VOICE_FROM_NUMBER go into .env. New flags: --create-voice-service, --rent-number <region>, --area-code <digits>, --force (required to rent when non-interactive) and --json. New voice projects get accessKey: "managed" in sinch.json.
These commands now accept --json. Each prints one JSON document on stdout and never prompts. Where confirmation is needed and neither --force nor --non-interactive is given, --json fails with an error document naming --force and exits 66. voice v1 conferences kick-all (which also takes --yes), functions download (to overwrite), storage delete, the sinch sip delete commands, auth logout and config profile delete take only --force as confirmation.
sinch functions delete,download,validate,db download|upload,storage list|upload|download|deletesinch conversationdelete and stop commands (apps, contacts, conversations, messages, templates, webhooks), andsinch sipdelete commands (acls, ACL IP ranges, endpoints, trunks) andsip trunks acls remove.conversation conversations stopandconversation messages deletegain--force, and a confirmation step they did not have before (see below).sinch config(all subcommands;config profile deletegains--force),sinch secrets add|get|delete|clear(secrets listalready had--json),sinch skills,sinch env initsinch auth status|login|logout,sinch health.auth loginneeds--credentials-fileunder--json, andauth logoutgains--force.sinch numbers order resume
sinch functions logs (one JSON object per line with --follow), sinch fax download and sinch upgrade also gain --json. sinch voice v1 conferences kick-all already accepted --json. It gains -f, --force, and --yes still works.
Under --json, missing or rejected credentials now print { "error": "..." } on stdout and exit 100 or 101, with no login prompt.
Breaking for scripts: with no terminal and no -f, --force, the sinch sip delete commands (acls, ACL IP ranges, endpoints, trunks) and sip trunks acls remove now exit 66 and change nothing. Before, they printed "Deletion cancelled" or "Operation cancelled" and exited 0.
conversation conversations stop and conversation messages delete now ask for confirmation. With no terminal and neither -f, --force nor --non-interactive, they exit 66 and do nothing. Before, they ran without asking.
Breaking for scripts: sinch auth status now exits 101 (AUTH_FAILED) when no credentials are configured, with and without --json. It used to exit 0. A script or CI step that ran it and treated exit 0 as success now sees a failure. With --json it prints { "authenticated": false }.
Credentials that exist but are rejected, for example a wrong SINCH_KEY_SECRET, still exit 0. With --json the output has "authenticated": true and "tokenValid": false, so a CI check should read tokenValid rather than the exit code alone.
Breaking for scripts: every --json list is now an object with one named array key, which leaves room for pagination fields later. A script that indexed the array directly reads the key instead, for example jq '.[0]' becomes jq '.faxes[0]'.
| Command | Before | Now |
|---|---|---|
sinch fax list --json | [...] | { "faxes": [...] } |
sinch fax services list --json | [...] | { "services": [...] } |
sinch fax services numbers <service-id> --json | [...] | { "numbers": [...] } |
sinch fax emails list --json | [...] | { "emails": [...] } |
sinch fax emails numbers <email> --json | [...] | { "numbers": [...] } |
sinch fax cover-pages list --json | [...] | { "coverPages": [...] } |
sinch fax send --json (with and without --wait) | [...] | { "faxes": [...] } |
sinch numbers active list --json | [...] | { "activeNumbers": [...] } |
sinch numbers order list --json | [...], or text if empty | { "orders": [...] } |
sinch voice calls list --json | [...] | { "calls": [...] } |
sinch voice services list --json | [...] | { "services": [...] } |
Commands that already printed an object (conversation, sip, porting, templates, secrets, functions list) are unchanged.
- A failed API call exits with a code that follows its HTTP status: 401 exits 100, 403 exits 77, 404 exits 102, 409 exits 103, and 429 or 5xx exits 69. CI/CD lists every code.
-a, --app-keyworks on every Voice v1 command. Onvoice v1 applications numbers listit filters the listed numbers instead.voice calls createandvoice calls bridgegain--service-id.functions initremoves the half-created directory when stopped with Ctrl+C, and exits 130.- New
sinch conversation apps updatecommand. It sends only the fields you pass. sinch conversation apps createno longer fails with HTTP 400 because it sent an empty body.sinch functions devpoints the Voice and Conversation webhooks back at their deployed targets when it stops.



