Unreleased
What has changed?
Zoho CRM Read File and Custom API Call only send the token to the connection’s Zoho CRM hosts
Read File used to send the connection’s Zoho access token to whatever URL it was given, including hosts outside Zoho. From Zoho CRM 0.4.0 it only fetcheshttps URLs on the connection’s own Zoho API host under /crm/ (for example https://www.zohoapis.com/crm/bulk/v8/read/<job>/result), or on that data centre’s download hosts (for example https://download-accl.zoho.com/v2/crm/... for a data backup). Custom Zoho function URLs (/crm/.../functions/...) and URLs in another data centre are refused. Any other URL fails before a request is made. Redirects are followed only to those same hosts; a redirect anywhere else stops the download before that host is requested. The file is streamed, so the deployment’s file size limit (AP_MAX_FILE_SIZE_MB) applies.
Custom API Call keeps working with paths such as /Leads and with full URLs on the connection’s own API host (for example https://www.zohoapis.com/crm/v8/...). A full URL on any other host, including other Zoho hosts, now fails before a request is made instead of receiving the token.
What you need to do
Nothing if your Read File steps point at Zoho CRM backup, bulk-read or API file URLs of the connected account, and your Custom API Call steps use a path or a URL on the connection’s API host. If a step calls any other URL, replace it with the HTTP piece’s Send HTTP Request action. Steps keep running on the version they were built with until you upgrade them.Instagram for Business no longer reports success when a reel fails to publish
Publishing a reel uploads the video to Instagram and then waits for Instagram to finish processing it before the post goes live. The piece used to give up after about a hundred seconds and return the booleanfalse, which the flow recorded as a successful step. Anything downstream carried on with false where a media id was expected, and nothing in the run said the post had not been published.
Upload Reel now throws when Instagram reports an error, and waits up to five minutes, which is the window Instagram’s own guidance describes. Upload Photo waits for the same signal instead of publishing blind, so a container Instagram rejects now surfaces as a failed step rather than a confusing error from the next call.
The piece also moves from Graph API v17.0, which expired on 12 September 2025, to v23.0.
What you need to do
If a flow branches on the output of Upload Reel beingfalse, that branch will no longer be taken — the step fails instead. Handle the failure with the step’s error handling options, or with a branch on the run status.
Reconnect your Instagram connections. The piece now requests the permissions needed for comments, insights, content management, direct messages and Page metadata, and a token issued before this release does not carry them. Steps that were saved earlier will also ask you to select the Page again, because messaging needs the Facebook Page id that the Page dropdown now stores.
The AI provider config endpoint is removed
GET /v1/ai-providers/:provider/config returned a provider’s decrypted credentials so that an AI step running inside the engine could build the model itself and call the provider directly. AI steps no longer work that way: the worker resolves the credentials and makes the call, which is what lets Activepieces charge managed AI on what the call actually cost. Nothing in the product calls the endpoint any more, and it now returns 404.
The route only ever accepted an engine token, so it was never reachable with a user token, an API key or from the browser. GET /v1/ai-providers and GET /v1/ai-providers/:provider/models are unchanged.
What you need to do
Nothing on a normal upgrade. Every flow is moved to the AI piece version that runs on the worker the first time its version is read, before it can run. If you serve pieces from your own registry, make sure it carries the AI piece at0.11.0 or later. A flow left on an earlier version would still try to fetch its provider credentials over this endpoint and fail.
AI steps are billed on what each call costs, not on a fixed price per model
The managed Activepieces AI provider used to charge a fixed number of credits per model per step, taken from a table calibrated at roughly a thousand tokens per call. A short call was charged about right; a long one was charged the same as a short one while costing us many times more. Every managed AI call is now billed on the dollar cost the provider reports for that call, converted atAP_AI_CREDIT_USD_VALUE (default 0.0005, so one credit is a twentieth of a cent of model spend). A call on your own API key is billed a flat one credit per model call. Tool calls stay at one credit each.
This changes what the same flow costs in both directions. A short prompt on an expensive model gets much cheaper; a long document through Extract Structured Data gets dearer. The credit cost shown in the model picker and in the credits breakdown is gone, because there is no longer a fixed number to show.
A step or a chat turn on your own API key costs the same as it did: one credit, plus one per tool call. An agent still counts as one credit however many times it goes back to the model.
What you need to do
Nothing to configure. Self-hosters who want a different conversion rate can setAP_AI_CREDIT_USD_VALUE to the dollar value of one credit.
AI steps now consume credits on your own API key too
POST /v1/ai/execute refuses to start an AI step when the platform is out of credits, whatever provider the step uses. Previously only the managed Activepieces provider was gated, so a platform that had exhausted its credits kept running AI steps as long as they used its own key.
Credits are only enforced where a billing provider is configured, so a Community self-host is unaffected.
What you need to do
Nothing, unless you run AI steps on your own provider key on a platform that sits at zero credits. Those steps now fail with a credits error instead of running. Top up, or raise the plan’s credit allowance.Files passed to an AI step are capped at AP_MAX_FILE_SIZE_MB
Extract Structured Data and Generate Image used to read file inputs straight from the flow’s memory, so no Activepieces-side size limit applied. Those files are now stored and fetched by the worker that runs the model, which puts them under the same per-file limit as every other file the engine writes: AP_MAX_FILE_SIZE_MB, 25 MB by default.
The limit is per file, not per step, so several large files in one step are fine as long as each is under it. On Activepieces Cloud the limit is 10 MB and is not configurable.
What you need to do
Nothing unless an AI step handles files larger than 25 MB. Those steps now fail with a size error naming the limit. RaiseAP_MAX_FILE_SIZE_MB on a self-hosted installation if you need more.
Applying a release or a project replace now updates changed connection references
Applying a release (Environments / Git Sync) or running Project Replace used to keep whatever connection the destination step already pointed at. A step whose connection changed in the source silently kept the old one, and the connection the release created for it stayed unreferenced with statusMISSING. Two things change:
- A changed connection reference is now a change the diff sees, so a flow whose only edit is its connection is applied instead of being reported as unchanged.
- The destination’s connection is kept only when the incoming step carries no connection of its own, and only when the step is still the same piece. Swapping a step to a different piece no longer grafts the old piece’s connection onto it.
MISSING connection for someone to authorize there.
What you need to do
Nothing on upgrade if your source project is the source of truth for connections, which is the intended model. If instead you deliberately re-point a step in the destination project at a different connection than the source uses, that re-point is now overwritten on the next apply. Either point the source at the connection you want, or clear the connection on the source step so the destination wiring is preserved.Seven actions are no longer offered to agents
The Pinterest piece advertised its six original actions to AI agents asaudience: 'both', but they identify boards and Pins through dynamic dropdowns that an agent has no way to drive. They are now human, alongside the Trello add_card_attachment action, whose only input is a file an agent cannot produce.
An agent that currently holds one of these tools stops seeing it. Every one has a replacement among the new agent actions that takes plain IDs instead: Create Pin from Media, Create New Board, Update Board Details, Delete Pin by ID, Search Boards, Search Pins, and Add Card Attachment from URL.
The flow builder is unaffected. All seven actions keep working exactly as before for human users, and no saved step changes.
What you need to do
Nothing for flows. If you have an agent configured with one of the seven actions above, point it at the corresponding agent action listed there. MCP clients should refresh their tool list.Pinterest Update Board can no longer clear a description
Update Board and its agent twin Update Board Details treat a blank or whitespace-only description as “keep the current one”, matching the help text the field always carried. Previously a blank description was sent to Pinterest and wiped the board’s description on every run. Clearing a description from this action is therefore no longer possible; that is the intended reading. A call that supplies only a blank description now fails with “At least one field (name, description, or privacy) must be provided to update the board.” instead of silently doing nothing.What you need to do
Nothing unless a flow or an agent relied on a blank description to clear a board’s description, which previously happened on every run whether or not it was intended. Clear it from Pinterest directly.WhatsApp Business’ Send Message and Send Media return the API response instead of the HTTP envelope
The WhatsApp Business piece returned two different shapes depending on which action you used.Send Template Message returned the WhatsApp Cloud API payload directly, while Send Message and Send Media returned the whole HTTP response, so the same payload sat one level down under body, alongside status and headers.
Both actions now return the API payload directly, matching Send Template Message and every other action in the piece. A step that produced
v23.0, via a single WHATSAPP_API_BASE constant. It previously split between v17.0 (expired September 2025) and v20.0 (expires 24 September 2026).
What you need to do
Update any step that reads the output ofSend Message or Send Media. Drop the body. prefix: {{step.body.messages[0].id}} becomes {{step.messages[0].id}}. Steps that only send and ignore the output need no change, and no connection has to be re-authorised.
0.91.0
What has changed?
WhatsScale media actions take a file input, capping media at the instance file-size limit
The 17 WhatsScale actions that send media — image, video, document and audio sends across the contact, group, channel and CRM-contact variants, plus the image and video Status posts — used to take a plain text URL and hand it straight to WhatsScale, which fetched it itself. Those fields are now file inputs: the engine resolves whatever you pass (a URL, or a file from a previous step) into a file, stores it on your instance, and gives WhatsScale that copy to fetch. The field keys are unchanged (imageUrl, videoUrl, documentUrl, audioUrl), so existing flows keep their configured value and a stored URL still works. Two behaviour changes come with the new path:
- Media is now capped by
AP_MAX_FILE_SIZE_MB— 10 MB on Cloud, 25 MB by default self-hosted. The file travels through your instance instead of going vendor-to-vendor, so a URL pointing at something larger than that limit now fails where it previously sent. This mostly affects video and document sends. Streaming does not lift the ceiling: writing into storage is counted against the cap either way, and producing a URL for WhatsScale to fetch requires writing into storage. See Limits. - The URL WhatsScale fetches is now one your instance serves. It is a signed, expiring link on your public API URL. An instance that is not reachable from the internet cannot hand WhatsScale a URL it can fetch, so media sends need a publicly resolvable
AP_FRONTEND_URLon self-hosted installs.
What you need to do
Nothing if your media is comfortably under the cap and your instance is reachable from the internet. On Cloud that cap is 10 MB, so check any flow that forwards video or large documents. If you send files larger than the cap on a self-hosted install, raiseAP_MAX_FILE_SIZE_MB to cover the largest media you send and redeploy. On Cloud the 10 MB cap is not configurable. If your instance is not publicly reachable, keep media sends on a host that is, or leave these actions unused; there is no way for WhatsScale to fetch a file from a private address.
WhatsScale “Add a Tag to a CRM Contact” now takes a list of tags
The two add-tag actions (“Add Tags to a CRM Contact” and its By-ID twin) accepted a single tag in a text field namedtag. They now accept a list, in a field named tags, and send one request per tag so existing tags are kept.
Because the field was renamed, a step configured before this release loses its tag value and shows “Tags” as an empty required field. The field could not keep its old name: a stored single string does not validate as a list.
Adding several tags is not atomic — each tag is its own request, so a failure part-way through leaves the earlier tags applied. Re-running is safe: adding a tag a contact already has converges on the same set.
What you need to do
Re-enter the tag on any flow that uses either add-tag action, as a list entry rather than free text. The removal actions are unchanged and still take one tag at a time.A custom AI provider is now checked when you save it
The custom OpenAI-compatible provider accepted any text as its base URL and as its API key header name. A config that cannot be used saved without complaint and then failed on every run that used it, with a message from the HTTP layer rather than from Activepieces: a header name ofauthorization: bearer produced “Headers.append: is an invalid header name”, and a base URL that will not parse produced “Invalid URL”.
Saving now fails with a message naming the field to fix. Nothing changes for a provider whose config already works, and no stored config is altered or re-checked in place.
What you need to do
Nothing, unless you have a custom AI provider whose base URL or API key header is malformed. Those already fail at run time. The next time you save that provider you will be told which field is wrong: enter the header name on its own, such asAuthorization, with its value in the API key field, and give the base URL in full including the scheme, such as https://api.example.com/v1.
Agent steps on Activepieces AI credits are limited to the models Activepieces offers
The managed Activepieces AI provider used to accept any model id a flow named, because it serves the OpenRouter catalogue unfiltered and nothing checked the value server-side. The model picker only ever offered the three chat tiers, but the API tookmodelName as free text, so a flow, a saved agent, or a direct call to POST /v1/agents/runs could run any model OpenRouter publishes on Activepieces’ own key.
An agent step, saved agent, or agent run that names a model outside the offered list now fails with a VALIDATION error that lists the models available to it, instead of running a model nobody selected. Bring-your-own keys are unaffected: an OpenRouter, OpenAI, Anthropic, or custom provider key can still name any model it pays for.
What you need to do
Nothing, if your agent steps use the model picker. If a flow, a saved agent, or an API call names a model id directly while running on Activepieces AI credits, switch it to one of the offered models or to your own provider key. The error message lists the available ids.The legacy product-embed connection-key and app-credential endpoints are removed
The original product-embed flow is gone. It let a host application store per-project OAuth client credentials and a public key, then mint an app connection by presenting a token signed with the matching private key. These endpoints are removed:GET,POSTandDELETE/v1/connection-keys/app-connectionsGET,POSTandDELETE/v1/connection-keysGET,POSTandDELETE/v1/app-credentials
404.
The current embedding stack is unaffected: signing keys, managed authentication, JWT user provisioning and the embed SDK are a separate feature and continue to work unchanged.
What you need to do
Nothing for a self-hosted installation, and no environment variable or migration. Theapp_credential and connection_key tables are left in place by this release and are simply no longer read; a later release drops them.
If you call one of the endpoints above against Activepieces Cloud, move to the current embedding flow, which provisions users and connections through a platform signing key. See Embedding.
Kimai connections now authenticate with an API token instead of a username and API password
Kimai is deprecating its legacyX-AUTH-USER / X-AUTH-TOKEN authentication (API passwords), with removal planned no later than July 2026 — see Kimai’s announcement. The Kimai piece’s connection now sends Authorization: Bearer <token> instead, matching Kimai’s current API. This also fixes the Activity dropdown on the Create Timesheet action, which ignored the selected project because it tried to filter on a GET request body that the piece’s HTTP client cannot send.
The connection’s Username and API Password fields are removed and replaced with a single API Token field.
What you need to do
Only if you have an existing Kimai connection. Reconnect it: in your Kimai instance, generate an API token from your user profile’s “API Access” page, then re-enter your Kimai connection in Activepieces with the Server URL and that token. Existing connections using the old username/API-password fields will fail to authenticate until reconnected.Worker group runs no longer fall back to shared workers
Runs for a project assigned to a worker group used to fall back to the shared queue whenever the group had no online workers, so shared workers would execute them. Runs now always stay on the group’s dedicated queue (project-<group-name>-jobs) and wait there until a worker carrying the matching AP_WORKER_GROUP_ID connects — shared workers never pick them up.
What you need to do
If you assign projects to worker groups, keep at least one worker online per assigned group. If a group is down, reassign the project to another group or unassign it (set itsworkerGroupId to null) — any assignment change moves the project’s waiting runs to the new queue.
Airtable’s Find Record returns up to 1000 matches and the Record picker lists up to 500 records
Find Record used to return only the first page Airtable sent back, 100 records, and silently dropped the rest. It now follows Airtable’s paging and returns up to 1000 matching records. The Record dropdown on Get Record by ID listed the first 50 records of a table; it now lists up to 500. Update Record and Clean Record now sendtypecast: true, as Create Record always has. Airtable then converts text into the field’s type instead of rejecting it: a date typed as text is parsed, a select value that does not exist yet is created as a new option, and a linked-record name is resolved to the record. Before, those requests failed with INVALID_VALUE_FOR_COLUMN.
What you need to do
Nothing to configure or migrate. Check any Update Record or Clean Record step that writes to a single-select or multiple-select field: a value that used to fail because the option did not exist now creates that option in Airtable. Review flows that loop over Find Record’s output or count its rows: a search that matched more than 100 records now returns more rows than before, and each extra page is one more request against Airtable’s limit of 5 requests per second per base.0.90.4
What has changed?
Telemetry moves from AP_TELEMETRY_ENABLED to the platform admin UI
Product analytics used to be governed only by the AP_TELEMETRY_ENABLED environment variable, read once when the app started. It is now a per-platform setting stored in the database, editable at Platform → Infrastructure → Configurations.
Upgrading does not change what you collect. Each platform’s setting is created the first time it is read, taking AP_TELEMETRY_ENABLED as its value, so an instance running with AP_TELEMETRY_ENABLED=false stays opted out — on an existing install and on a brand-new one alike.
After a platform’s setting exists, the environment variable no longer governs it. Editing the variable has no effect on that platform, and switching the toggle on in the UI turns product analytics on even if the variable still reads false.
The setting is per platform, so on an instance hosting several platforms each one is controlled separately. The page is hidden on Activepieces Cloud.
What you need to do
Nothing, if you want to keep collecting what you collect today, and nothing if you rely onAP_TELEMETRY_ENABLED=false — that value is carried into each platform’s setting as it is created. What changes is that the variable becomes a starting value rather than a permanent lock: once a platform has a setting, an admin can switch product analytics on from the UI regardless of what the variable says. If that matters to you, restrict who holds platform-admin rights.
0.90.1
What has changed?
AWS connections using the IAM Role / OIDC method are now verified against AWS before they save
Saving an AWS connection (Bedrock, S3, Secrets Manager) with the IAM Role / OIDC method previously only checked that the Role ARN was well formed, so any well-formed ARN saved with status “Connected” even when the role did not exist or could not be assumed. The connection now performs the samests:AssumeRoleWithWebIdentity call the flow makes at runtime, and the save fails with the AWS error when the role cannot be assumed.
Two consequences. A connection that was accepted before is now rejected if its IAM OIDC provider, trust policy, or AP_FRONTEND_URL issuer is not set up correctly. And because the save now calls AWS, an instance with no outbound access to sts.<region>.amazonaws.com cannot create these connections at all.
The region on these connections is also validated against the AWS region format at both save time and every flow step (the region flows into the STS endpoint hostname, so the check is enforced everywhere it is used). The STS call now times out after 10 seconds instead of waiting for the job timeout.
What you need to do
Only if you use the IAM Role / OIDC method on an AWS piece. Allow outbound HTTPS tosts.<region>.amazonaws.com from the machine running the worker, and make sure AP_FRONTEND_URL matches the Provider URL of your IAM OIDC identity provider, since the issuer in the signed token is derived from it. Existing saved connections keep working and are not revalidated automatically — pressing Recheck on a connection whose trust policy is wrong will now move it to an error state, which reflects what already happens when a flow runs.
0.90.0
What has changed?
Front’s Attachments field takes files instead of URLs
The Front piece’s Send Message, Send Reply, Create Draft and Create Draft Reply actions describedAttachments as a list of attachment URLs and sent those strings inside a JSON body. Front only accepts attachments on a multipart/form-data request, as the bytes of the file, so it took the message and dropped the attachments — HTTP 202, no error, no attachment. The field is now a list of files, the same shape the Gmail and Discord pieces use, and the request is sent as multipart when a message carries attachments.
A URL is still all you need to supply: the engine downloads it and hands the piece the resolved file. A step that already holds a file — an earlier download, a trigger’s attachment — can be wired straight in. An entry whose file cannot be resolved is skipped rather than failing the send.
What you need to do
Re-pick the attachment in any Front step that used the field. The stored value is a plain string and the field now holds a file, so it does not carry across. A flow that never set Attachments is unaffected and keeps its JSON request path. Nothing to configure on the server, and no new environment variable.A file URL that fails to download is no longer treated as a file
Any piece property that takes a file also accepts a URL, and the engine buffered whatever came back from that URL without checking the response status. A 4xx or 5xx produced a file named after the URL whose contents were the server’s error page, and a piece could not tell that apart from the real thing — an expired signed link became an email with the storage provider’s XML error attached. A failed download now fails the step, which is what the streaming path already did.What you need to do
Nothing to configure. A flow that was silently passing on error pages will start failing at that step instead, and the fix is the URL itself — usually a link that has expired or that the instance is not authorized to read.Signing in with an emailed code is now offered on Activepieces Cloud only
POST /v1/authentication/otp/request and POST /v1/authentication/otp/verify are no longer served on a self-hosted
instance. They return 404, and the sign-in card no longer offers the “email me a code” step — it opens on the
password form instead. Versions 0.88.2 through 0.89.0 did serve them on any edition with SMTP configured.
POST /v1/authentication/complete-sign-up is unaffected and still served everywhere.
A six-digit code is a million possibilities, so what keeps guessing it expensive is the captcha in front of the
request endpoint. Cloudflare Turnstile is opt-in and unset out of the box, so a self-hosted instance served both
endpoints with nothing in front of them. Rather than require a Cloudflare account to make a sign-in method safe,
that method is no longer served where the captcha is not there.
On Cloud the same rule now applies: the routes exist only when both AP_TURNSTILE_SITE_KEY and
AP_TURNSTILE_SECRET_KEY are set. Without them the instance starts normally and simply does not offer emailed
codes. Activepieces Cloud has both configured, so nothing changes for it — the code step stays on the sign-in card
and accounts that use it keep signing in exactly as before.
What you need to do
Nothing, if your users sign in with a password or with Google — those paths are unchanged, and so are/sign-up,
/sign-in and /switch-platform.
If you ran 0.88.2–0.89.0 with SMTP configured, assume some accounts were created through the code flow. Those
accounts hold a random password nobody was ever shown, so removing the code flow removes the only way they could
sign in. There is no reliable marker for them in the database — a verified code deletes its otp row — so treat any
EMAIL-provider account whose owner cannot recall setting a password as one of them.
On Enterprise, send those users through Forgot password once to set a password; that flow needs the same SMTP
you already have configured.
On Community there is no way back in the product. Password reset lives in the enterprise module, which Community
does not register, so POST /v1/authn/local/reset-password is not served — and nothing else writes a password on any
edition, as there is no change-password endpoint. Do not be misled by the first half of that flow appearing to work:
POST /v1/otp is served on Community and answers 204, but Community sends no OTP email of any type except a
login code, so no reset mail ever arrives. Set a password for each affected account directly —
UPDATE user_identity SET password = '<bcrypt hash>' WHERE email = '…' — and hand it to its owner over a channel you
trust, since they cannot change it themselves afterwards. Do this before you upgrade if you can, so nobody is
locked out in between.
If you script or test the sign-in page, note that the emailed-code step is gone and the two endpoints above
answer 404.
A failed run on a synchronous webhook answers with 500 instead of 408 after the full timeout
A/sync webhook call whose flow run fails used to hold the connection open for the whole AP_WEBHOOK_TIMEOUT_SECONDS (30 seconds by default) and then answer 408 Request Timeout with an empty body, no matter how quickly the run had actually failed. Nothing reported a terminal run status back to the waiting request, so the caller only ever saw the timeout fallback.
A run that ends in FAILED, INTERNAL_ERROR, TIMEOUT, MEMORY_LIMIT_EXCEEDED or LOG_SIZE_EXCEEDED now answers immediately with 500 and a body of {"message": "The flow has failed and there is no response returned"}. For FAILED, INTERNAL_ERROR and MEMORY_LIMIT_EXCEEDED this restores the behaviour from before 0.80.0, where they answered 500 (TIMEOUT answered 504 then; it is 500 now, like the rest). LOG_SIZE_EXCEEDED never had a response of its own in any earlier release, so it gains one here.
Between 0.80.0 and 0.85.x the same failures answered 204 No Content rather than 408, which many HTTP clients read as success. If you integrated against an Activepieces in that range and concluded a synchronous webhook “returns 204 when it fails”, that is the behaviour being replaced.
Two cases are deliberately unchanged. A run that succeeds without reaching a Return Response step still waits out the timeout and answers 408, exactly as it did before 0.80.0. A run blocked on credits still answers 402 before it starts.
What you need to do
Nothing to configure or migrate. If you have a caller or reverse proxy that treats408 as the signal for a failed synchronous flow, or retry logic keyed on 408, switch it to 5xx — a failed run no longer produces a 408, and the reply now arrives in seconds rather than after the timeout.
0.89.0
What has changed?
Piece builds fail when piece code uses __dirname without declaring bundleForkedEntries
The piece bundler now emits files a piece loads by path at runtime (for example a child_process.fork target) beside the main bundle, when they are declared in a bundleForkedEntries array in the piece’s package.json, and it keeps dependencies that only those files import in the published manifest. Because an undeclared __dirname-relative file access always breaks after publishing — this is exactly how @activepieces/piece-oracle-database 0.1.11/0.1.12 shipped with every new connection failing — the build now fails loudly when a piece’s source references __dirname and declares no forked entries. Previously such a piece built successfully and shipped broken.
What you need to do
Nothing for catalog pieces — oracle-database is the only piece that forks a sibling file, and this change fixes it (0.1.13). If you build custom pieces and one references__dirname, either declare the runtime-loaded file in bundleForkedEntries (see Bundling Pieces) or remove the __dirname usage. Already-published pieces keep working; the check runs at build time only.
A new workspace is named after the company in the sign-up email
Completing sign-up used to always name the new platform after the person, as"Ahmad's Platform". It now reads the email domain first: [email protected] creates a platform called Activepieces, and the project alongside it becomes Activepieces's Project.
The person-based name is still what you get from a consumer address. [email protected] continues to produce "Ahmad's Platform", as do the other common providers (Outlook, Yahoo, iCloud, Proton, GMX, QQ and similar). Whether an address counts as a work address is decided by a denylist of consumer providers, so anything not on that list is treated as a company.
This only affects platforms created from here on. Existing platforms keep their names, and renaming stays available in settings.
What you need to do
Nothing. No configuration, no new environment variable, and nothing to migrate. If you script or test first-run sign-up and assert on the generated platform or project name, update that assertion: a work-domain address no longer yields"<FirstName>'s Platform".
Workers no longer pre-warm the flow cache on startup by default
Since 0.86.2 every worker pre-filled its local piece and code cache on startup by resolving and compiling every enabled flow on the platform. That warm-up costs memory and CPU proportional to the number of enabled flows: on instances with many flows it pinned each worker at its CPU limit for the duration and spiked memory enough to OOM-kill small workers, especially during upgrades when all workers restart at once. The warm-up is now opt-in behind the newAP_PREWARM_CACHE_ON_STARTUP worker environment variable, which defaults to false. When disabled, caches fill lazily on each flow’s first run after a worker starts, exactly as they did before 0.86.2.
What you need to do
Nothing, unless you want to keep the warm-up behaviour of 0.86.2 through 0.88.4. SetAP_PREWARM_CACHE_ON_STARTUP=true on your worker containers to restore it — recommended only if your instance has a modest number of enabled flows and your workers have memory headroom. See Environment Variables for details.
The Microsoft Teams Bot piece no longer needs a server-side installation record
POST /v1/teams-bot/webhook and POST /v1/teams-bot/send are removed, and the teams_bot_installation table is dropped. The webhook existed only to capture Microsoft’s per-tenant serviceUrl at install time so the send endpoint could look it up.
The piece now posts to Microsoft’s documented global Teams service endpoint directly, so it holds no server-side state and its messaging endpoint moves to the shared app-webhooks route, /api/v1/app-events/microsoft-teams-bot. Because the installed-or-not check is no longer a cached row, it is answered by Microsoft at send time: posting to a team the bot is not a member of now fails with 403 The bot is not part of the conversation roster instead of a stale local lookup.
The piece is published as 0.1.0 with a minimum supported release of 0.88.4, so releases below 0.88.4 keep being offered 0.0.2, which still has the server route it depends on.
What you need to do
Nothing for existing connections; they keep working untouched, and sending no longer reads the dropped table. If you already have a flow using Microsoft Teams Bot piece version0.0.2, open the step and upgrade the piece to 0.1.0. Flow steps pin an exact piece version, so an existing step stays on 0.0.2 after you upgrade, and 0.0.2 calls the /v1/teams-bot/send route this release removes. That step will fail with a 404 until it is upgraded.
Optionally repoint the Messaging endpoint on your Azure Bot resource from /api/v1/teams-bot/webhook to /api/v1/app-events/microsoft-teams-bot; an endpoint left on the old path returns 404 and is otherwise harmless. If you call /v1/teams-bot/send directly from your own code, switch to the piece’s Send Channel Message as Bot action.
Brevo’s Create or Update Contact stops clearing blacklist flags and attributes it was not given
Four changes to the Brevo (formerly Sendinblue) piece’s Create or Update Contact action alter what an existing, unchanged step does. The action used to strip every falsy value from the request before sending it, soEmail Blacklisted and SMS Blacklisted could be switched on but never switched back off — the false was dropped and the contact stayed blacklisted with no error. Those flags are now sent when you set them, and neither checkbox defaults to off any more, so a checkbox you never touched is omitted from the request instead of quietly un-blacklisting the contact on every run.
The Attributes field used to come pre-filled with nine empty values (FIRST_NAME, LAST_NAME, SMS, CIV, DOB, ADDRESS, ZIP_CODE, CITY, AREA). Because they were sent on every call, running the step overwrote whatever those attributes held in Brevo with empty strings. The default is removed, and only the attributes you list are written.
List IDs was a free-text list of numbers and is now a dropdown of the lists in your account. A stored numeric id is still sent exactly as before, so existing steps keep working unchanged.
The SMTP Blacklist Sender checkbox is replaced by a Blocked Sender Addresses list. Brevo expects a list of sender email addresses here, not a true or false, and rejects a boolean outright with “Invalid smtpBlacklistSender format” — so ticking that checkbox always failed the step, and leaving it clear did nothing at all. The field never worked. It is now a list of addresses, which Brevo accepts, and any value your step already had is ignored rather than sent.
What you need to do
Nothing to configure or migrate, and no existing step stops working. Review any flow whose Create or Update Contact step relied on the old behaviour: a step that was silently wiping attributes will now leave them intact, and a step you were relying on to blacklist contacts must have the checkbox explicitly ticked. To block a sender for a contact, list that sender’s address inBlocked Sender Addresses — it must be an active sender in your Brevo account, or Brevo answers “One of the sender is invalid or inactive”.
A Run Agent step whose turn dies now fails its flow run
A Run Agent step whose turn died — no AI provider configured for the chosen vendor, a revoked API key, a model the provider no longer serves — used to report success. The step returned the failed agent result rather than raising it, so the step read SUCCEEDED, the run completed SUCCEEDED, and later steps acted on a payload that carried the failure inside it. Such a run is now FAILED, and the agent’s error message is the step’s error. Two cases are deliberately unaffected, because the agent did produce usable output:- A turn that finished but had a single tool call error. The agent may have recovered from it and reported on it, so those runs keep succeeding exactly as before.
- A turn that was cut short by the output limit or the run’s usage budget. It still returns the work it completed, and the flow still continues.
What you need to do
Nothing to configure or migrate, and no new environment variable. Two things to check if either applies to you. If a flow relied on continuing past a dead agent step, tick Continue on failure on that step — it now takes effect, where previously the step never failed for it to apply to. If a flow branches on the agent result (a Router reading the step’sstatus), that branch no longer runs when the turn dies, because the step raises instead of returning; move that handling onto the step’s failure path.
If you alert on run status, expect agent flows that were silently completing on a misconfigured provider to start showing as failed. That is the misconfiguration surfacing, not new breakage.
AP_FLOW_TIMEOUT_SECONDS now also bounds a single action run
An action run — an agent’s configured piece tool, a chat action, or MCP ap_run_action — used to be capped at a hardcoded 120 seconds, and a flow run started as an MCP tool at a hardcoded 300 seconds. Neither could be changed. Any agent tool whose action took longer than a minute failed outright with RPC [executePieceTool] failed (timeout: 60000ms), because a second hardcoded limit in the worker cut it off first.
Both hardcoded limits are gone. All of them now follow AP_FLOW_TIMEOUT_SECONDS, the same setting that bounds a flow run, which defaults to 600 seconds. An action run therefore gets the same budget as a flow step.
The limit going up is the change to be aware of: a slow or hung action now occupies a worker slot for up to AP_FLOW_TIMEOUT_SECONDS instead of 120 seconds, and action runs are not covered by the per-project concurrency limiter. On a small worker pool, several slow actions can hold execution capacity for longer than they used to.
What you need to do
Nothing to configure or migrate, and no new environment variable — a default installation gets the fix with no action. Two things to consider if they apply to you. If you raisedAP_FLOW_TIMEOUT_SECONDS for long flows, note that agent tools, chat actions and MCP action runs now inherit that same ceiling; lower it if you do not want them held that long. If you put Activepieces behind a reverse proxy and use MCP ap_run_action, an action that runs past the proxy’s read timeout (nginx defaults to 60 seconds, Cloudflare to 100) returns a gateway error to the MCP client while the action keeps running — raise proxy_read_timeout if you rely on long action runs over MCP.
Sign-up addresses are checked with ZeroBounce instead of a bundled blocklist
The bundled list of disposable-email domains introduced in 0.88.2 is gone. Sign-up now asks ZeroBounce about the address, on every password sign-up and on the emailed-code path only when the address has no account yet, and refuses it when ZeroBounce reports it as disposable, a spam trap, abusive, or on a global suppression list. The refusal is silent, so the response looks the same as a successful one. When ZeroBounce cannot be reached, or the key is invalid or out of credits, the address is let through and the reason is logged. The check runs only whenAP_ZEROBOUNCE_API_KEY is set. AP_ALLOW_DISPOSABLE_EMAILS is removed; the key is the switch. An instance without a key accepts throwaway addresses again, as it did before 0.88.2.
What you need to do
Nothing, unless you relied on the 0.88.2 blocklist to keep throwaway addresses out. To keep refusing them, create a ZeroBounce account and setAP_ZEROBOUNCE_API_KEY on the app container. Remove AP_ALLOW_DISPOSABLE_EMAILS from your configuration if you set it; it is ignored. See Environment Variables.
0.88.2
What has changed?
The container no longer bundles PM2 — crashes exit the container
The Docker image used to run the app and worker under PM2, which restarted a crashed process inside the container. PM2 is removed; the entrypoint now launches the processes with plainnode. When a process crashes (or is OOM-killed), the container exits instead of silently recycling the process in place, and your orchestrator restarts it.
What you need to do
Nothing if you deploy with Docker Compose, Kubernetes/Helm, or any orchestrator that already restarts failed containers (all official deployments do). If you run the image with a baredocker run and relied on PM2 to keep the container alive across process crashes, add a restart policy: docker run --restart unless-stopped ....
Table record filters compare date columns chronologically
Thegt, gte, lt and lte operators on GET /v1/records used to parse every cell value as a number. On a Date column that meant 2026-08-12T14:30:00Z was read as 2026, so two dates in the same year always compared equal and a range filter matched nothing. Those four operators now compare Date and Date & Time columns as instants.
This affects the Tables piece’s Find Records action and any direct API call that filters a Date column with a range operator. eq, neq and co are unchanged and still compare the stored text exactly, so two spellings of the same instant (...T14:30:00Z and ...T14:30:00.000Z) do not match each other.
What you need to do
Nothing on upgrade. Re-check any flow or API integration that filters a Date column withgt, gte, lt or lte — it now returns the rows the filter actually describes, which may be more or fewer than before.
Official piece bundles are served from npm again by default
AP_USE_CDN_FOR_BUNDLES goes back to defaulting to false, reversing the change in 0.87.0. Official piece bundles are downloaded from registry.npmjs.org instead of cdn.activepieces.com. When the flag is switched on, the CDN serves the repackaged, self-contained tarballs from https://cdn.activepieces.com/pieces/bundled/. The same release stops mirroring bundles into your own S3 bucket: a bundle that was copied there is no longer served from it, and every download goes to npm or the CDN.
What you need to do
If your network policy restricts outbound traffic, allowregistry.npmjs.org: it is the default source, and it stays the fallback for any bundle the CDN does not have even when AP_USE_CDN_FOR_BUNDLES=true. Set the flag to true to prefer the CDN, and allow cdn.activepieces.com as well in that case. Otherwise nothing.
MCP OAuth: revoking a token requires a client identity, and registration issues a usable secret
Two changes to the MCP OAuth endpoints:POST /revokeused to revoke a refresh token for a caller that presented no client identity at all, so anyone who learned a refresh token could disconnect its owner. It now requires the request to identify the client, and a confidential client to authenticate, per RFC 7009. A revocation that sends onlytokennow returns400 invalid_client.- Dynamic client registration (
POST /register) that omitstoken_endpoint_auth_methodnow records the client asclient_secret_basicand issues a client secret, per RFC 7591. It previously issued a secret but recorded the client as public, so that secret was never checked. A client registered from now on must present it when calling/tokenand/revoke. Concretely: a client that omitstoken_endpoint_auth_methodand discards theclient_secretit is handed now gets400 invalid_clientat/token, where it previously succeeded. Such a client must either store and send that secret, or register explicitly withtoken_endpoint_auth_method: "none"to stay public.
What you need to do
Nothing for already-connected clients. A client’s authentication method is read from the row it registered with, so existing registrations are untouched, including the ones created before this fix that hold a secret while recorded as public. Those keep working whether or not they send it. Claude, Cursor and anything else built on the MCP SDK are unaffected: the SDK stores and sends theclient_secret it is given, and it never calls the revocation endpoint. A confidential client’s secret is accepted from either the request body or the Authorization: Basic header, so a client is never rejected for choosing one over the other.
If you maintain your own MCP OAuth client, check two things before upgrading: that it sends client_id when it revokes a token, and that it stores and presents the client_secret that /register returns. Note that disconnecting and re-adding an MCP server creates a fresh registration, so an existing user meets the new behaviour when they reconnect rather than at upgrade.
Disposable email addresses can no longer sign up
Sign-up now refuses addresses from throwaway providers such asmailinator.com and guerrillamail.com, on both the emailed-code flow and the password form. Federated sign-in (Google, SAML, JWT), managed authentication and SCIM provisioning are unaffected, since those addresses come from an identity provider you already trust.
What you need to do
Only if your members sign up with addresses from a disposable email provider. On 0.88.2 through 0.88.4, setAP_ALLOW_DISPOSABLE_EMAILS=true to keep accepting them.
Superseded in 0.89.0: the bundled blocklist was replaced by a ZeroBounce check that runs only when
AP_ZEROBOUNCE_API_KEY is set, and AP_ALLOW_DISPOSABLE_EMAILS is no longer read. See the 0.89.0 entry.Sign-in and sign-up are one screen, and an emailed code signs people in wherever SMTP is configured
/sign-in and /sign-up now render the same card, and /sign-up redirects to /sign-in carrying its query string, so existing links — invitation URLs included — keep working.
The card’s primary path is a six-digit code emailed to the address typed into it. It is offered whenever the instance has SMTP configured and email auth is enabled, on every edition including Community, so a self-hosted instance that already sends transactional email gains a way to sign in that needs no password. An instance with no SMTP is unaffected: the card opens directly on the classic password form, with Google and SAML above it exactly as before.
Two things change on an instance that does have SMTP. Password sign-in moves behind a Use password link on the card, and password sign-up is offered only where the card is in sign-up mode — the first account on a fresh instance, or an invitation link (/sign-up?email=…) — so someone who simply opens /sign-in on an instance that already has accounts is given the emailed code and no way to switch to a password sign-up form. Existing passwords are untouched: a verified identity keeps its password, and signing in with a code does not discard it.
Who may get in does not change, and the existing guards all run before a code is sent. Joining still requires AP_ALLOW_OPEN_SIGN_UP=true, an accepted invitation, or existing membership, and that refusal is silent — the response is identical to an accepted one and no code is sent, so the endpoint reveals nothing about who has an account. A platform’s allowed-domains list still applies too, but it answers with an explicit domain-not-allowed error rather than silently, and like the platform’s Email-auth setting it is inert on Community and on any platform whose plan does not include SSO. On a fresh install, before the first platform exists, there is no platform for either check to run against and both are skipped.
What you need to do
Nothing to configure or migrate, and no new environment variable: emailed-code sign-in turns itself on once SMTP is configured and Email is enabled as an authentication method. If you do not want emailed-code sign-in, turn off Email as an authentication method for the platform (Enterprise and Cloud, under SSO settings, and only where your plan includes SSO); that disables password sign-in along with it, since both are the same method. On Community that toggle is inert, so the only lever there is leaving SMTP unconfigured. If you script or end-to-end test the sign-in screen, re-check it: the same URL now renders a different form depending on whether SMTP is configured and whether any account exists yet. Password reset moved inside the card wherever the emailed-code path is active; an instance without SMTP still sends people to/forget-password, and Community shows no reset control at all.
Emailed sign-in codes allow ten wrong guesses per account per hour
The six-digit login code already allowed five wrong guesses, but that budget lived on the code itself, and the fifth wrong guess threw the code away — so asking for a new code handed out five fresh guesses immediately, with no ceiling on how often that could repeat. A six-digit code is only a million possibilities, so unlimited retries reduce it to a matter of hours. Wrong guesses are now counted per account over a rolling hour, independently of how many codes get sent. Entering the right code clears the counter, so someone who fumbles a few digits and then succeeds is unaffected. Two consequences worth knowing. Someone who spends ten wrong guesses on an account within an hour cannot sign in with an emailed code until the hour is up; password and Google sign-in are unaffected. And because the counter is keyed on the account rather than the caller, anyone who knows an address can spend that budget on the owner’s behalf — a temporary nuisance for the owner, and the trade the cap is worth making.What you need to do
Nothing. The limit applies out of the box and needs no configuration. If your support team sees a report of “the code keeps saying it’s wrong”, have them check whether the account has burned its hourly budget, and point the user at password or Google sign-in in the meantime.One-time codes are no longer stored in a readable form
Theotp table used to hold the six-digit sign-in code as plain text, so anyone who could read the database — a replica, a backup, a support query — could sign in as any account for the ten minutes that code was alive, without a password. Codes are now stored as a digest keyed with a server-held secret, so reading the table no longer yields anything you can sign in with. The code itself is held only long enough to re-send it if the person asks for it again.
A code found to be expired is thrown away when it is next presented, rather than sitting in the table until the same person happens to request another one.
What you need to do
Nothing, and no new configuration: the key is derived from a secret your instance already has. Codes written by an older build are recorded as such and keep working until they expire, so a sign-in already underway when you deploy still completes, an email verification link still opens, and a rolling deploy where both builds are serving at once behaves the same. Rolling back costs at most the codes issued after the deploy: the older build cannot read those, so whoever holds one asks for a fresh code. Nothing is rewritten and nothing is deleted, so no cleanup is needed either way.0.88.0
What has changed?
Agent steps move from the flow engine to the server
An agent step used to run its loop inside the engine, holding a worker for as long as the agent took. It now pauses the flow, runs on the server, and resumes when the agent finishes. This upgrade rewrites every existing agent step to the new version. The step’s inputs and its output shape are unchanged, so anything reading the step’s result or its structured output keeps working. Sub-flow, MCP server, knowledge base and piece action tools all run on the new path. Two differences are worth knowing before you upgrade:- Web search is no longer a step setting. It follows what the platform has configured rather than a per-step toggle. A step that had it switched on keeps working; the stored value is ignored.
- Max steps is honoured up to a ceiling. The value you set still applies, but the server caps a single run at 50 turns. A step configured above that runs 50.
What you need to do
Nothing on upgrade. Check any agent step that relied on the per-step web search toggle, or that set max steps above 50, since those now follow the platform and the server ceiling.0.87.0
What has changed?
Plans and credits are now managed by our billing service
Two license-key endpoints are removed:GET /v1/license-keys/:licenseKey and POST /v1/license-keys/verify. Applying a key is now POST /v1/platform-billing/activate.
Four feature flags no longer appear in GET /v1/flags: SHOW_BILLING_PAGE, CAN_BUY_ACTIVE_FLOWS, CAN_BUY_AI_CREDITS and SHOW_BILLING_LIMITS_ON_SIDEBAR. Whether the billing page appears is now decided from the edition and plan instead.
Enterprise instances without a license key are placed on the free plan
An Enterprise-edition instance with no license key previously ran with no credit enforcement. It is now enrolled on the free plan, so credit limits apply to it. Entering your license key restores your contracted limits.Running out of credits now stops production flow runs
When a platform has no credits left, new production runs are recorded with theQUOTA_EXCEEDED status instead of executing, and synchronous webhooks respond with HTTP 402. Such a run keeps its trigger payload, so it can be retried once credits are available. Test runs are unaffected.
The AI piece offers only the named model tiers for Activepieces-provided AI
In the AI piece, picking the Activepieces-provided AI now lists only the named tiers (Fast, Expert, Heavy) rather than the full upstream model catalogue. Existing steps keep running on the model they already have, but that model no longer appears in the dropdown, so re-saving the step moves it onto one of the tiers.Do you need to take action?
- Only if you run the Enterprise edition without a license key. Enter your key so your contracted limits apply instead of the free plan’s.
- Only if you call
GET /v1/license-keys/:licenseKeyorPOST /v1/license-keys/verify. Both are removed — usePOST /v1/platform-billing/activateinstead. - Only if you read
SHOW_BILLING_PAGE,CAN_BUY_ACTIVE_FLOWS,CAN_BUY_AI_CREDITSorSHOW_BILLING_LIMITS_ON_SIDEBARfromGET /v1/flags. They no longer exist. - Only if a flow uses Activepieces-provided AI on a model outside the Fast/Expert/Heavy tiers. Choose a tier the next time you edit that step.
- No database action is required. The migration only adds columns and leaves the existing ones in place.
Official piece bundles are served from the Activepieces CDN by default
AP_USE_CDN_FOR_BUNDLES now defaults to true. When an official piece bundle is not already cached in your own S3 bucket, the engine is redirected to cdn.activepieces.com for the tarball instead of registry.npmjs.org. If the CDN does not have that piece version, the download falls back to npm automatically, so installs keep working either way. Custom pieces and pieces from a private registry never use the CDN and are unaffected.
Do you need to take action?
- Only if your network policy restricts outbound traffic. Allow
cdn.activepieces.com, or setAP_USE_CDN_FOR_BUNDLES=falseto keep serving official bundles from npm.
Reverted in 0.88.2:
AP_USE_CDN_FOR_BUNDLES defaults to false again, so official bundles are served from npm by default. Set it to true to opt back into the CDN. The S3 cache mentioned above was removed in the same release.0.86.0
What has changed?
Log fields are now grouped by entity
Log fields are now grouped under the entity they belong to, so each thing has one name. A flow run id isflowRun.id (it used to appear as runId, flowRunId, or a bare id), and other ids follow the same shape (flow.id, project.id, job.id, …). Errors are logged under error. This only changes how logs look — nothing about the API, database, or flows changes.
Google SSO is configured via environment variables only
“Sign in with Google” can no longer be enabled from the SSO page in the admin panel — that setting has been removed. It is now controlled solely by theAP_GOOGLE_CLIENT_ID and AP_GOOGLE_CLIENT_SECRET environment variables. The button only appears when both are set (and the platform’s Google auth toggle is enabled).
Pieces are now self-contained bundles
Each piece is now built into a single self-contained bundle — its own code, the Activepieces framework, and its third-party dependencies are inlined into one artifact, so the engine provisions a piece by downloading one file instead of installing a dependency tree at runtime. As part of this, the shared libraries (@activepieces/shared, @activepieces/pieces-framework, @activepieces/pieces-common, @activepieces/core-*) are no longer published to npm, and pieces import only from @activepieces/pieces-framework (which re-exports the foundation symbols that used to come from @activepieces/shared). Built-in pieces are unaffected — this only matters for custom pieces.
AP_PRE_WARM_CACHE removed
The AP_PRE_WARM_CACHE environment variable no longer exists. It used to make a worker install pieces into its cache on startup. The worker is now its own sandbox and fills its cache lazily on first use, so the flag has no effect and setting it does nothing. Cache warmth now comes from running long-lived worker replicas rather than an up-front install step.
The up-front install is no longer needed because piece installs are now fast: each piece is a self-contained bundle fetched as a single file. If you have S3 enabled, official piece bundles are cached to your S3 bucket on first use and served from there via signed links — so when your bucket is co-located in the same region as your workers, subsequent installs are a low-latency download from a nearby object store instead of a registry round-trip.
Removed in 0.88.2: bundles are no longer mirrored into your S3 bucket. Every download goes to npm or, with
AP_USE_CDN_FOR_BUNDLES=true, to the CDN.Do you need to take action?
- Only if you set up Google SSO from the admin panel. Move your Google OAuth2 credentials into the
AP_GOOGLE_CLIENT_IDandAP_GOOGLE_CLIENT_SECRETenvironment variables. - Only if you build dashboards or alerts on Activepieces logs. Update them to the new grouped names, e.g.
runId→flowRun.idanderr→error. - Only if you maintain custom pieces (in a fork or built outside the repo). Migrate each one to the bundle model — run
npm run cli -- pieces migrate <piece-name>(or--all), or follow the migration guide. Pieces that still import@activepieces/sharedor depend on the now-unpublished libraries will fail to build. - Only if your deployment sets
AP_PRE_WARM_CACHE. Remove it from your environment — it is no longer read. Nothing else is required.
0.85.4
What has changed?
Observability: OpenTelemetry replaced with evlog
Logging moved from pino + OpenTelemetry to evlog. Logs are now one rich event per request/job instead of many small lines, so the JSON shape changed. Traces and metrics are no longer exported. OpenTelemetry tracing produced a huge volume of low-value spans — far more data (and cost) than it was worth — so we dropped it in favour of these wide events, which carry the same context in one place.AP_OTEL_ENABLED=true now sends logs only, over OTLP.
New optional env vars: AP_LOG_SAMPLE_RATE_INFO (percent of info logs to keep, default 100) and AP_LOG_KEEP_SLOW_MS (always keep requests slower than this, default 2000). Drain settings (AP_AXIOM_*, AP_BETTERSTACK_*, AP_LOKI_*, AP_HYPERDX_TOKEN) are unchanged.
Action: only if you ingest Activepieces telemetry — update log dashboards to the new shape, and move any trace- or metric-based monitoring to logs.
Referencing step outputs
Previously if you had a step called step_1 you would had to reference it “step_1[‘the_property_you_want’]” but now you must reference it as “step_1[‘output’][‘the_property_you_want’]”, there is already a migration that will take care of this for you, but if you must abide by this new syntax if you are writing/editing step references manually not through the builder. You can now also reference the step error via “step_1[‘error’]”, these changes come with the error handling feature. Also step names there were shown on hover in the builder are now removed, you can right click the step and copy its reference instead.Enforcing same version of docker image on both worker and app servers
Previously if your worker was on a different version of your app server, the worker would work fine most of the time, but because some changes we do will require both of them to be on the same version we added this safeguard.0.84.0
What has changed?
Flow Run Log Size Enforcement
This is an important behavior change in how flow run logs are stored and capped, but no action is required — the existing default (AP_MAX_FLOW_RUN_LOG_SIZE_MB=50) is preserved.
- Large step outputs are now offloaded to object storage instead of sitting inline in worker memory, controlled by the new
AP_FLOW_RUN_LOG_SLICE_THRESHOLD_KBenv var (default32). - Large step input values are replaced with a
(truncated, original size <N>)placeholder in the log via the newAP_FLOW_RUN_LOG_INPUT_TRUNCATE_THRESHOLD_KBenv var (default2). The step still receives the full value at runtime. - Runs whose combined step inputs and outputs exceed
AP_MAX_FLOW_RUN_LOG_SIZE_MBnow terminate with the newLOG_SIZE_EXCEEDEDstatus instead of silently trimming inputs. Offloaded outputs still count their original size against the cap. - See Limits → Files & flow run logs for the full behavior, environment variables, and defaults.
- Embedding now requires setting allowed embed origins, which means only the domains listed in the field can embed the app (wildcards are supported). There is also a new env variable
AP_ALLOWED_EMBED_ORIGINSfor setting pre-allowed origins, and a new endpoint for adding these origins — check docs. - “Sign in with Google” can no longer be enabled from the SSO page in the admin panel — that setting has been removed. It is now controlled solely by the
AP_GOOGLE_CLIENT_IDandAP_GOOGLE_CLIENT_SECRETenvironment variables. The button only appears when both are set (and the platform’s Google auth toggle is enabled).
Do you need to take action?
- Embedding — if you are embedding your self-hosted activepieces somewhere make sure it’s on the allow list
- Only if you set up Google SSO from the admin panel. Move your Google OAuth2 credentials into the
AP_GOOGLE_CLIENT_IDandAP_GOOGLE_CLIENT_SECRETenvironment variables.
0.83.0
What has changed?
When creating a project now, the platform owner email doesn’t automatically get added to the alert recievers list of the project, you can manually assign it in the UI/API, when creating a project.0.82.0
What has changed?
Piece Versions Are Now Pinned
- Piece versions are no longer stored with wildcards (
~1.2.0,^1.2.0). All piece steps now use exact versions (e.g.1.2.0). - A migration automatically strips wildcard prefixes from all existing flow versions on upgrade.
- The
LOCK_AND_PUBLISHoperation no longer resolves piece versions at publish time — steps run with the exact version stored in the flow. - A new version switcher UI in the builder lets users upgrade or downgrade piece versions manually.
REST API
ADD_ACTION,UPDATE_ACTION, andUPDATE_TRIGGERnow strip wildcard prefixes (~,^) frompieceVersionbefore saving. If you were relying on wildcard versions to auto-resolve on publish, your steps will now be pinned to the base version (e.g.~1.2.0becomes1.2.0).LOCK_AND_PUBLISHno longer modifiespieceVersionon any step. The version in the draft is the version that will run.- A new endpoint
GET /v1/pieces/:name/versionsis available to list all versions of a piece, useful for building custom version selection.
Concurrent Jobs Env Var Renamed
AP_MAX_CONCURRENT_JOBS_PER_PROJECT→AP_DEFAULT_CONCURRENT_JOBS_LIMIT. Default drops from100to5.
Outbound HTTP is SSRF-filtered
- Server-side HTTP (OAuth, Vault, Conjur, event destinations, on-call pager, MCP validator) now blocks private, loopback, and cloud-metadata IPs. Reach internal hosts by adding their IP/CIDR to
AP_SSRF_ALLOW_LIST.
Do you need to take action?
- Pinned piece versions — if you create or update flows via the REST API with wildcard versions (
~or^), switch to exact versions; wildcards are silently stripped. If your publish flow relied onLOCK_AND_PUBLISHresolving wildcards, set the exact version on each step before publishing. UseGET /v1/pieces/:name/versionsto list available versions. - Concurrent jobs — rename
AP_MAX_CONCURRENT_JOBS_PER_PROJECTtoAP_DEFAULT_CONCURRENT_JOBS_LIMIT. To keep the old cap, setAP_DEFAULT_CONCURRENT_JOBS_LIMIT=100. - SSRF filter — if you self-host Vault, Conjur, an OAuth2 token endpoint, or any internal webhook on a private IP, set
AP_SSRF_ALLOW_LIST(comma-separated IPs or CIDRs, e.g.10.0.5.12,192.168.10.0/24) before upgrading.
0.80.0
What has changed?
Infrastructure
- A new environment variable
AP_MAX_WEBHOOK_PAYLOAD_SIZE_MBhas been introduced to control the maximum allowed webhook payload size. The default is25MB. Webhooks exceeding this limit will be rejected with a413 Request Too Longresponse. - Nginx has been removed from the Docker image. Fastify now serves both the API and the React frontend directly. All API routes are now under the
/apiprefix natively. If you were using/v1/healthas a health check endpoint (e.g. in Kubernetes probes or load balancer checks), update it to/api/v1/health. - Secret managers has been refactored, the version in 0.79.0 no longer is supported, it was not used by anyone but it’s worth to mention to upgrade to 0.80.0 before considering using the feature
API
- A new
UPDATE_SAMPLE_DATA_INFOflow operation has been introduced to handle sample data updates independently. UPDATE_ACTIONandUPDATE_TRIGGERno longer accept or apply changes tosampleDatain step settings. AnysampleDatafields sent in these requests will be ignored and the existing sample data will be preserved.- A new required
lastUpdatedDatefield has been added to all actions and triggers, tracked automatically by the server. It is not accepted inUPDATE_ACTIONorUPDATE_TRIGGERrequests.
Do you need to take action?
- If you want to restrict webhook payload sizes below the new
25MB default, setAP_MAX_WEBHOOK_PAYLOAD_SIZE_MBto your desired limit. - If you are using the API to update sample data on steps via
UPDATE_ACTIONorUPDATE_TRIGGER, switch to the newUPDATE_SAMPLE_DATA_INFOoperation instead. - If you have custom health checks pointing to
/v1/health, update them to/api/v1/health.
0.78.1
What has changed?
- The Platform
Operatorrole can now edit all projects.
Do you need to take action?
- Only if you want to restrict Operators from having editor access to every project. Review your Operator permissions as needed.
0.78.0
What has changed?
- The
usageCountfield has been removed from both the template API responses and the database—it’s no longer available. - The Todos feature is now deprecated and will not be supported going forward.
Do you need to take action?
- If you’re using the Todos feature, update your flows to use the new approvals channels available from the approvals tab in the piece selector.
0.77.0
What has changed?
- For Embed Plan users: the “Use a Template” dialog no longer appears when clicking the “New Flow” button.
- The
/flow-templatesAPI endpoints have been removed and replaced by/templates. - Log size configuration has changed:
AP_MAX_FILE_SIZE_MBno longer controls flow run logs. UseAP_MAX_FLOW_RUN_LOG_SIZE_MBinstead.
Do you need to take action?
- If you are on the embed plan, update your implementation to redirect users to the
/templatespage. - Review the new endpoints documentation: Templates API Schema.
- If you use a custom value for
AP_MAX_FILE_SIZE_MB, be sure to also setAP_MAX_FLOW_RUN_LOG_SIZE_MBaccordingly.
0.75.0
What has changed?
- When you navigate to a flow run inside the builder the url will change to /runs, this is something embedding customers might need to consider in case they have a route guard that only allows users to navigate to /flows.
- In development mode, loading piece translations are now off by default. Set
AP_LOAD_TRANSLATIONS_FOR_DEV_PIECES=trueto enable.
Do you need to take action?
- Check your embedding navigation handler and see if it would be blocking the user from seeing the runs inside the builder or not.
- If you want to load translations for pieces in development mode, set
AP_LOAD_TRANSLATIONS_FOR_DEV_PIECES=truein your environment variables.
0.74.0
What has changed?
- The default embedded database for development and lightweight deployments has changed from SQLite3 to PGLite (embedded PostgreSQL).
- The environment variable
AP_DB_TYPE=SQLITE3is now deprecated and replaced withAP_DB_TYPE=PGLITE. - Existing SQLite databases will be automatically migrated to PGLite on first startup.
- Templates are broken in this version. A migration issue changed template IDs, breaking API endpoints. This will be fixed in the next patch release.
- The
aiCreditsfeature per project has been removed. In the next version, it will be replaced by integration with the AI Gateway.
Do you need to take action?
- If you are using
AP_DB_TYPE=SQLITE3: Update your configuration to useAP_DB_TYPE=PGLITEinstead. - If you are using templates: Wait for the next patch release to fix the template IDs.
0.73.0
What has changed?
- Major change to MCP: Read the announcement.
- If you have SMTP configured in the platform admin, it’s no longer supported—you need to use AP_SMTP_ environment variables.
Do you need to take action?
- If you are currently using MCP, review the linked announcement for important migration details and upgrade guidance.
- If you are below 0.73.0 and plan to switch
AP_EDITIONfromcetoee, upgrade to 0.73.0 on your current edition first, then switch. Edition-gated migrations are recorded as run without executing, so switching earlier leaves the schema incomplete.
0.71.0
What has changed?
- In separate workers setup, now they have access to Redis.
AP_EXECUTION_MODEmodeSANDBOXEDis now deprecated and replaced withSANDBOX_PROCESS- Code Copilot has been deprecated. It will be reintroduced in a different, more powerful form in the future.
When is action necessary?
- If you have separate workers setup, you should make sure that workers have access to Redis.
- If you are using
AP_EXECUTION_MODEmodeSANDBOXED, you should replace it withSANDBOX_PROCESS
0.70.0
What has changed?
AP_QUEUE_MODEis now deprecated and replaced withAP_REDIS_TYPE- If you are using Sentinel Redis, you should add
AP_REDIS_TYPEtoSENTINEL
When is action necessary?
- If you are using
AP_QUEUE_MODE, you should replace it withAP_REDIS_TYPE - If you are using Sentinel Redis, you should add
AP_REDIS_TYPEtoSENTINEL
0.69.0
What has changed?
AP_FLOW_WORKER_CONCURRENCYandAP_SCHEDULED_WORKER_CONCURRENCYare now deprecated all jobs have single queue and replaced withAP_WORKER_CONCURRENCY
When is action necessary?
- If you are using
AP_FLOW_WORKER_CONCURRENCYorAP_SCHEDULED_WORKER_CONCURRENCY, you should replace them withAP_WORKER_CONCURRENCY
0.66.0
What has changed?
- If you use embedding the embedding SDK, please upgrade to version 0.6.0,
embedding.dashboard.hideSidebarused to hide the navbar above the flows table in the dashboard now it relies onembedding.dashboard.hideFlowsPageNavbar
0.64.0
What has changed?
- MCP management is removed from the embedding SDK.
0.63.0
What has changed?
- Replicate provider’s text models have been removed.
When is action necessary?
- If you are using one of Replicate’s text models, you should replace it with another model from another provider.
0.46.0
What has changed?
- The UI for “Array of Properties” inputs in the pieces has been updated, particularly affecting the “Dynamic Value” toggle functionality.
When is action necessary?
- No action is required for this change.
- Your published flows will continue to work without interruption.
- When editing existing flows that use the “Dynamic Value” toggle on “Array of Properties” inputs (such as the “files” parameter in the “Extract Structured Data” action of the “Utility AI” piece), the end user will need to remap the values again.
- For details on the new UI implementation, refer to this announcement.
0.38.6
What has changed?
- Workers no longer rely on the
AP_FLOW_WORKER_CONCURRENCYandAP_SCHEDULED_WORKER_CONCURRENCYenvironment variables. These values are now retrieved from the app server.
When is action necessary?
- If
AP_CONTAINER_TYPEis set toWORKERon the worker machine, andAP_SCHEDULED_WORKER_CONCURRENCYorAP_FLOW_WORKER_CONCURRENCYare set to zero on the app server, workers will stop processing the queues. To fix this, check the Separate Worker from App documentation and set theAP_CONTAINER_TYPEto fetch the necessary values from the app server. If no container type is set on the worker machine, this is not a breaking change.
0.35.1
What has changed?
- The ‘name’ attribute has been renamed to ‘externalId’ in the
AppConnectionentity. - The ‘displayName’ attribute has been added to the
AppConnectionentity.
When is action necessary?
- If you are using the connections API, you should update the
nameattribute toexternalIdand add thedisplayNameattribute.
0.35.0
What has changed?
- All branches are now converted to routers, and downgrade is not supported.
0.33.0
What has changed?
- Files from actions or triggers are now stored in the database / S3 to support retries from certain steps, and the size of files from actions is now subject to the limit of
AP_MAX_FILE_SIZE_MB. - Files in triggers were previously passed as base64 encoded strings; now they are passed as file paths in the database / S3. Paused flows that have triggers from version 0.29.0 or earlier will no longer work.
When is action necessary?
- If you are dealing with large files in the actions, consider increasing the
AP_MAX_FILE_SIZE_MBto a higher value, and make sure the storage system (database/S3) has enough capacity for the files.
0.30.0
What has changed?
AP_SANDBOX_RUN_TIME_SECONDSis now deprecated and replaced withAP_FLOW_TIMEOUT_SECONDSAP_CODE_SANDBOX_TYPEis now deprecated and replaced with new mode inAP_EXECUTION_MODE
When is action necessary?
- If you are using
AP_CODE_SANDBOX_TYPEtoV8_ISOLATE, you should switch toAP_EXECUTION_MODEtoSANDBOX_CODE_ONLY - If you are using
AP_SANDBOX_RUN_TIME_SECONDSto set the sandbox run time limit, you should switch toAP_FLOW_TIMEOUT_SECONDS
0.28.0
What has changed?
- Project Members:
- The
EXTERNAL_CUSTOMERrole has been deprecated and replaced with theOPERATORrole. Please check the permissions page for more details. - All pending invitations will be removed.
- The User Invitation entity has been introduced to send invitations. You can still use the Project Member API to add roles for the user, but it requires the user to exist. If you want to send an email, use the User Invitation, and later a record in the project member will be created after the user accepts and registers an account.
- The
- Authentication:
- The
SIGN_UP_ENABLEDenvironment variable, which allowed multiple users to sign up for different platforms/projects, has been removed. It has been replaced with inviting users to the same platform/project. All old users should continue to work normally.
- The
When is action necessary?
- Project Members:
EXTERNAL_CUSTOMER role, you should start using the OPERATOR role instead.
- Authentication: