Mobile Integration
Penguin can be integrated into any platform that can make HTTP requests. All raw HTTP calls require two headers:
X-AM-API-Key: <your_api_key>— Your developer API keyAuthorization: Bearer <supabase_anon_key>— The Supabase anon key (see below)
:::info Supabase Anon Key The anon key is a public key that grants anonymous-level access to the API. It is not a secret. The TypeScript SDK includes it automatically. For raw HTTP integrations, use this value:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBlcnV3bmJycWt2bXJsZGhwb29tIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzgyNzg2NzQsImV4cCI6MjA1Mzg1NDY3NH0.kRBiByVkLLazr5bqM-vJtxij-IW4_MIQpcmzz8Niwqw
:::
iOS (Swift)
import Foundation
class PenguinClient {
let apiKey: String
let baseURL = "https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1"
let anonKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBlcnV3bmJycWt2bXJsZGhwb29tIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzgyNzg2NzQsImV4cCI6MjA1Mzg1NDY3NH0.kRBiByVkLLazr5bqM-vJtxij-IW4_MIQpcmzz8Niwqw"
init(apiKey: String) {
self.apiKey = apiKey
}
func search(query: String) async throws -> [String: Any] {
var request = URLRequest(url: URL(string: "\(baseURL)/api-v1/search")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("Bearer \(anonKey)", forHTTPHeaderField: "Authorization")
request.setValue(apiKey, forHTTPHeaderField: "X-AM-API-Key")
request.httpBody = try JSONSerialization.data(withJSONObject: ["query": query])
let (data, _) = try await URLSession.shared.data(for: request)
return try JSONSerialization.jsonObject(with: data) as! [String: Any]
}
}
Android (Kotlin)
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.net.HttpURLConnection
import java.net.URL
class PenguinClient(private val apiKey: String) {
private val baseUrl = "https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1"
private val anonKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
suspend fun search(query: String): String = withContext(Dispatchers.IO) {
val url = URL("$baseUrl/api-v1/search")
val conn = url.openConnection() as HttpURLConnection
conn.requestMethod = "POST"
conn.setRequestProperty("Content-Type", "application/json")
conn.setRequestProperty("Authorization", "Bearer $anonKey")
conn.setRequestProperty("X-AM-API-Key", apiKey)
conn.doOutput = true
conn.outputStream.write("""{"query":"$query"}""".toByteArray())
conn.inputStream.bufferedReader().readText()
}
}
Web (JavaScript)
const ANON_KEY = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...';
async function searchPenguin(query, apiKey) {
const response = await fetch(
'https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/api-v1/search',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${ANON_KEY}`,
'X-AM-API-Key': apiKey,
},
body: JSON.stringify({ query }),
},
);
return response.json();
}
REST API endpoints
For mobile and non-TypeScript integrations, use the REST API (/api-v1):
| Endpoint | Method | Description |
|---|---|---|
/api-v1/search | POST | Search for capabilities |
/api-v1/session/start | POST | Start interactive session |
/api-v1/session/message | POST | Send session message |
/api-v1/session/end | POST | End session |
/api-v1/feedback | POST | Submit feedback |
/api-v1/openapi.json | GET | OpenAPI 3.1.0 spec |
The OpenAPI spec at /api-v1/openapi.json can be imported into tools like Postman or used to generate client code for any language.