Swift SDK for self-hosted new-api instances. Provides chat completions, streaming, and model listing over an OpenAI-compatible REST API with HMAC-SHA256 request signing, certificate pinning, and device-bound authentication.
- Swift 5.9+
- iOS 15+ / macOS 12+ / tvOS 15+ / watchOS 8+
- No external dependencies (Foundation + CryptoKit only)
Add to your Package.swift:
dependencies: [
.package(url: "https://github.com/conversun/NewAPIKit.git", from: "1.0.0")
]Or in Xcode: File → Add Package Dependencies → paste the repository URL.
import NewAPIKit
let client = NewAPIClient(configuration: NewAPIConfiguration(
apiKey: "sk-your-token",
baseURL: URL(string: "https://api.example.com")!,
defaultModel: "gemini-3-flash",
pinnedCertificateHashes: ["base64-sha256-hash-from-admin-panel"]
))let response = try await client.chatCompletion(
messages: [
.system("You are a helpful assistant."),
.user("Hello!")
],
model: "gemini-3-flash",
temperature: 0.7,
maxTokens: 1024
)
print(response.content ?? "")let stream = try await client.chatCompletionStream(
messages: [.user("Tell me a story")]
)
for try await chunk in stream {
if let text = chunk.content {
print(text, terminator: "")
}
}let models = try await client.listModels()
for model in models {
print(model.id)
}Every request is automatically signed with HMAC-SHA256. The signing key is derived from the API key, bundle ID, and device ID (identifierForVendor), ensuring requests cannot be forged from outside the app on a different device.
| Header | Description |
|---|---|
Authorization |
Bearer sk-... |
X-Bundle-Id |
App's bundle identifier |
X-Device-Id |
UIDevice.current.identifierForVendor |
X-Timestamp |
Unix timestamp |
X-Nonce |
UUID for replay protection |
X-Signature |
HMAC-SHA256(timestamp + nonce + bodyHash) |
Signing algorithm:
signingKey = SHA256(apiKey + bundleId + deviceId)
bodyHash = SHA256(requestBody).hex
message = "{timestamp}\n{nonce}\n{bodyHash}"
signature = Base64(HMAC-SHA256(message, signingKey))
The SDK supports TLS certificate pinning to prevent MITM attacks. It checks the entire certificate chain — pin the intermediate CA for stability across leaf certificate renewals.
Get the hash from the admin panel: Token Editor → iOS Authentication → Get Certificate Hash.
let config = NewAPIConfiguration(
apiKey: "sk-your-token",
baseURL: URL(string: "https://api.example.com")!,
defaultModel: "gemini-3-flash",
pinnedCertificateHashes: ["your-intermediate-ca-hash"]
)When pinnedCertificateHashes is empty (default), pinning is disabled.
When iOS authentication is enabled on a token in the admin panel, that token cannot be used without valid signatures. Even if someone extracts the sk-xxx key, requests without proper HMAC signing from a real device are rejected.
All errors are typed via NewAPIError:
do {
let response = try await client.chatCompletion(messages: [.user("Hi")])
} catch let error as NewAPIError {
switch error {
case .invalidAPIKey:
// Invalid or missing API key
case .invalidSignature:
// HMAC signature verification failed
case .missingDeviceId:
// Device ID unavailable (e.g. simulator without identifierForVendor)
case .invalidBundleId, .missingBundleId:
// Bundle ID not authorized or missing
case .rateLimitExceeded(let retryAfter):
// Rate limited
case .quotaExceeded, .insufficientCredits:
// Billing issue
case .timeout:
// Request timed out
default:
print(error.localizedDescription)
}
}See LICENSE.