PeqabooPeqaboo
User GuideVetSheetBlogNewsroom
ExploreLogin
PeqabooPeqabooPeqaboo

Your Boo AI Pet Care Companion

+852 9661 0906

Entrepreneurship Centre, Level 5, Core F, Cyberport 3, 100 Cyberport Road, Hong Kong

NavigateHomeAbout Peqaboo AIHow it worksFAQContact
ResourcesUser GuideVetSheetVetSheetBOOlogNewsroomDevelopers
LegalTerms of ServicePrivacy PolicyCommunity Guidelines
© 2026 Decennium Platforms Limited
BooApp Platform
QuickstartSDKPermissionsSubmitExamplesLLM Prompt

SDK Reference

The peqaboo global API

Every method below is available on the auto-injected peqaboo global. No import, no install. Always await peqaboo.ready() before calling anything else.

Namespaces

LifecycleAuthPetMediaStorageLocationPaymentNotificationChatDeviceDataCollectionsSharedProfileEventsContactsReminderRecordNotificationScheduleMarket
setup.ts
/// <reference types="@decennium/booapp-sdk" />
// peqaboo is auto-injected — no import line needed.

Lifecycle

Bridge readiness, environment detection, and runtime metadata. Always call ready() before anything else.

peqaboo.ready(): Promise<void>

Resolves once the native bridge has handshaked. Always await before calling other APIs.

Returns

Promise<void>
ts
await peqaboo.ready();
console.log('Bridge ready, version', peqaboo.bridgeVersion);
peqaboo.isInApp: boolean

true when running inside the Peqaboo WebView; false in a plain browser. Use to conditionally fall back.

Returns

boolean
ts
if (!peqaboo.isInApp) {
  document.body.innerHTML = 'Open in Peqaboo to use this app.';
  return;
}
peqaboo.platform: 'ios' | 'android' | 'web'

Host platform reported by the bridge.

Returns

'ios' | 'android' | 'web'
ts
if (peqaboo.platform === 'ios') { /* iOS-specific tweak */ }
peqaboo.bridgeVersion: number

Native bridge version. v3 supports permission scopes; v2 is legacy.

Returns

number
ts
if (peqaboo.bridgeVersion < 3) {
  alert('Please update Peqaboo to use this BooApp.');
}
peqaboo.lang: string

BCP-47 language tag of the user (e.g. zh-HK, en-US).

Returns

string
ts
const isChinese = peqaboo.lang.startsWith('zh');
peqaboo.uid: string | null

Current logged-in user id, or null if not logged in. Use requireLogin() to force login.

Returns

string | null
ts
if (!peqaboo.uid) await peqaboo.requireLogin();

Auth

User identity. Login is handled by Peqaboo — your BooApp just asks who the user is.

peqaboo.requireLogin(): Promise<User>

Returns the current user. If no user is logged in, opens the native login flow first. Resolves with the User object after success.

scope: auth.requireLogin

Returns

Promise<User>
ts
const user = await peqaboo.requireLogin();
console.log(user.uid, user.name, user.avatarUrl);

Pet

Pet records the user has added in Peqaboo. Read-only by default; update requires explicit user grant.

peqaboo.pet.list(): Promise<Pet[]>

List all pets owned by the current user.

scope: pet.list

Returns

Promise<Pet[]>
ts
const pets = await peqaboo.pet.list();
pets.forEach(p => console.log(p.name, p.species));
peqaboo.pet.read(petId: string): Promise<Pet>

Read a single pet by id. Includes full profile, breed, birth date, photo URLs.

scope: pet.read

Parameters

  • petId string — The petId from pet.list().

Returns

Promise<Pet>
ts
const pet = await peqaboo.pet.read('pet_abc123');
console.log(pet.weight, pet.allergies);
peqaboo.pet.update(petId, patch): Promise<Pet>

Update fields on a pet. The user is shown a confirm sheet before any write.

scope: pet.update

Parameters

  • petId string — Target pet id.
  • patch Partial<Pet> — Fields to update.

Returns

Promise<Pet>
ts
await peqaboo.pet.update('pet_abc123', { weight: 5.4 });

Media

Pick or capture images and videos. Returns native File objects you can upload via storage.upload.

peqaboo.media.pickImage(opts?): Promise<File>

Open the native image picker. Set opts.source = 'camera' to skip directly to camera.

scope: media.pickImage

Parameters

  • opts.source 'camera' | 'library' — Default is library.
  • opts.maxSize number — Max edge length in px before downscale.

Returns

Promise<File>
ts
const file = await peqaboo.media.pickImage({ source: 'camera' });
const url = await peqaboo.storage.upload(file);
peqaboo.media.pickVideo(opts?): Promise<File>

Pick or capture a video.

scope: media.pickVideo

Returns

Promise<File>
ts
const video = await peqaboo.media.pickVideo({ maxDuration: 30 });
peqaboo.media.takePhoto(): Promise<File>

Open the native camera directly, skipping the chooser.

scope: media.takePhoto

Returns

Promise<File>
ts
const photo = await peqaboo.media.takePhoto();

Storage

Upload files to Peqaboo Cloud Storage. Returns a public CDN URL you can render or save.

peqaboo.storage.upload(file, opts?): Promise<string>

Upload a file. Files are scoped to your BooApp and the current user; other apps cannot read them.

scope: storage.upload

Parameters

  • file File — A File from media.* or a blob.
  • opts.path string — Optional sub-path within your app scope.

Returns

Promise<string>
ts
const file = await peqaboo.media.pickImage();
const url = await peqaboo.storage.upload(file, { path: 'cards/' });
img.src = url;

Location

Read the user's location. One-shot or subscription.

peqaboo.location.getCurrent(): Promise<Coords>

Returns one geolocation reading. Triggers a native permission prompt the first time.

scope: location.getCurrent

Returns

Promise<{ lat: number; lng: number; accuracy: number }>
ts
const { lat, lng } = await peqaboo.location.getCurrent();
peqaboo.location.subscribe(cb): () => void

Subscribe to position updates. Returns an unsubscribe function.

scope: location.subscribe

Returns

() => void
ts
const unsub = peqaboo.location.subscribe(coords => {
  console.log(coords.lat, coords.lng);
});
// later
unsub();

Payment

Charge the user. Always shows a native confirm sheet — high-tier scope, never silent.

peqaboo.payment.request(opts): Promise<PaymentResult>

Request a payment. The user sees a native modal with full breakdown and must tap Confirm.

scope: payment.request

Parameters

  • opts.amount number — Amount in minor units (e.g. cents).
  • opts.currency string — ISO 4217, e.g. HKD, USD.
  • opts.description string — What the user is paying for.

Returns

Promise<{ paymentId: string; status: 'success' | 'cancelled' }>
ts
const r = await peqaboo.payment.request({
  amount: 4800, currency: 'HKD',
  description: 'Loyalty card stamp set'
});
if (r.status === 'success') unlockReward();

Notification

Send push to the current user (e.g. reminders for the BooApp).

peqaboo.notification.send(opts): Promise<void>

Schedule a push for the current user. Useful for reminders, follow-ups, drip flows.

scope: notification.send

Parameters

  • opts.title string — Notification title.
  • opts.body string — Notification body.
  • opts.scheduleAt number — Unix ms timestamp. Omit to send now.
  • opts.deeplink string — Optional path inside your BooApp to open on tap.

Returns

Promise<void>
ts
await peqaboo.notification.send({
  title: 'Daily walk',
  body: 'Time to walk Mochi!',
  scheduleAt: Date.now() + 8 * 3600 * 1000,
});

Chat

Open a chat with another Peqaboo user.

peqaboo.chat.openWith(uid, opts?): Promise<void>

Open the native chat sheet. You can prefill a starter message for the user to send.

scope: chat.openWith

Parameters

  • uid string — Target user id.
  • opts.prefill string — Optional draft text to seed the input.

Returns

Promise<void>
ts
await peqaboo.chat.openWith('user_xyz', {
  prefill: 'Hi! I saw your post about the puppy class…'
});

Device

Native device features — share sheet, haptics, QR scanner.

peqaboo.device.share(opts): Promise<void>

Open the native share sheet.

scope: device.share

Parameters

  • opts.title string — Share title.
  • opts.text string — Body text.
  • opts.url string — Optional URL to share.

Returns

Promise<void>
ts
await peqaboo.device.share({
  title: 'Mochi got a new card!',
  url: 'https://peqaboo.app/cards/abc',
});
peqaboo.device.haptic(type): void

Trigger a haptic tap. Sync — no await needed.

scope: device.haptic

Parameters

  • type 'light' | 'medium' | 'heavy' — Intensity.

Returns

void
ts
peqaboo.device.haptic('light');
peqaboo.device.scanCode(): Promise<string>

Open the native QR scanner. Resolves with the decoded payload.

scope: device.scanCode

Returns

Promise<string>
ts
const code = await peqaboo.device.scanCode();
console.log('Scanned:', code);

Data

Per-user key/value store. Scoped to your BooApp + the current user. Persists across sessions.

peqaboo.data.set(key, value): Promise<{ key, value }>

Set/replace a value. Max 100 KB serialised.

scope: data.write

Returns

Promise<{ key, value }>
ts
await peqaboo.data.set('streakCount', 7);
peqaboo.data.get(key): Promise<{ key, value, exists }>

Read a value. Returns null when missing.

scope: data.read

Returns

Promise<{ key, value, exists }>
ts
const { value } = await peqaboo.data.get('streakCount');
peqaboo.data.delete(key): Promise<void>

Delete a key. No-op if absent.

scope: data.write

Returns

Promise<void>
ts
await peqaboo.data.delete('streakCount');
peqaboo.data.list(): Promise<{ keys: Array<{ key, _updatedAt }> }>

List keys (latest 500).

scope: data.read

Returns

Promise<{ keys: ... }>
ts
const { keys } = await peqaboo.data.list();

Collections

Per-user collections that mirror Firestore — add/set/update/delete/get/list/onChange. Auto _createdAt + _updatedAt timestamps.

peqaboo.collection(name).add(doc): Promise<T & { id }>

Append with auto-id. Doc cap: 100 KB, 100 top-level fields.

scope: data.write

Returns

Promise<T & { id }>
ts
const visits = peqaboo.collection('visits');
const r = await visits.add({ petId: 'p1', rating: 5 });
collection.list(opts?): Promise<{ docs, cursor, hasMore }>

Filtered query. If a composite index is missing the call throws QueryNeedsIndexError once — the platform auto-files a deploy ticket; retry in ~5 min.

scope: data.read

Returns

Promise<QueryResult<T>>
ts
const page = await visits.list({
  where: [['petId', '==', 'p1']],
  orderBy: [['_createdAtDate', 'desc']],
  limit: 20,
});
collection.onChange(cb, opts?): () => void

5-second polling fallback (true streaming planned).

scope: data.read

Returns

() => void
ts
const off = visits.onChange(page => render(page), {
  where: [['petId', '==', 'p1']],
});
// later: off();

Shared

Cross-user (BooApp-wide) collections. Append + read only. Writes rate-limited to 10/min/uid.

peqaboo.shared.collection(name).add(doc): Promise<T & { id, _authorUid }>

Append a public doc visible to every user of your BooApp.

scope: data.shared.write

Returns

Promise<T & { id, _authorUid }>
ts
await peqaboo.shared.collection('leaderboard').add({ score: 99 });
peqaboo.shared.collection(name).list(opts?): Promise<QueryResult<T>>

Read shared collection.

scope: data.shared.read

Returns

Promise<QueryResult<T>>
ts
const top = await peqaboo.shared.collection('leaderboard').list({
  orderBy: [['score', 'desc']], limit: 10,
});

Profile

Distribution channels (Phase 9e). Pin THIS BooApp on the caller's public profile so other users see it under the Apps rail when they visit the profile.

peqaboo.profile.pinThisApp(): Promise<{ appId, pinned }>

Set `installs/{uid}.pinned = true` for this BooApp. The user's public profile then shows it under the Pinned rail.

scope: profile.pin

Returns

Promise<{ appId: string; pinned: true }>
ts
// After delivering value (e.g. user printed their NFC card),
// prompt them to pin so friends can discover it.
await peqaboo.profile.pinThisApp();
peqaboo.profile.unpinThisApp(): Promise<{ appId, pinned }>

Remove this BooApp from the user’s pinned rail.

scope: profile.pin

Returns

Promise<{ appId: string; pinned: false }>
ts
await peqaboo.profile.unpinThisApp();

Events

Subscribe to native events pushed by the platform — lifecycle, push, NFC, keyboard.

peqaboo.on(event, cb): () => void

Subscribe to a Bridge Event. Returns an unsubscribe function. Known events: appResume, appPause, authTokenRefreshed, pushReceived, nfcTagDetected, keyboardShow, keyboardHide.

Returns

() => void
ts
const off = peqaboo.on('appResume', () => {
  refreshData();
});
// later
off();

Contacts

Read the user's friends and recent chat partners — useful for picking a recipient, sharing inside the user's social graph, or showing a recent-activity rail. Reuses the existing Peqaboo friend + chat APIs.

peqaboo.contacts.list(opts?): Promise<{ contacts: ContactRow[] }>

List the user's friends + recent chat partners. opts.source = 'friends' | 'chat' | 'all' (default 'all').

scope: contacts.read

Returns

Promise<{ contacts: ContactRow[] }>
ts
const { contacts } = await peqaboo.contacts.list({ source: 'friends' });
peqaboo.contacts.pick(): Promise<ContactRow | null>

Show a native bottom-sheet contact picker (Friends / Recent tabs). Resolves with the picked row or null on cancel.

scope: contacts.read

Returns

Promise<ContactRow | null>
ts
const c = await peqaboo.contacts.pick();
if (c) await peqaboo.chat.openWith(c.uid);

Reminder

Add reminders into the user's existing pet reminders. Tagged with this BooApp's id so the BooApp can list and delete only the reminders it created. Rate limit: 10 writes / day / user.

peqaboo.reminder.add(data): Promise<Reminder>

Add a reminder. Body: { petId, title, dueAt (ISO), repeat?, notes? }. Writes to the petReminders collection scoped with sourceBooAppId.

scope: reminder.write

Returns

Promise<Reminder>
ts
await peqaboo.reminder.add({
  petId: 'p1',
  title: 'Walk Mochi',
  dueAt: new Date(Date.now() + 3600_000).toISOString(),
});
peqaboo.reminder.list(): Promise<{ reminders: Reminder[] }>

List reminders this BooApp created (others are hidden).

scope: reminder.write

Returns

Promise<{ reminders: Reminder[] }>
ts
const { reminders } = await peqaboo.reminder.list();
peqaboo.reminder.delete(reminderId): Promise<void>

Delete a reminder. Only succeeds if the reminder was created by this BooApp.

scope: reminder.write

Returns

Promise<void>
ts
await peqaboo.reminder.delete(r.reminderId);

Record

Add pet records (vaccine, vet visit, weight log, …) into the user's existing petRecords timeline. Confirms every call (high tier) because pet records are medical-adjacent. Rate limit: 20 writes / day / user.

peqaboo.record.add(data): Promise<Record>

Add a pet record. Body: { petId, type, occurredAt (ISO), notes?, attachments? }. Writes to petRecords with sourceBooAppId.

scope: record.write

Returns

Promise<Record>
ts
await peqaboo.record.add({
  petId: 'p1',
  type: 'vaccine',
  occurredAt: new Date().toISOString(),
  notes: 'Annual rabies booster',
});

NotificationSchedule

Schedule a push notification to fire at a future time. The platform's cron dispatcher (1 minute granularity) picks up due rows and fires via the existing push system. Rate limit: 5 / day / user.

peqaboo.notification.schedule(opts): Promise<{ pushId, when, title }>

Schedule a push. Body: { when (ISO, future), title, body, link?, imageUrl?, actions? }.

scope: notification.schedule

Returns

Promise<{ pushId: string; when: string; title: string }>
ts
await peqaboo.notification.schedule({
  when: new Date(Date.now() + 8 * 3600_000).toISOString(),
  title: 'Daily walk',
  body: 'Time to walk Mochi!',
});

Market

Search and read the Peqaboo marketplace product catalog. Filtered to live, sellable products (marketStatus listed | onSale | available). Read-only — purchase still requires payment.request.

peqaboo.market.search(q): Promise<{ hits: ProductHit[]; count; query }>

Search products. Returns up to 30 hits.

scope: market.read

Returns

Promise<{ hits: ProductHit[]; count: number; query: string }>
ts
const { hits } = await peqaboo.market.search('cat food');
peqaboo.market.get(productId): Promise<ProductDetail>

Read a single product detail.

scope: market.read

Returns

Promise<ProductDetail>
ts
const detail = await peqaboo.market.get(hits[0].productId);