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.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