---
title: "iOS SDK"
description: "Feedback tickets and store-then-send crash reporting for iOS (the Hands CocoaPod)."
category: "SDKs & API"
order: 11
---

# iOS SDK

`Hands` is the iOS SDK for Hands: in-app **feedback tickets** and
**crash reporting** posted to a Hands server's public
feedback endpoint. Objective-C, no dependencies, iOS 14.1+.

## Install (CocoaPods, via git)

```ruby
pod 'Hands', :git => 'https://github.com/botiverse/hands.git', :tag => 'ios-v0.2.1'
```

## Configure & start

All configuration is runtime parameters — the SDK ships nothing
app-specific. Get the client key from your app's **Settings** tab in the
Hands console (Sentry-DSN model: it identifies the app and ships in the
bundle; rotate it from the console if it leaks).

```swift
import Hands

Hands.install(with: HandsConfig(
    baseUrl: "https://hands.build",
    appSlug: "my-app",
    channel: "main",          // Hands release-channel routing field
    clientKey: "qk_…"
))
```

`install(with:)` installs the crash handlers and uploads any pending crash
reports a few seconds after launch. Call it as early as possible (app init).

## Feedback

```swift
Hands.submitFeedback(
    "Feed doesn't refresh after login.",
    kind: "bug",                      // "feedback" | "bug" | "crash"
    attachmentPaths: [logFilePath],   // up to 3 files, 10 MB each
    extras: nil
) { ticketId, error in … }
```

Device metadata (version, model, OS, arch, locale, per-install device id) is
attached automatically.

`Hands.install(with:)` also sends a throttled launch/install metrics ping for
active-device and version-distribution analytics. It carries no PII beyond the
random per-install Hands device id and build/OS metadata, and should not be
treated as a true online heartbeat.

## Crash reporting

`Hands.install(with:)` captures uncaught `NSException`s and fatal signals
and uploads them as `kind=crash` tickets, grouped by signature in the
console. Nothing else to wire.

## Notes

- The client key (`qk_…`) authenticates feedback/crash submissions. It ships
  inside the app bundle (Sentry-DSN model — app identifier, not a user
  secret); it is never logged or included in diagnostics exports.
- The device id is a random UUID, not a hardware id; it resets on reinstall.
