Changelog
What changed in WarpLink across the dashboard, API, MCP server, and the iOS, Android, React Native, and Flutter SDKs, with a dated entry for each release.
SDK 1.1.1
Released 2026-10-10. The iOS, Android, React Native, and Flutter SDKs are all at 1.1.1. This release retries rate-limited requests once and states how to use matchGuaranteed. No source changes are required to upgrade. For the full per-line history, see each SDK's own CHANGELOG.md in its repository.
What changed in 1.1.1
- Rate limits are retried once. When the link resolve or the attribution match answers
429, the iOS and Android SDKs retry it once when itsRetry-Afteris 5 seconds or less (1 second when the header is unreadable). A longerRetry-Afteris not retried, and the call fails as a server error with status 429. A second429is reported the same way, and no new error case is added, so existingswitchandwhencode keeps compiling. Android'sServerErroralso carries the server'sretryAfterSeconds. The React Native and Flutter SDKs use the native SDKs underneath, so they behave the same and their APIs do not change. The retry table is in Fallbacks when the API is unreachable. matchGuaranteedis for routing. Use it, likematchConfidence, to choose which screen to open, and keep sign-in on your own authentication. Only the Play Install Referrer on Android is deterministic. The iOS device ID check returns the install the device already has, with that install's own match type. The SDK guides and Attribution accuracy say the same.- Pins move to 1.1.1. The Flutter SDK pins the iOS SDK at 1.1.1 (Swift Package Manager) and the Android SDK at 1.1.1 (the
app.warplink:sdkartifact). The React Native SDK pins the same Android artifact and an iOS floor of 1.1.1.
Upgrading to 1.1.1
Update your Swift Package Manager dependency to 1.1.1:
dependencies: [
.package(url: "https://github.com/WarpLinkApp/warplink-ios-sdk", from: "1.1.1")
]If you move from 1.0.x, read the 1.1.0 notes first. customParams changed type in 1.1.0.
Update your Gradle dependency to 1.1.1:
dependencies {
implementation("app.warplink:sdk:1.1.1")
}Update the npm package to 1.1.1:
npm install @warplink/react-native@1.1.1Update the package to its latest 1.x release:
flutter pub upgrade warplink_flutterSee the Flutter SDK guide for platform setup.
Reliability, trust, and exports
Released 2026-10-10. This release documents how the SDK endpoints are protected and publishes the evidence behind our claims.
- SDK requests are limited per device address. The three SDK endpoints (
GET /v1/sdk/validate,GET /v1/links/resolve/{slug},POST /v1/attribution/match) allow 60 requests per minute per key per client IP address. A burst of installs on different devices no longer shares one allowance. Every other route keeps 60 requests per minute per key. See Rate limiting. - SDK keys are scoped to the SDK endpoints. An SDK key ships inside your app, so it works on
GET /v1/sdk/validate,GET /v1/links/resolve/{slug}, andPOST /v1/attribution/matchand on nothing else. Any other endpoint and the MCP server answer it with403 SDK_KEY_ROUTE_FORBIDDEN. Use an API key for those calls. See Authentication. - Link UTM fields are applied on redirect.
utm_source,utm_medium, andutm_campaignset on a link are added to the redirect URL, including for links created before you set them. The exact precedence is in the Links API. - Routing-only mode. An app can turn off probabilistic matching. Deep links keep working, and installs are matched only by the Play Install Referrer and the device ID repeat check. Set it under Install matching in the app's settings, or with
probabilistic_matchingonPATCH /v1/apps/{id}and the MCPupdate_apptool. See Routing-only mode. - Click CSV exports run on demand. An export starts as soon as you create it and is ready in seconds to a few minutes. The finished file stays available for 7 days. See the Exports API reference.
- Trust and reliability docs. Nine pages cover performance methodology, architecture, attribution, data portability, plan changes, deprecation policy, abuse protection, API fallbacks, and SDK data flow. See Trust and reliability.
- Security and support pages. The Security and Support pages state our security practices, support reply times, and contacts.
- DPA, sub-processor list, Terms, and Privacy Policy. The DPA, the sub-processor list, the Terms, and the Privacy Policy are published. We give 30 days' notice before a new sub-processor starts.
- Installs API.
GET /v1/installsandGET /v1/attribution/attemptslist install records and attribution attempts with stable IDs, and the MCP toolslist_installsandlist_attribution_attemptsdo the same. - MCP server. The MCP server now has 34 tools.
Free plan analytics: 30-day look-back and a freeze at the limit
Released 2026-10-08. Free keeps every traffic analytics feature and now reads the last 30 days. Data is still kept for 90 days, and an upgrade shows the older days at once.
- A locked range says so. A range that starts before the last 30 days is refused, not shortened. The dashboard marks the locked days in the date picker. REST and MCP return
LOOKBACK_EXCEEDED(403) withdetails.earliest_allowed. - Comparisons and exports follow the same 30 days. A comparison works on Free when its earlier period also starts inside the last 30 days. Free exports cover the same 30 days.
- Analytics freeze at the click limit. A Free org that reaches 10,000 monthly clicks keeps reading its figures as they stood when the limit was reached. Clicks keep being stored and appear after an upgrade or in the next billing period. REST and MCP carry
pausedas{ reached_at, limit }on the receipt, plus a warning. - Match health. The match tile shows Healthy (80% or more), Needs attention (50% to under 80%), or Low (under 50%) on the rate among new installs where a tap was found, once at least 50 such installs are counted.
attempt_match_rategains an additivetap_foundfield. The new "Why installs don't match" page lists the reasons. - Four key numbers. The dashboard no longer draws app open share. REST and MCP still return
app_open_share.
See Link analytics.
Flutter SDK
Released 2026-10-08. The Flutter SDK is published as warplink_flutter 1.1.0, with the same onLink callback, deferred deep links, and install attribution as the iOS, Android, and React Native SDKs. See the Flutter SDK guide.
An address for every app
Released 2026-10-05. Every app now has its own link address, yourapp.aplnk.to, on every plan. Apps that existed before keep aplnk.to for good, with no end date. Links you already have stay where they are and keep opening your app. Existing apps keep using the domain of their most recent link by default: aplnk.to, or a custom domain that is live and served by your plan, otherwise aplnk.to. Owners and admins can change it per app in the app's Settings.
- Set it up when you are ready. Each existing app has its own address to set up in its Settings: choose it, add it to your app and test it, then make it the default for new links. The steps are guidance, not a locked wizard.
- A permanent test link. Every app address has
https://yourapp.aplnk.to/test. Tap it on a phone with your new build. If your app opens, it is set up. The slugtestis reserved on app addresses. - A reversible default. Owners and admins choose which domain new links use: the app's address,
aplnk.to, or a live custom domain. Change it back at any time. Existing links keep their addresses, and a link that names a domain always gets that domain. UsePUT /v1/apps/{id}/link-domainor theset_app_link_domainMCP tool. - Change an unused address freely. While no link or redirect uses the address, change it as often as you like on every plan, with no rename period. A released address is held for 7 days. Once a link uses it, you can change it once more on every plan, after you confirm. Links you already made stay on the old address, and the old address keeps working.
- New apps use their own address. The create step prefills it from the app name. Through the API and MCP, leave
link_handleout and we derive it. - One quiet reminder. Owners and admins see one bar in the dashboard while an app's address is not its default. Not now hides it for 24 hours, and Dismiss hides it for good. We send one email about app addresses to owners and admins, and no reminders after it.
- API and MCP. Apps return
link_handle,link_domain,legacy_apex_enabled,default_link_domain,default_link_domain_available,allowed_link_domains,previous_link_handle,previous_link_domain,rename_period_ends_at, andrename_period_extensions.PATCH /v1/apps/{id}and theupdate_apptool takeexpected_link_handlewithlink_handle. APOST /v1/linkswith nodomainuses the app's default, and an explicitdomainis never replaced. Links returnredirected_fromonGET /v1/links/{id}. The MCP server has 32 tools.
See Your app's own link address.
Members can pause any link
Released 2026-10-01. Every role in an organization can pause and resume any link, from the link's row menu, its detail page, bulk actions, the REST API, and the MCP server. Members still edit and delete only the links they created.
Better Analytics
Released 2026-09-29. The Analytics page is rebuilt to answer "what changed, and why" in one screen.
- A question you can read. The query bar states the view as a sentence: which links, which period, which filters. Copy the view link to share that exact view with your team.
- The answer first. A headline sentence says how clicks moved against the previous period and where the change came from, such as a country, referrer, or campaign source. Each mover is a chip you click to filter the page. A key numbers strip shows clicks, unique clicks, installs, tap-to-install rate, and app open share, each with its change and a sparkline. A spike day gets one plain line and a way to look at it.
- A trend you can zoom. The chart draws the previous period as a second line, bucket by bucket. Switch between hourly, daily, and weekly buckets, and drag across the chart to zoom into a range.
- Breakdowns that filter. A grid breaks clicks down by country, referrer, device, operating system, browser, campaign source, app, and tap source, each row with its share, change, and sparkline. Add a row's value to the filter, or remove it, straight from the grid.
- Filters that combine. Check up to 25 values in a dimension (any of them matches) and combine dimensions (every one must match). With two or more values checked, Split draws one line and one total per value, up to five at a time.
- Links that need attention. The links leaderboard shows top movers, links new this period, and active links with no taps. Compare Links puts two to five links next to each other over the same window.
Every organization now sets its own reporting time zone, in Settings. Charts bucket and label days in that zone, and trends run through the current local day, with the running day marked as in progress. Exports resolve their date range in that zone and record it in the file, though each row's timestamp stays in UTC. A new organization defaults to the time zone of whoever signed up. The REST API and MCP server use the same zone unless a request names its own.
Some states now say what they are, in words, instead of showing a number that looks final. A period outside your plan's retention window says that, instead of showing zero.
Exports include every matching click for the organization or for one link, in the date range you select and up to your plan's retention window, with UTM fields and uniqueness data.
The Overview page now shows your attempt match rate, the share of attribution attempts that matched to a link, alongside your active link count under the page title.
An AI client reads the same numbers. The query_analytics MCP tool returns every part of the Analytics page: the overview, one link, a breakdown, the key numbers and headline, the trend, the links leaderboard, and a link comparison. export_analytics creates, checks, and downloads a full click-data export. The REST API exposes the same read at GET /v1/analytics. See Link Analytics and the Analytics API reference. For the reasoning behind the redesign, read what changed in WarpLink analytics, and why.
API and MCP details
- Analytics page signals over MCP and REST (2026-09-29).
query_analyticsandGET /v1/analyticsgainsummary,trend, andleaderboardsurfaces with the same numbers as the Analytics page: KPIs including tap-to-install rate and app open share, the headline and top movers, chart series by hour, day, or week with the previous period, and a links leaderboard including active links with no taps.exploregainssearchandrow_series. - Multi-value filters (2026-09-29). A filter accepts several values for one dimension (any of them matches), up to 25. On REST, repeat
filter=dimension:valuefor one dimension; before, a second value for a dimension was refused. - Reporting time zone is the default (2026-09-29). Days, weeks, and hours in
query_analyticsandGET /v1/analyticsare now labeled in your organization's reporting time zone, the same zone the dashboard uses. They defaulted to UTC before. Sendtimezoneto keep UTC or name another zone. Theget_link_analyticstool follows the same default and takes the same optionaltimezoneinput. Anext_cursorissued for an organization with a reporting time zone before this change returnsCURSOR_INVALID; run the query again without it. Cursors expire after 15 minutes either way. - Installs under a filter count taps in the range (2026-09-29). With a filter set or a member's own-links scope,
linked_installscounts installs from taps inside the range, seen so far. Without either it counts installs that happened inside the range. The tap-to-install rate uses the same tap cohort, so an installs figure for a closed range can still grow as later installs are matched. - Repeated query parameters are refused (2026-09-29).
GET /v1/analyticsanswers400 VALIDATION_ERRORwhen a parameter other thanfilteris sent twice. Before, the first value won and the second was dropped. The same route also refusesorg, which it always ignored: it answers for the API key's own organization. An emptysearchondimension=sourceis refused, as it is over MCP. - Refused chart sizes name the parameter (2026-09-29).
INVALID_GRANULARITYnow readsgranularity=hour needs a window of at most 7 days.orgranularity=week needs a window of at least 14 days., andexplorewithrow_series=truechecks the window after the plan's retention cut, so a size that the visible part of the window cannot draw is refused instead of answered in days. Sparkline points that cannot be computed, such as a rate with no denominator, arenull, andinsight.silent_stateonleaderboardsays whether the silent tab can claim silence.
Click exports API
Released 2026-09-29. Start a click export for an organization or one link, poll its status, and download the finished CSV through the REST API, or through the export_analytics MCP tool. An export is a snapshot cut when the job starts, so running the same request again can produce a different file. See the Exports API reference.
Keys page and app-tied SDK keys
Released 2026-09-21. The dashboard has a Keys page with separate SDK keys and API keys tabs. An SDK key can now be tied to one app, so a key shipped in one app cannot record installs for another. A request from a different app gets 403 KEY_APP_MISMATCH. Deleting an app revokes the SDK keys tied to it. See Authentication.
Two-factor authentication and session controls
Released 2026-09-19. Dashboard sign-in supports authenticator app (TOTP) two-factor authentication, with backup codes. Organization owners can require it for every member, and can set a session lifetime and an idle timeout for the organization.
Audit log
Released 2026-09-17. The dashboard has an organization audit log that records account and security events, available on every plan.
SDK 1.1.0
iOS, Android, and React Native shipped 1.1.0 on 2026-09-15, and Flutter on 2026-10-08. The WarpLink SDK 1.1.0 release post walks through the onLink callback and the upgrade. This section covers what changed at a high level and how to upgrade. Later changes are under SDK 1.1.1. For the full per-line history, see each SDK's own CHANGELOG.md in its repository.
What Changed in 1.1.0
The iOS, Android, and React Native SDKs shipped the same set of changes in the 2026-09-15 release:
- Opt-out configuration. A single
configure({ apiKey, onLink })call now wires up cold-start deep links, warm-start deep links, and the deferred deep link check automatically. Each piece can still be turned off individually if you want to drive it yourself. - Custom link domains. The SDKs fetch your organization's verified custom domains and resolve links on them, instead of recognizing only
aplnk.to. Declare domains locally with thelinkDomainsoption (or the no-code manifest/plist equivalent) so a link resolves correctly on the very first launch, before the server response arrives. - Shorter deferred match window. The default lifetime of a deferred deep link payload dropped from 72 hours to 6, set per link, up to 24 hours. This affects the probabilistic match tier only; the install referrer and device ID branches are unaffected.
- In-app opens now count as recorded clicks. A verified Universal Link or App Link that opens your app directly now appears in analytics alongside browser redirects, and counts toward click deduplication the same way. This is a server-side change and applies to older SDK versions too.
Platform-Specific Changes
- iOS:
customParamsis now[String: JSONValue]instead of[String: Any], a type change that needs a one-line edit where you read it: replace a cast such ascustomParams["id"] as? Stringwith the typed accessorcustomParams["id"]?.stringValue. - Android and React Native: no source-breaking changes in this release.
Upgrading
Update your Swift Package Manager dependency to 1.1.0:
dependencies: [
.package(url: "https://github.com/WarpLinkApp/warplink-ios-sdk", from: "1.1.0")
]If any code reads customParams with a cast such as customParams["x"] as? String, switch to the typed accessor: customParams["x"]?.stringValue. Everything else is additive; no other code changes are required to upgrade.
Update your Gradle dependency to 1.1.0:
dependencies {
implementation("app.warplink:sdk:1.1.0")
}No source changes are required. The release is additive and backward compatible.
Update the npm package to 1.1.0:
npm install @warplink/react-native@1.1.0No source changes are required. The release is additive and backward compatible.
The Flutter SDK is published at the same version, so Flutter apps start on 1.1.0 with nothing to upgrade from:
flutter pub add warplink_flutterSee the Flutter SDK guide for platform setup.
Custom domains
Released 2026-06-06. Custom domains get real HTTPS certificates that issue and renew automatically, a guided setup that shows each stage until the domain is live, and a free trial: every organization can run one custom domain free for 3 months. See Custom domains.
Incidents
Since 1 January 2026, no service-wide incident has been recorded. When one happens, it is posted here and on the status page with the time, the effect, and the fix.
Related
- Link Analytics: how clicks, uniqueness, and retention work
- Analytics API reference:
GET /v1/analyticsrequest and response shape - SDK Overview: platform support and design principles across every SDK
- Quickstart: install and configure a WarpLink SDK from scratch
- Deferred deep links: how the match window and confidence tiers work
Apple Privacy Rules and Install Matching
Our position: deep links and deferred deep links work on iOS with or without an App Tracking Transparency opt-in, because WarpLink does not track users.
Migration
Move from any deep linking provider to WarpLink: link recreation, SDK swap, app association, cutover, and verification, with a guide for each provider.