All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
0.3.1 - 2026-08-14
Tracks the June–July 2026 Dropbox API spec updates that touch routes Magpie already wraps.
Added
Magpie.Files.ListFolder.list_folder/3andstream/3now take an optionaloptsmap merged into the request body, so callers can use the remaining/files/list_folderarguments — including the newinclude_restorable_infoflag (each returned deleted entry then says whether it can be restored viais_restorable)Magpie.Files.ListFolder.list_revisions/4gained the same optionaloptsmap ("mode","before_rev","include_restorable_info")
Changed
Magpie.Files.get_thumbnail_v2/3docs no longer list"quality"as an option — Dropbox pulled the field from the public API surface in the July 2026 spec update
0.3.0 - 2026-08-10
Phoenix uploads. LiveView already owns the upload experience, so Magpie does not ship a component — it fills the two gaps a Dropbox backend creates: getting the bytes there without spooling them to disk, and skipping the server altogether.
Added
Magpie.LiveView.UploadWriter— aPhoenix.LiveView.UploadWriterthat streams a LiveView upload straight into a Dropbox upload session, so the bytes never land on the server's disk. Chunks are buffered to:chunk_size(default 8 MiB, Dropbox wants multiples of 4 MiB) and the tail rides along with the finish call. Magpie does not depend on:phoenix_live_view— the behaviour is a plain set of callbacksMagpie.LiveView.presign_upload/4— a LiveView:externaluploader that mints a one-time link withMagpie.Files.get_temporary_upload_link/3so the browser posts the file straight to Dropbox, bypassing the server. Entries above Dropbox's 150 MB single-request limit are rejected at presign time instead of being handed a link that cannot work. The client-side half ships aspriv/static/magpie_uploader.js
0.2.1 - 2026-08-05
Added
Magpie.Auth.TokenServerno longer requires a refresh token at startup. A server started without one sits in an unconfigured state — calls return a pattern-matchable{:error, %Magpie.Error{summary: "no_refresh_token"}}without touching the network — and the newset_refresh_token/3configures it (or replaces the token, for re-authorization) at any time, discarding any cached access token unless a validaccess_token/expires_atpair is seeded. Fresh installs whose token arrives through the OAuth callback now work from a plain static supervision treeMagpie.Auth.authorize_url/2acceptsextra_params:(keyword list or map) for additional Dropbox authorization params such asforce_reapprove,locale,require_roleanddisable_signup. Params the function already sets cannot be overridden — collisions raiseArgumentError
0.2.0 - 2026-08-05
OAuth 2 support. Dropbox access tokens expire after ~4 hours, so a static token is not enough for anything that runs unattended — Magpie now handles the whole flow and keeps tokens fresh on its own.
Added
Magpie.Auth— OAuth 2 flow helpers:authorize_url/2(offline access by default),pkce_pair/0andpkce_challenge/1for public apps,exchange_code/3andrefresh/3Magpie.Auth.Token— token struct with an absoluteexpires_atcomputed from Dropbox'sexpires_inMagpie.Auth.TokenProvider— behaviour that decouples the client from where tokens live, with two implementations:Magpie.Auth.StaticTokenandMagpie.Auth.TokenServerMagpie.Auth.TokenServer— supervised token holder that refreshes proactively (configurable:refresh_margin, default 300s), serializes concurrent refreshes into a single request, survives failed refreshes and can persist tokens through an:on_refreshcallbackMagpie.Client.new/1accepts a refresh token (refresh_token:/app_key:+app_secret:orpkce: true, starting a linkedTokenServer) or an explicittoken_provider: {module, arg}- Transparent recovery from expired tokens: requests rejected with HTTP 401
expired_access_tokenare refreshed and replayed once. Streamed upload bodies cannot be replayed and are not retried — the proactive refresh covers them - OAuth guide on HexDocs: getting a refresh token from the App Console, the web redirect flow, PKCE, supervision, persistence and custom providers
Changed
Magpie.Clientgained atoken_providerfield;access_tokenis kept andMagpie.Client.new("ACCESS_TOKEN")behaves exactly as beforeMagpie.Error.new/2uses the OAutherrorfield (e.g."invalid_grant") as the errorsummarywhen there is noerror_summary
0.1.0 - 2026-08-01
First release of Magpie 🐦 — a modern, actively maintained Elixir client for the Dropbox API v2, born as a rewrite of the unmaintained elixir_dropbox package (see the Origin section of the README).
Added
- Coverage of all 132 current user-scoped routes of the Dropbox API v2
(
files,sharing,file_properties,file_requests,users,account,auth,check,contacts,openid), verified against the official dropbox-api-spec Magpie.Files.upload_file/4— smart upload: single request for small files, chunked upload session for large ones, streamed from diskMagpie.Pager— lazyStream-based pagination, with ready-made wrappers (Magpie.Files.ListFolder.stream/2,Magpie.Files.search_stream/3,Magpie.Sharing.list_folders_stream/2,Magpie.FileRequests.stream/2)Magpie.Async.await/4— waits for asynchronous batch jobs by polling the check endpoint with exponential backoffMagpie.Error— normalized error struct (and exception) carrying the HTTPstatus, Dropbox'serror_summaryand the full errorbody- Offline test suite built on
Req.Test(~94% line coverage) and aconfig :magpie, req_options: [...]hook so consumer apps can stub Dropbox in their own tests - Examples guide on HexDocs
Changed
- HTTP client migrated from HTTPoison/Poison to Req/Jason
- Every call now returns
{:ok, result}or{:error, %Magpie.Error{}} - Deprecated Dropbox endpoints migrated to their current versions:
move_v2,search_v2(+search/continue_v2),copy_batch_v2(+check_v2),upload_session/finish_batch_v2andcreate_shared_link_with_settings - Default endpoint URLs are built in — consumer configuration is optional
Fixed
Magpie.Files.upload/6sent the file as JSON instead of raw bytes, breaking every upload since the Req migrationMagpie.Users.get_account_to_struct/2always returned an error even on successful responses- Paper
docs/users/list/continuepointed to a nonexistent URL
Deprecated
- The legacy
/paper/docs/*wrappers (Magpie.Paper.*) remain for compatibility, but the whole Paper API is deprecated by Dropbox — preferMagpie.Files.Paper