Skip to content

About

Unofficial Swift SDK for the Toss Securities Open API

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

TossInvestKit

Unofficial Swift SDK for the Toss Securities Open API

A Swift Package for Linux, macOS, iOS, watchOS, tvOS, and visionOS, with asynchronous REST APIs and typed request and response models. Realtime WebSocket availability depends on the platform and, on watchOS, the operating system's permitted networking use cases. This project is independent of Toss Securities and is not an official SDK.

Requirements

  • Swift 6.0 or later.
  • Linux with a compatible Swift toolchain, macOS 12+, iOS 15+, watchOS 9+, tvOS 15+, or visionOS 1+.
  • REST uses Foundation and, on Linux, FoundationNetworking.
  • The default realtime transport uses WebSocketKit and SwiftNIO on Linux, macOS, iOS, tvOS, and visionOS. It does not require a custom libcurl build.
  • watchOS uses URLSession for REST and its default WebSocket adapter; WebSocketKit and NIOPosix are excluded from that target. Normal trading apps on watchOS cannot use direct WebSocket networking. See platform support for Apple's restrictions and deployment guidance.
  • The optional URLSession WebSocket adapter requires a WebSocket-enabled libcurl on Linux and does not work in the tested stock Swift 6.0 Jammy or Swift 6.2 Noble images.

Local installation

For local development, add the package to your application's Package.swift:

.package(path: "../TossInvestKit")

Then add .product(name: "TossInvestKit", package: "TossInvestKit") to the application's target dependencies.

Quick start

Choose the credential and network deployment model in the platform guide before using these direct-service examples in a distributed app.

Use an access token obtained through your application's credential-management flow:

import TossInvestKit

let client = try TossInvestClient(accessToken: accessToken)
let prices = try await client.getPrices(symbols: "005930,AAPL")
let accounts = try await client.getAccounts()

To issue a token explicitly:

let credentials = try ClientCredentials(clientID: clientID, clientSecret: clientSecret)
let token = try await TossInvestClient.issueToken(credentials: consume credentials)
let client = try TossInvestClient(accessToken: token.accessToken)

Run privileged token issuance in a trusted environment. Do not embed client secrets in distributed apps; obtain application data through an authenticated backend when appropriate. A backend relay is an application architecture recommendation, not an included SDK service. Direct requests still require an allowed public source IP, which mobile or changing networks may not provide. Issuing another token for the same client ID invalidates the previous token immediately. Reuse the token across REST and realtime clients. Rotation, expiration tracking, and retries are caller-managed. See the official authentication contract.

API coverage

The SDK implements token issuance and all 35 authenticated REST operations in the bundled OpenAPI 1.2.17 specification:

  • Market data, stocks, investor trading, rankings, indicators, exchange rates, and calendars.
  • Accounts, holdings, orders, conditional orders, buying power, sellable quantity, and commissions.
  • Realtime trade ticks, orderbook updates, personal order events, subscription acknowledgements, errors, and keepalive frames from AsyncAPI 1.2.2.

Account-specific calls require an explicit account string containing the accountSeq returned by getAccounts(). Prices, quantities, and timestamps preserve their wire string representations. Decimal financial values are not converted through Double.

Requests execute once. In particular, the SDK does not retry a failed order or generate an idempotency key automatically. Server validation remains authoritative; model construction does not validate every trading rule. Inspect TossInvestHTTPError for the status, API code, request ID, and retry headers.

Realtime subscriptions replace the entire active set. Applications must send keepalive, close failed connections, reconnect with backoff, redeclare subscriptions, and reconcile order state through REST. The client exposes one frame at a time with a bounded internal receive queue when using the WebSocketKit transport that closes the connection on overflow instead of silently dropping order events.

Ownership

ClientCredentials and PreparedOrder are noncopyable (~Copyable) values. Token issuance consumes the credentials. client.prepareOrder(account:body:) transfers a request body into a prepared order whose consuming submit() can be called only once, including when the call throws. The Swift compiler rejects reuse of either consumed value.

The client can be borrowed to prepare multiple orders. Codable response values and access tokens remain reusable. Ownership does not erase secret string memory or guarantee that separately constructed requests execute only once on the server.

Documentation

The Swift-DocC catalog connects the official API contract to the SDK's behavior:

  • Platform support: minimum versions, default transports, watchOS restrictions, and credential deployment.
  • Getting started: client registration, allowed source IPs, token issuance, and coordinated renewal.
  • REST guide: account selection, pagination, order constraints, idempotency, and conditional orders.
  • Errors and limits: diagnostic references, error categories, throttling, and SDK header visibility.
  • Realtime guide: wire frames, subscription results, service limits, keepalive, and delivery guarantees.
  • Ownership: compile-time transfer and single-use submission contracts.

Service guidance was checked on 2026-09-14 against the official overview, OpenAPI 1.2.17, and AsyncAPI 1.2.2. Both JSON contracts match the bundled snapshots. Service quotas and eligibility remain subject to the official documentation.

Scripts/build-docs.sh

This builds .build/documentation/TossInvestKit.doccarchive, including static hosting files with the default base path TossInvestKit. It requires DocC and its rendering template from the Swift toolchain. No SwiftPM documentation plugin is required. Open the archive in Xcode or serve the static files under that base path. This command builds documentation locally; it does not publish it.

Scripts/build-docs.sh --help
Scripts/build-docs.sh /tmp/TossInvestKit.doccarchive ""

The second command builds for hosting at a server's root path.

GitHub Pages deployment

The Documentation workflow builds with Xcode 27 (xcode-27) and deploys DocC to GitHub Pages on pushes to main or a manual run on main. Enable Settings → Pages → GitHub Actions before the first run. The deployment URL appears in the github-pages environment. See the deployment guide.

Development

python3 Scripts/lint.py
swift test
swift build -c release
python3 Scripts/generate.py --check
python3 Scripts/test-network.py
python3 Scripts/test-ownership.py
Scripts/build-docs.sh

Build Apple device and simulator targets with installed Xcode SDKs:

Scripts/build-apple-platform.sh --help
Scripts/build-apple-platform.sh ios device
Scripts/build-apple-platform.sh watchos simulator

The script accepts ios, watchos, tvos, or visionos, followed by device or simulator. CI configures both destinations for each platform. These are unsigned compile checks, not execution on hardware. A watch simulator permits low-level networking that a real watch may block; device validation remains separate.

The tests include all 74 official successful JSON examples. Normal tests use injected transports. test-network.py starts bounded localhost HTTP and WebSocket fixtures and runs the three opt-in HTTP and WebSocketKit integration tests. It requires Python 3 and makes no calls to Toss Securities. test-ownership.py compiles valid ownership transfers and confirms that duplicate submission, reused credentials, and consuming borrowed credentials are rejected.

Specification snapshots and compatibility notes describe regeneration and the documented ETF englishName exception. Changes to the official API may require regenerating and reviewing models before adoption.

Validation against real credentials, permitted source IPs, live market data, and live orders remains outside the local test suite.

Swift linting

Run python3 Scripts/lint.py to check handwritten Swift sources, tests, and Package.swift. Use python3 Scripts/lint.py --fix to apply formatting and rerun strict lint. The .swift-format configuration uses four-space indentation and a 120-character line-length target.

CI uses the formatter bundled with Xcode 27 as the canonical lint version; use the same toolchain locally to avoid version-dependent formatting differences. Generated Models.swift and Endpoints.swift are excluded from formatting and checked separately with python3 Scripts/generate.py --check.

License

Licensed under the MIT License.

About

Unofficial Swift SDK for the Toss Securities Open API

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages