iOS + Transloadit
Upload from iOS with TransloaditKit while delegating every request signature to a trusted backend.
Executable recipe
Build the integration
This Swift example asks a backend to sign requests for one fixed Template, uploads a file, and polls the Assembly status.
- Add TransloaditKit with Swift Package Manager and create a backend signature endpoint.
- Require application authentication on the endpoint and sign only the exact string received with the Auth Secret.
- Initialize the SDK with the signature generator and pass a local file URL to createAssembly.
Package.swift
.package(
url: "https://github.com/transloadit/TransloaditKit",
.upToNextMajor(from: "3.0.0")
)signing-server.ts
import { createHmac, timingSafeEqual } from 'node:crypto'
import { createServer } from 'node:http'
const authSecret = process.env.TRANSLOADIT_SECRET
const appApiToken = process.env.APP_API_TOKEN
const templateId = process.env.TRANSLOADIT_TEMPLATE_ID
if (!authSecret || !appApiToken || !templateId) {
throw new Error('Server configuration is incomplete')
}
createServer(async (request, response) => {
const expectedToken = Buffer.from(`Bearer ${appApiToken}`)
const suppliedToken = Buffer.from(request.headers.authorization ?? '')
const isAuthorized =
expectedToken.length === suppliedToken.length && timingSafeEqual(expectedToken, suppliedToken)
if (request.method !== 'POST' || request.url !== '/transloadit/sign') {
response.writeHead(404).end()
return
}
if (!isAuthorized) {
response.writeHead(401).end()
return
}
let stringToSign = ''
for await (const chunk of request) {
stringToSign += chunk
if (stringToSign.length > 100_000) {
response.writeHead(413).end()
return
}
}
let params: unknown
try {
params = JSON.parse(stringToSign)
} catch {
response.writeHead(400).end()
return
}
const usesAllowedTemplate =
typeof params === 'object' &&
params !== null &&
!Array.isArray(params) &&
'template_id' in params &&
params.template_id === templateId
if (!usesAllowedTemplate) {
response.writeHead(403).end()
return
}
const digest = createHmac('sha384', authSecret).update(stringToSign).digest('hex')
response.writeHead(200, { 'content-type': 'text/plain' }).end(`sha384:${digest}`)
}).listen(3000)Uploader.swift
import Foundation
import TransloaditKit
final class Uploader {
private let templateId = "YOUR_TRANSLOADIT_TEMPLATE_ID"
private let transloadit: Transloadit
init(appSessionToken: String) {
transloadit = Transloadit(
apiKey: "YOUR_TRANSLOADIT_KEY",
sessionConfiguration: .default,
signatureGenerator: { stringToSign, completion in
Task {
do {
var request = URLRequest(
url: URL(string: "https://example.com/transloadit/sign")!
)
request.httpMethod = "POST"
request.httpBody = Data(stringToSign.utf8)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue(
"Bearer \(appSessionToken)",
forHTTPHeaderField: "Authorization"
)
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
let signature = String(decoding: data, as: UTF8.self)
completion(.success(signature))
} catch {
completion(.failure(error))
}
}
}
)
}
func upload(fileURL: URL) {
transloadit.createAssembly(templateId: templateId, andUpload: [fileURL]) { result in
print(result)
}.pollAssemblyStatus { result in
print(result)
}
}
}Authentication
- Initialize TransloaditKit with the public Auth Key and a signatureGenerator that sends each string-to-sign to your authenticated backend.
- The backend signs only permitted requests with the Workspace Auth Secret and returns the prefixed signature. The secret never belongs in the app bundle.
- The signature generator must always call its completion handler with success or failure; otherwise the SDK request remains pending.
Limitations and operational notes
- An iOS binary cannot keep an Auth Secret. Passing the secret directly to TransloaditKit is suitable only when exposure is an accepted risk.
- The create callback means the Assembly exists and uploads were scheduled; it does not mean file upload or processing has finished.
- Background URL sessions can schedule one task per tus chunk. Tune tusUploadChunkSize for the app’s background-transfer behavior.
- The dependency-free signer uses one server-configured bearer token for a runnable local example. Replace it with expiring per-user session validation and rate limits before production.
More integrations