Skip to main content

CoinPaprika Swift SDK

The official Swift client library for the CoinPaprika API provides convenient, static access to cryptocurrency market data.

Installation

Swift Package Manager (SPM)

Add the following package dependency to your Package.swift file or via Xcode:
https://github.com/coinpaprika/coinpaprika-api-swift-client

CocoaPods

Add the following line to your Podfile and run pod install:
pod 'CoinpaprikaAPI'

Quick Start

First, import the library:
import Coinpaprika
Then, you can call any API endpoint via the static Coinpaprika.API object. All requests are asynchronous and return a Result type in a closure.
// Get global market stats
Coinpaprika.API.global().perform { result in
    switch result {
    case .success(let stats):
        print("Market Cap: $\(stats.marketCapUsd)")
        print("24h Volume: $\(stats.volume24hUsd)")
        print("Bitcoin Dominance: \(stats.bitcoinDominancePercentage)%")
    case .failure(let error):
        print("An error occurred: \(error)")
    }
}

Authenticating with a paid plan

Paid plans (Starter / Pro / Business / Ultimate / Enterprise) live on a separate hostname, https://api-pro.coinpaprika.com/v1/, and require an API key in the Authorization header. Send the bare key — a Bearer prefix is rejected by the WAF. The high-level Coinpaprika.API static methods don’t currently accept a key. To call paid endpoints, drop down to the CoinpaprikaNetworking Request<Model> constructor with .bearer(token:) and point it at the Pro base URL. The package exposes CoinpaprikaNetworking as a separate library product, so add it to your target’s dependencies alongside Coinpaprika.
import CoinpaprikaNetworking
import Foundation

struct KeyInfo: Codable {
    let plan: String
    let plan_status: String
}

let key = ProcessInfo.processInfo.environment["COINPAPRIKA_API_KEY"]!

let request = Request<KeyInfo>(
    baseUrl: URL(string: "https://api-pro.coinpaprika.com/v1/")!,
    method: .get,
    path: "key/info",
    params: nil,
    userAgent: "my-app/1.0",
    authorisation: .bearer(token: key)
)

request.perform { result in
    switch result {
    case .success(let info):
        print("Plan: \(info.plan), status: \(info.plan_status)")
    case .failure(let error):
        print("Error: \(error)")
    }
}
For free-tier endpoints that don’t need a key (most of Coinpaprika.API), keep using the high-level static API against the default base URL.

Common Use Cases

Ticker Data for a Specific Coin

import Coinpaprika

Coinpaprika.API.ticker(id: "btc-bitcoin", quotes: [.usd, .btc]).perform { response in
    switch response {
    case .success(let ticker):
        print("Bitcoin Information:")
        print("Name: \(ticker.name)")
        print("Symbol: \(ticker.symbol)")
        
        // Access quotes using subscripting
        if let usdQuote = ticker[.usd] {
            print("USD Price: $\(usdQuote.price)")
            print("Market Cap: $\(usdQuote.marketCap)")
        }
        
        if let btcQuote = ticker[.btc] {
            print("BTC Price: ₿\(btcQuote.price)")
        }
    case .failure(let error):
        print("Error: \(error)")
    }
}

Coin Details

import Coinpaprika

Coinpaprika.API.coin(id: "eth-ethereum").perform { response in
    switch response {
    case .success(let coin):
        print("Ethereum Details:")
        print("Name: \(coin.name)")
        print("Description: \(coin.description ?? "N/A")")
        print("Development Status: \(coin.developmentStatus)")
    case .failure(let error):
        print("Error: \(error)")
    }
}

Historical Ticker Data

Historical endpoints require a paid plan. The high-level Coinpaprika.API.historicalTicks(...) shape is shown below for the request structure; to actually authenticate, build a Request<Tick> against the Pro base URL using the .bearer(token:) pattern from “Authenticating with a paid plan”.
import CoinpaprikaNetworking
import Foundation

struct Tick: Codable {
    let timestamp: String
    let price: Double
    let volume24h: Double
    enum CodingKeys: String, CodingKey {
        case timestamp, price
        case volume24h = "volume_24h"
    }
}

let key = ProcessInfo.processInfo.environment["COINPAPRIKA_API_KEY"]!
let sevenDaysAgo = Calendar.current.date(byAdding: .day, value: -7, to: Date())!
let isoStart = ISO8601DateFormatter().string(from: sevenDaysAgo)

let request = Request<[Tick]>(
    baseUrl: URL(string: "https://api-pro.coinpaprika.com/v1/")!,
    method: .get,
    path: "tickers/btc-bitcoin/historical",
    params: ["start": isoStart, "limit": 100, "quote": "usd"],
    userAgent: "my-app/1.0",
    authorisation: .bearer(token: key)
)

request.perform { result in
    switch result {
    case .success(let ticks):
        ticks.forEach { print("[\($0.timestamp)] $\($0.price)") }
    case .failure(let error):
        print("Error fetching historical ticks: \(error)")
    }
}
import Coinpaprika

Coinpaprika.API.search(
    query: "proof-of-work",
    categories: [.tags]
).perform { response in
    switch response {
    case .success(let searchResults):
        print("Found \(searchResults.tags.count) tags for 'proof-of-work'")
        searchResults.tags.forEach { tag in
            print("- \(tag.name) (Coin count: \(tag.coinCounter))")
        }
    case .failure(let error):
        print("Error: \(error)")
    }
}

Error Handling

The Result object in the completion handler provides a detailed RequestError case for failures.
import Coinpaprika

Coinpaprika.API.coin(id: "invalid-coin-id").perform { response in
    if case .failure(let error) = response {
        switch error {
        case .networkError(let underlyingError):
            print("Network error: \(underlyingError.localizedDescription)")
        case .decodingError(let underlyingError):
            print("Decoding error: \(underlyingError)")
        case .httpError(let statusCode, let data):
            let errorBody = String(data: data, encoding: .utf8) ?? "No response body"
            print("HTTP error \(statusCode): \(errorBody)")
        case .unknown:
            print("An unknown error occurred.")
        }
    }
}

Async/Await Support (iOS 13+ / macOS 10.15+)

The SDK supports modern concurrency with async/await.
import Coinpaprika

@available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 6.0, *)
func getMarketData() async {
    do {
        let globalStats = try await Coinpaprika.API.global().async()
        print("Market Cap: $\(globalStats.marketCapUsd)")
        
        let tickers = try await Coinpaprika.API.tickers(quotes: [.usd]).async()
        print("Retrieved \(tickers.count) tickers")
    } catch {
        print("An error occurred: \(error)")
    }
}

Available Methods

Global Data

  • global() - Get global market overview.

Coins

Tickers

Exchanges

People & Tags

Search & Tools

FAQs

The high-level Coinpaprika.API static methods don’t currently accept a key. Use CoinpaprikaNetworking’s Request<Model> constructor with .bearer(token:) and the https://api-pro.coinpaprika.com/v1/ base URL. See the “Authenticating with a paid plan” section above.
Use the Coverage Checker to obtain canonical IDs (e.g., btc-bitcoin).
Historical endpoints require a paid plan. Build a Request<Model> against the Pro base URL with .bearer(token:) auth (see the “Authenticating with a paid plan” section), pointing at tickers//historical or coins//ohlcv/historical with start/end/quote parameters.

Requirements

  • iOS 10.0+ / macOS 10.12+ / watchOS 3.0+ / tvOS 10.0+
  • Swift 4.2+

License

This library is available under the MIT license. See the LICENSE file for more info.