Releases: Flipboard/surf-sdks
Releases · Flipboard/surf-sdks
Release list
surf-sdks v1.2.0
Added
- Diagnostics + confidential debug bundles (Python, TypeScript, Go, Java) — new diagnostics namespace for the developer portal's agent-debugging surface:
client.diagnostics(Python/TypeScript),client.Diagnostics(Go),client.diagnostics(Java). Targets the portal host (https://surf.social/devportal/v1) automatically; override withdevportal_url(Python),devportalUrl(TypeScript),WithDevportalURL(...)(Go), orsetDevportalUrl(...)(Java) for non-prod backends.diagnose(app_id=None)/diagnose(appId?)/Diagnose(appID)/diagnose(appId)— structured diagnosis (derived findings + token health + usage + error breakdown). With an app API key, omit the app id to diagnose that token's own app.create_bundle(app_id=None, ttl_minutes=15)/createBundle({ appId?, ttlMinutes? })/CreateBundle(appID, ttlMinutes)/createBundle(appId, ttlMinutes)— mint a redacted, short-lived snapshot to share with Surf support; returnsshare_token+share_url.get_bundle(token)/getBundle(token)/GetBundle(token)/getBundle(token)— fetch a shared bundle (no auth; the token is the capability).revoke_bundle(token)/revokeBundle(token)/RevokeBundle(token)/revokeBundle(token)— revoke a bundle before it expires.
- AI cover-image generation (Python, TypeScript, Go, Java) — Media API methods for generating a feed cover image from a text prompt (Stable Diffusion XL), requiring the
use:aiscope. Async submit/poll: generation runs server-side and can take a couple of minutes (longer than request/CDN timeouts), so it doesn't block.generate_image/generateImage/GenerateImage— submits a job and returns immediately with{ key, url, status: "pending" }(Java: typedGenerateImageJob; Go:json.RawMessage).skip_refiner/skipRefinertrades quality for speed.get_generate_image_status/getGenerateImageStatus/GenerateImageStatus— polls a job:{ status: "pending" | "done" | "failed" | "not_found" }.generate_image_and_wait/generateImageAndWait/GenerateImageAndWait— convenience that submits and polls until done (default every 4s, up to 10 min), returning the image URL; raises/throws on failure or timeout.- GPU-bound, so it has its own dedicated 20/day-per-app cap (separate from the shared 100/day AI pool) plus a 20/day-per-user backstop; over-limit returns
429.
- Nested posts on the
Postmodel — The typedPostmodel now exposes two optional self-referential nested posts:reblog(the reposted post, present on reposts) andquote(the quoted post, present on quote posts). Available in Python (reblog/quote), TypeScript (reblog?/quote?), and Go (Reblog/Quote); the Java SDK returns rawMap<String, Object>for posts and is unaffected. - SurfRTBClient (Python, TypeScript, Go, Java) -- RTB (Real-Time Bidding) client for programmatic ad buying. Uses the same
surf_sk_live_...API key asSurfClientbut targets the RTB endpoints. API key must includertb:bidand/orrtb:reportsscopes.bid()-- send OpenRTB 2.5 bid requests with optionalsandbox=Truefor testing without real spendreports()-- access RTB performance reports with configurable granularityconfig()-- get publisher RTB configuration and tier infoscopes()-- list available RTB scopesads_txt()/adsTxt()/AdsTxt()-- fetch your personalized ads.txt entry authorizing Surf as a seller- Tracking is response-driven: impression, click, win (
nurl), and billing (burl) URLs are pre-built into the bid response and fired verbatim — there is noevent()method or separate reporting call. - Multi-impression bid requests are supported: pass multiple
impentries inbid()and the response returns a bid per fillable impression (keyed bybid.impid); each impression can carry its ownext.surffeed targeting - Automatic retry -- RTB calls now retry on 429 (respecting
Retry-After) and 5xx with capped exponential backoff, matchingSurfClient. Default 3 retries (up to 4 total attempts), base delay 1s doubling each retry, capped at 60s; set to 0 to disable. Configurable viamax_retries(Python),maxRetries(TypeScript),WithRTBMaxRetries(n)(Go), and theRtbClient(apiKey, baseUrl, maxRetries)constructor (Java). - Async (Python):
AsyncSurfRTBClientmirrors the syncSurfRTBClientwithawaitable methods and the same retry behavior; exported fromsurf_api. - Test coverage: per-language RTB integration tests (sandbox
bid()+reports()/config()/scopes()/ads_txt()+ an auth/scope error case), gated onSURF_API_TEST_TOKENand run by the sharedtest-harness/run_all.sh; plus expanded Python unit tests for RTB retry behavior.
- Public pagination helper — All four SDKs now expose a consistent
paginate()method for walking cursor-paginated endpoints that return JSON objects ({"<key>": [...], "cursor": "..."}). Bothcursorandnext_cursorresponse fields are supported. An optionallimitparameter caps total items yielded regardless of page count.- Python (sync):
SurfClient.paginate(path, key, params, limit=None)— generator;_paginateretained as a backward-compatible alias - Python (async):
AsyncSurfClient.paginate(path, key, params, limit=None)— async generator - TypeScript:
client.paginate<T>(path, key, params?, limit?)—AsyncGenerator<T>, usable withfor await...of - Go:
client.Paginate(path, key string, params url.Values, limit int) *Paginator—Next() boolchecks whether an item is available (fetches the next page when the buffer is exhausted);Item() json.RawMessagereturns the current item, advances the internal pointer, and enforces the call contract — calling it without a precedingNext()or more than once perNext()setsErr()and returnsnil;Err() errorreturns any fetch, parse, or misuse error; Go 1.21 compatible - Java: already public since v1.0.0; no change
- Python (sync):
- Typed operator helpers — Python, TypeScript, and Go now have a typed
NewFeedOperator/FeedOperatorconstruct matching Java's existingNewFeedOperatorrecord, so callers no longer have to hand-build raw maps when creating feeds with sources.- Python:
NewFeedOperatordataclass withsource()/of()factory methods andto_dict();FeedFilterdataclass withto_dict(); both exported fromsurf_api;create()auto-serializesNewFeedOperatorobjects alongside raw dicts; newcreate_with_operators(title, operators, description=None)convenience method oncustom_feeds - TypeScript: exported
FeedOperatorinterface (surfId, optionaloperator, optionalfilters) with literal-preservingoperatortype (string & {});create()keepsoperators?: unknown[](fully backwards-compatible);createWithOperators(title, operators, description?)is the strongly-typed entry point - Go:
Operatorstring type with named constants (OperatorSource,OperatorInclude,OperatorFilteringInclude,OperatorExclude,OperatorScore);FeedOperatorandFeedOperatorFilterstructs withomitemptyJSON tags;NewFeedOperatorSource(surfID)andNewFeedOperator(surfID, op)constructor funcs; variadicCreateWithOperators(title, description string, operators ...FeedOperator)method
- Python:
- SurfAgent -- AI agent with Surf MCP tools pre-loaded, powered by the Claude Agent SDK. Available in Python and TypeScript only (Go and Java do not include agent functionality).
- Python:
SurfAgentclass insurf_api.agentwithrun()andstream()methods - TypeScript:
SurfAgentclass exported from@surf/apiwithrun()andstream()methods - Pre-configured MCP connection to
mcp.surf.socialwith all 24 Surf tools (includingask_creatorfor per-creator agents) - Budget controls via
max_turns/max_budget_usd(Python) ormaxTurns/maxBudgetUsd(TypeScript) - Safety: read-only by default. Write tools (
create_post,save_custom_feed,favourite_post,set_feed_theme) are only permitted whenallow_writes=True(Python) orallowWrites: true(TypeScript). 20 read-only tools are allowed by default. - Lazy import of Agent SDK -- does not require
claude-agent-sdk/@anthropic-ai/claude-agent-sdkunlessSurfAgentis used - Unit tests for import, instantiation, read/write tool allowlists, and ImportError on missing SDK
- Python:
- TypeScript, Go, Java: automatic retry with exponential backoff on 429 and 5xx responses — default 3 retries (up to 4 total attempts per call), base delay 1s doubling each retry, all paths capped at 60s, 429 respects
Retry-Afterheader. Retry count matches Python's default; Python's 5xx/network backoff is uncapped, ours caps at 60s. - TypeScript:
maxRetriesoption onSurfClientOptionsto configure retry count (default:3; set to0to disable) - Go:
WithMaxRetries(n int) ClientOptionpassed toNewClientto configure retry count (default:3; passWithMaxRetries(0)to disable) - Java: 4-parameter constructor
SurfClient(apiKey, baseUrl, timeoutSeconds, maxRetries)to configure retry count (default:3)
Fixed
- Post-action methods now work for Bluesky posts (AT-URI ids).
favourite,unfavourite,reblog/boost,unreblog/unboost,bookmark,unbookmark, anddeletePostnow percent-encode the post id in the URL path, so Bluesky AT-URIs (at://did:plc:…/app.bsky.feed.post/…) route correctly instead of 404ing on the unencoded://and/. Fixes Python, TypeScript, and Go (Java already encoded the path segment). Numeric Mastodon ids are unaffected (encoding is a no-op for them).
v1.1.0
Feed theme support. See CHANGELOG.md for details.
Surf API SDKs v1.0.0
Initial public release.
API Coverage (83 endpoints)
- Feeds -- Browse topics, trending, timelines; create/favourite/boost/bookmark/delete posts
- Search -- Feeds, posts, accounts, podcasts with filtering and sorting
- Custom Feeds -- CRUD with typed operators (topic, hashtag, keyword, RSS, Bluesky/Mastodon users)
- AI -- Natural language search, feed summaries, AI feed builder (100/day)
- Content -- URL resolve, article extraction, language detection, enrichment
- Images -- AI analysis: describe, classify, OCR, object detection
- Audio -- Radio stations, briefings, podcasts, TTS, quizzes
- Account -- Lookup, profile links, connected apps
- Notifications -- Feed and badge counts
- Preferences -- Get/set user preferences
- Analytics -- Feed performance metrics
- Media -- Image upload
- MCP -- Model Context Protocol for AI agents
Authentication
- API tokens (
surf_sk_*) for server-to-server - OAuth 2.0 with PKCE (
surf_at_*) for user-delegated access ?service=bluesky|mastodonparameter for targeting linked accounts
SDKs
- Python -- Sync (
requests) + async (httpx), typed models, OAuth helper, auto-pagination - TypeScript -- Full type definitions, async/await, SSE streaming, OAuth helper
- Go -- Idiomatic error handling, typed models, OAuth helper
- Java -- Java 17+ records,
java.net.http.HttpClient(no deps), typed models, Jackson
Infrastructure
- Rate limiting (Free/Basic/Pro/Enterprise tiers)
- Auto-retry on 429 with Retry-After
- Cursor-based pagination
- Consistent error types across all SDKs