iOS integration guide

Integrate BackgroundErase into an iOS app using our Swift API client, pick an image, remove the background, and save or share the transparent PNG result.

Matt
Written by Matt
Updated in March 2026

BackgroundErase provides a minimal Swift API client and iOS demo app so you can pick a photo, remove its background through the API, and save or share the result as a transparent PNG.

Quick summary: Add your API key to Info.plist, include BEN2Client.swift in your app, call removeBackground(...), and the API returns raw PNG bytes with transparency.


Requirements

  • Xcode 14 or newer
  • iOS 16 or newer
  • Swift 5.7 or newer
  • An active Business or Enterprise plan with API access

The demo app uses PhotosPicker and NavigationStack, which is why iOS 16+ is required.

Get your API key

  1. Create an account or sign in at backgrounderase.com/account.
  2. Purchase or upgrade your plan if needed at backgrounderase.com/pricing.
  3. Go to the API Access section in your account dashboard.
  4. Generate a new token and store it securely.

Install the demo or client

The easiest way to get started is to clone the Swift portion of the integration repository:

git clone --no-checkout https://github.com/BackgroundErase/api-integrations.git
cd api-integrations
git sparse-checkout init --cone
git sparse-checkout set Swift
git checkout main
cd Swift

Then open the Xcode project or workspace inside the Swift folder.

If you already have your own iOS app, you can just copy BEN2Client.swift into your target and optionally bring over the demo UI.

Configure Info.plist

By default, the client reads your API key from BG_ERASE_API_KEY in Info.plist. You should also add Photo Library permission strings if you want to save results to Photos.

<key>BG_ERASE_API_KEY</key>
<string>YOUR_API_KEY</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>We save your cutouts to your Photos library.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your photos to pick an image.</string>

After updating Info.plist: Clean the build folder, delete the app from the simulator or device, and run again.


The Swift client

The client uploads a single image under the field name image_file using multipart form data and returns raw PNG bytes.

import Foundation
import UIKit

public enum BEN2Error: Error, LocalizedError {
    case invalidResponse(Int, String)
    case notImage
    case encodeFailed

    public var errorDescription: String? {
        switch self {
        case .invalidResponse(let code, let body): return "HTTP \(code): \(body)"
        case .notImage: return "Server returned non-image data"
        case .encodeFailed: return "Could not encode image"
        }
    }
}

public final class BEN2Client {
    public static let shared = BEN2Client(
        apiKey: Bundle.main.object(forInfoDictionaryKey: "BG_ERASE_API_KEY") as? String ?? "YOUR_API_KEY"
    )

    private let apiKey: String
    private let baseURL = URL(string: "https://api.backgrounderase.com/v2")!
    private let session: URLSession

    public init(apiKey: String, session: URLSession = .shared) {
        self.apiKey = apiKey
        self.session = session
    }

    public func removeBackground(
        image uiImage: UIImage,
        filename: String = "image.jpg",
        jpegQuality: CGFloat = 0.9,
        timeout: TimeInterval = 60
    ) async throws -> Data {
        guard let data = uiImage.jpegData(compressionQuality: jpegQuality) else {
            throw BEN2Error.encodeFailed
        }
        return try await removeBackground(imageData: data, filename: filename, timeout: timeout)
    }

    public func removeBackground(
        imageData: Data,
        filename: String,
        timeout: TimeInterval = 60
    ) async throws -> Data {

        var request = URLRequest(url: baseURL)
        request.httpMethod = "POST"
        request.timeoutInterval = timeout

        let boundary = "----BEN2-\(UUID().uuidString)"
        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
        request.setValue(apiKey, forHTTPHeaderField: "x-api-key")

        let mime = Self.mimeType(for: filename)
        let body = Self.multipartBody(
            name: "image_file",
            filename: filename,
            mimeType: mime,
            fileData: imageData,
            boundary: boundary
        )

        request.httpBody = body
        request.setValue(String(body.count), forHTTPHeaderField: "Content-Length")

        let (data, response) = try await session.data(for: request)
        guard let http = response as? HTTPURLResponse else { throw URLError(.badServerResponse) }
        guard http.statusCode == 200 else {
            let msg = String(data: data, encoding: .utf8) ?? "<no body>"
            throw BEN2Error.invalidResponse(http.statusCode, msg)
        }

        return data // raw PNG bytes
    }

    private static func mimeType(for filename: String) -> String {
        switch (filename as NSString).pathExtension.lowercased() {
        case "jpg", "jpeg": return "image/jpeg"
        case "png":         return "image/png"
        case "heic":        return "image/heic"
        case "webp":        return "image/webp"
        default:            return "application/octet-stream"
        }
    }

    private static func multipartBody(
        name: String,
        filename: String,
        mimeType: String,
        fileData: Data,
        boundary: String
    ) -> Data {
        let CRLF = "\r\n"
        var data = Data()
        data.append("--\(boundary)\(CRLF)".data(using: .utf8)!)
        data.append("Content-Disposition: form-data; name=\"\(name)\"; filename=\"\(filename)\"\(CRLF)".data(using: .utf8)!)
        data.append("Content-Type: \(mimeType)\(CRLF)\(CRLF)".data(using: .utf8)!)
        data.append(fileData)
        data.append("\(CRLF)--\(boundary)--\(CRLF)".data(using: .utf8)!)
        return data
    }
}

Simple usage with UIImage

Once the client is in your project, you can call it directly with a UIImage:

import UIKit

let client = BEN2Client.shared // uses BG_ERASE_API_KEY from Info.plist

let pngBytes = try await client.removeBackground(
    image: myUIImage,
    filename: "image.jpg",
    jpegQuality: 0.9,
    timeout: 60
)

let cutout = UIImage(data: pngBytes) // PNG with transparency

The returned value is raw PNG data, so creating a UIImage from it gives you a cutout with transparency preserved.

Uploading arbitrary Data

If you already have image bytes instead of a UIImage, use the imageData overload:

let data: Data = ... // image bytes (jpg/png/heic/webp)

let pngBytes = try await client.removeBackground(
    imageData: data,
    filename: "photo.png",
    timeout: 60
)

Supported input extensions for MIME detection include: jpg, jpeg, png, heic, and webp. Other file types fall back to application/octet-stream.

Passing the API key manually

If you do not want to store the key in Info.plist, you can initialize the client manually:

let client = BEN2Client(apiKey: "YOUR_API_KEY")

Demo app workflow

The demo app is designed to be minimal and polished:

  • Pick an image from Photos or Files
  • Tap Remove Background
  • Preview the transparent result over a checkerboard
  • Save to Photos or share/export the PNG

For saving results, add-only Photos permission is recommended on modern iOS versions.

Troubleshooting tips

  • After changing Info.plist, clean the build folder and reinstall the app.
  • Make sure your plan includes API access.
  • Check that your API key is present under BG_ERASE_API_KEY.
  • Confirm you are running on iOS 16+.
  • Include the Xcode version, iOS version, and reproduction steps when reporting issues.