Getting Started
Guide to installing and initially configuring the Petnow iOS SDK.
Overview
This guide walks you through installing the Petnow iOS SDK into your project and performing the initial setup, step by step.
Prerequisites
Before you begin, make sure you have the following ready:
- An Xcode project targeting iOS 16.4 or later
- Xcode 16.0 or later
- A Petnow API key — issue one from the Petify Console (or contact support@petnow.io)
Step 1: Install the SDK
The Petnow iOS SDK is distributed via AWS CodeArtifact.
Install the AWS CLI
Install the AWS CLI from the following link: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
Issue credentials from the Petify Console
Issue AWS CodeArtifact credentials from My Page in the Petify Console, and set the environment variables with the provided values. (See the Petify Console doc for sign-up, payment-method registration, and key issuance.)

export AWS_ACCESS_KEY_ID=<from Petify Console>
export AWS_SECRET_ACCESS_KEY=<from Petify Console>
export AWS_DEFAULT_REGION=<from Petify Console>
export PETNOW_CODEARTIFACT_DOMAIN=<from Petify Console>
export PETNOW_AWS_ACCOUNT_ID=<from Petify Console>
export PETNOW_IOS_SDK_REPOSITORY=<from Petify Console>Swift Package Manager (AWS CodeArtifact)
The iOS SDK is installed via Swift Package Manager (SPM). CocoaPods support is planned.
Choose one of the following based on your project type:
Option A: Package.swift project
For a project that has a Package.swift file, you only need to run the following commands:
- Move to the project root directory:
cd /path/to/your-project # the directory containing Package.swift- Log in to AWS CodeArtifact (run this from a directory that contains
Package.swift— it invokesswift package-registry setinternally):
aws codeartifact login --tool swift \
--domain $PETNOW_CODEARTIFACT_DOMAIN \
--domain-owner $PETNOW_AWS_ACCOUNT_ID \
--repository $PETNOW_IOS_SDK_REPOSITORY \
--namespace petnow--namespace petnow configures a scoped registry matching the SDK's package scope (petnow.ui, etc.); without it, every package would be routed to this registry. The scoped registry mapping is written to the project's .swiftpm/configuration/registries.json.
- Confirm success:
# Output on success:
Successfully configured swift to use AWS CodeArtifact repository ...
Login expires in 12 hours ...
# Check the project registry file:
cat .swiftpm/configuration/registries.jsonThe token is valid for 12 hours; re-run the login command when it expires. The token value is not stored in registries.json — it is kept in the macOS keychain (the file only records the registry URL and the auth method). In CI/automated environments, inject the AWS credentials as secrets and run aws codeartifact login on every build to refresh the token — see the AWS CodeArtifact authentication tokens docs.
Option B: Xcode Workspace
Installing in CI/CD (keychain-free)
CI runners can't rely on the macOS keychain. Instead of aws codeartifact login (which uses the keychain), inject the token via ~/.netrc — this works headlessly. Put the AWS credentials in CI secrets, and because the token expires every 12 hours, issue it on each build.
# .github/workflows/ios.yml (example)
jobs:
build:
runs-on: macos-15
env:
AWS_ACCESS_KEY_ID: ${{ secrets.PETNOW_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.PETNOW_AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: ${{ secrets.PETNOW_AWS_REGION }}
PETNOW_CODEARTIFACT_DOMAIN: ${{ secrets.PETNOW_CODEARTIFACT_DOMAIN }}
PETNOW_AWS_ACCOUNT_ID: ${{ secrets.PETNOW_AWS_ACCOUNT_ID }}
PETNOW_IOS_SDK_REPOSITORY: ${{ secrets.PETNOW_IOS_SDK_REPOSITORY }}
steps:
- uses: actions/checkout@v4
- name: Configure CodeArtifact SwiftPM registry (netrc)
run: |
ENDPOINT=$(aws codeartifact get-repository-endpoint \
--domain "$PETNOW_CODEARTIFACT_DOMAIN" --domain-owner "$PETNOW_AWS_ACCOUNT_ID" \
--repository "$PETNOW_IOS_SDK_REPOSITORY" --format swift \
--query repositoryEndpoint --output text)
HOST=$(printf '%s' "$ENDPOINT" | sed -E 's#https?://([^/]+)/.*#\1#')
TOKEN=$(aws codeartifact get-authorization-token \
--domain "$PETNOW_CODEARTIFACT_DOMAIN" --domain-owner "$PETNOW_AWS_ACCOUNT_ID" \
--query authorizationToken --output text)
# token via netrc (no keychain). Valid for 12 hours.
printf 'machine %s login aws password %s\n' "$HOST" "$TOKEN" > ~/.netrc
chmod 600 ~/.netrc
# register the scoped registry (run where Package.swift exists)
swift package-registry set "$ENDPOINT" --scope petnow
- name: Resolve & build
run: swift package resolve --netrc && swift build --netrcThis flow (get-authorization-token → ~/.netrc → swift package-registry set --scope petnow → swift package resolve --netrc) was verified against the live registry. An Xcode app (.xcworkspace) uses xcodebuild instead of swift build, with the registry config placed in the workspace (xcshareddata/swiftpm/configuration/registries.json — see Option B). Do not commit ~/.netrc.
Adding the package in Xcode

- Open your project in Xcode
- Select File > Add Packages...
- Search for the
petnow.uipackage in the configured CodeArtifact repository - Click Add Package
Important: After typing the package name, you must press Enter. If you don't, the search won't run.
Verify the installation
Once the package is added successfully, you can confirm it in the Package Dependencies section of the project navigator.
Step 2: Configure the project
Add Info.plist permissions
For the SDK to use the camera, you must add a permission description to your Info.plist.
Add the "Privacy - Camera Usage Description" or "NSCameraUsageDescription" key, and enter a string explaining why the camera is used.

Required permissions
<!-- Camera access permission (required) -->
<key>NSCameraUsageDescription</key>
<string>Camera access is required to detect and identify pets.</string>Important: Without a permission description, the app will crash when accessing the camera.
Import the module
import PetnowUIStep 3: Create a capture session
Required: Before initializing the camera, you must create a capture session on your server and obtain a captureSessionId.
// Obtain the captureSessionId from your server
// (the server calls createCaptureSession in the Petnow Server API)
let captureSessionId: UUID = await yourServerAPI.createCaptureSession(
species: "DOG",
purpose: "PET_PROFILE_REGISTRATION"
)Server API: The captureSessionId is created on your server through the Petnow Server API. It is not created directly on the client.
Creating the capture session is your app server's responsibility (the client only uses the issued captureSessionId). The petId requirement depends on the purpose (required for registration/verification, not required for identification). For the creation parameters, the petId requirement, and the full server flow through result-image upload, see Server API – Biometric.
For more on session concepts, see the UI Module Overview.
Step 4: Initialize the camera
Initialize the camera with PetnowUI's CameraController. Pass the capture settings (DetectionConfiguration) and the API key (LicenseInfo) to the controller's initializer, then call initializeCamera afterward.
import SwiftUI
import PetnowUI
struct PetCameraView: View {
@StateObject private var controller: CameraController
private let captureSessionId: UUID // the session ID received from the server
init(captureSessionId: UUID) {
self.captureSessionId = captureSessionId
_controller = StateObject(wrappedValue: CameraController(
configuration: DetectionConfiguration(
species: .dog, // .dog or .cat
purpose: .petProfileRegistration // .petProfileRegistration / .petVerification / .petIdentification
),
licenseInfo: LicenseInfo(apiKey: "YOUR_API_KEY")
))
}
var body: some View {
CameraView(controller: controller)
.task { await initializeCamera() }
}
private func initializeCamera() async {
do {
try await controller.initializeCamera(
initialPosition: .back,
captureSessionId: captureSessionId
) { result in
switch result {
case let .success(fingerprintImages, appearanceImages):
// Arrays of local file:// URLs — upload to your app server
print("Capture complete: fingerprint \(fingerprintImages.count), appearance \(appearanceImages.count)")
case .fail:
print("Capture failed")
}
}
} catch {
print("Camera initialization failed: \(error)")
}
}
}DetectionConfiguration / LicenseInfo
DetectionConfiguration(species:purpose:enableFakeDetection:difficultyMode:)— capture settings.purposeis aDetectionPurpose(.petProfileRegistration/.petVerification/.petIdentification).LicenseInfo(apiKey:)— the API key. License validation is performed on the server atinitializeCameratime (once per key).
The previous approach of passing the license via
initializeCamera(licenseInfo:…)is deprecated. As shown above, injectlicenseInfointo the initializer and callinitializeCamerawithout the license argument.
Step 5: Verify the installation
To confirm the SDK is installed correctly, build and run your app.
If camera initialization succeeds, the camera preview is shown. On failure, check the error message:
do {
// licenseInfo was already passed to the CameraController(configuration:licenseInfo:) initializer above
try await controller.initializeCamera(
initialPosition: .back,
captureSessionId: captureSessionId
) { _ in
print("Capture complete")
}
print("Camera initialization succeeded")
} catch {
print("Initialization failed: \(error.localizedDescription)")
}Troubleshooting
Package not found (Package Resolution Failed)
Symptom: Xcode shows "package 'PetnowUI' not found" or a similar error
Solution:
-
Check the registry configuration
# Xcode Workspace project cat YourApp.xcworkspace/xcshareddata/swiftpm/configuration/registries.json # Package.swift project (the .swiftpm in the project root) cat .swiftpm/configuration/registries.jsonIf the file is missing or empty, log in again from a directory that contains
Package.swift(the Package.swift project root, or the Option B dummy project):cd /path/to/package-dir # the directory containing Package.swift aws codeartifact login --tool swift \ --domain $PETNOW_CODEARTIFACT_DOMAIN \ --domain-owner $PETNOW_AWS_ACCOUNT_ID \ --repository $PETNOW_IOS_SDK_REPOSITORY \ --namespace petnow -
Check for token expiration
- Tokens expire after 12 hours
- Run the
aws codeartifact logincommand again
-
Clear the Xcode cache
# Clear the SPM cache rm -rf ~/Library/Caches/org.swift.swiftpm rm -rf ~/Library/Developer/Xcode/DerivedData # After restarting Xcode, File > Packages > Reset Package Caches
Missing registry configuration (Xcode Workspace)
Symptom: Xcode can't find the package even after logging in
Cause: The scoped registry mapping is created in the .swiftpm/configuration/registries.json of the project (or dummy project) where you ran the login. The Xcode Workspace uses its own xcshareddata/swiftpm/configuration/registries.json, so you must copy it there for the workspace to recognize it.
Solution: Perform the registry configuration copy from Option B (run from the dummy project directory)
# Copy into the Xcode Workspace
mkdir -p YourApp.xcworkspace/xcshareddata/swiftpm/configuration
cp .swiftpm/configuration/registries.json YourApp.xcworkspace/xcshareddata/swiftpm/configuration/Camera permission error
Symptom: The app crashes or no permission prompt is shown
Solution: Verify that NSCameraUsageDescription is added to Info.plist
API key error
Symptom: Authentication error during camera initialization
Solution: Verify that the API key is correct and contact the Petnow team
Next steps
Installation and setup are complete! You're now ready to use the SDK.
- UI Module Overview - Understand the UI module structure
- Basic Usage - Integrate the camera UI
Support
If you run into problems during installation, contact support@petnow.io.