PPromptHelm Docs
Quickstarts

Quickstart with iOS (Swift)

Call your PromptHelm prompts from any Apple platform application.

This quickstart walks you through minting an API token, adding the PromptHelm Swift SDK to an Xcode project, and making your first call from a Swift app. By the end you will have a working completion against a published prompt, an AsyncSequence streaming example, and a short production checklist.

Prerequisites

  • Xcode 15 or newer (Swift 5.9+, supports Swift 6 strict concurrency).
  • A deployment target of iOS 16, macOS 13, watchOS 9, tvOS 16, or visionOS 1 (or newer).
  • A PromptHelm account. Join the waitlist if you need an invite.
  1. Sign in to the dashboard and open Settings → API tokens. Click New token, name it (e.g. ios-app-dev), and copy the value immediately — tokens are revealed exactly once.

    Store the token in the Keychain

    Never embed an API token in Info.plist, asset catalogs, or any bundled resource. Use the iOS Keychain (or your app's secrets backend) and inject the value at runtime. The examples below read from the process environment for local development only.

  2. The SDK ships through Swift Package Manager. Add it once per project, either through the Xcode UI or by editing Package.swift.

    1. In Xcode, choose File → Add Package Dependencies…
    2. Paste the repository URL:
    https://github.com/Runivox/prompt-helm-sdk-ios.git
    1. Set the dependency rule to Up to Next Major Version from 0.1.0 and click Add Package.
    2. Select your app target when prompted to add the PromptHelm library product.
  3. In the dashboard, navigate to Prompts → New prompt. Give it a slug (for example, welcome), pick a default model, and write the prompt body. Use {{ variable_name }} syntax for runtime variables.

    When you click Save, PromptHelm publishes a v1 on the main environment. The slug is the contract your SDK calls reference.

    Learn more

    See Concepts → Prompts for the full data model — versions, environments, and promotion flows.

  4. Import PromptHelm, build a client, and await the first response. The example below reads the API key from the process environment for local runs; in production, swap to your Keychain accessor.

    Sources/MyApp/Quickstart.swift
    import PromptHelm
    
    let ph = try PromptHelm(config: .init(
        apiKey: ProcessInfo.processInfo.environment["PROMPTHELM_API_KEY"]!
    ))
    
    let response = try await ph.execute(.init(
        promptSlug: "welcome",
        variables: ["name": "World"]
    ))
    
    print(response.output)

    The call appears in the dashboard's Logs view with the full request/response payload, the per-call cost, and the round-trip latency.

  5. For interactive surfaces — chat bubbles, inline assistants, watchOS glances — switch to the streaming API. The SDK exposes an AsyncSequence of typed events so you can for try await each chunk straight into your UI.

    Sources/MyApp/Stream.swift
    for try await event in ph.stream(
        .init(promptSlug: "welcome", variables: ["name": "World"])
    ) {
        switch event {
        case .chunk(let content):
            print(content, terminator: "")
        case .done(let inputTokens, let outputTokens, let totalTokens, let cost, _, _):
            _ = (inputTokens, outputTokens)
            print("\n\(totalTokens) tokens, $\(cost)")
        case .error(let code, let message, _):
            print("Error \(code): \(message)")
        }
    }

    Wrapping the loop in a Task lets you cancel mid-flight (for example, when a user navigates away). Cancelling the task closes the underlying SSE connection automatically.

  6. Before you point real traffic at PromptHelm, run through this checklist:

    • Store the API token in the Keychain. Never read it from Info.plist or environment variables in shipped builds. Wrap the Keychain accessor in a small protocol so you can mock it in tests.
    • Handle errors with typed enums. Every SDK call throws PromptHelmError with a stable code. Map known codes to retries or user-facing alerts; let unknown codes bubble to your error reporter.
    • Cancel streaming Tasks on view teardown. Storing the Task in a @State property and calling task.cancel() from .onDisappear guarantees you do not leak SSE connections.
    • Set request deadlines. Pass a URLSession with a timeoutIntervalForRequest of 15 s (or use the SDK's timeout config option) so a slow provider never pins your UI.
    • Pin an environment. Default main to App Store traffic and promote new prompt versions through staging and dev first.

Next steps

On this page