Skip to content

Search the documentation by title, section, or page text.

Create a Profile

POST https://api.botsi.com/v2/profiles

Call this on first app launch. It creates the Profile every other operation depends on. AI Pricing, subscriptions, and Paywall tracking all need one to exist.

Identifiers#

  • profileId: a unique ID Botsi returns. Use it to fetch Paywalls and track events.
  • appUserId: your own internal app user ID, which links the Profile across devices.

Store one of the two locally. Every later call identifies the user by one or the other.

Send appUserId even though it is optional

It is what ties a Botsi Profile to the user record in your own system, and what lets the same person be recognized on a second device.

Request body#

ParameterTypeRequiredDescription
countrystringRequiredCountry code, for example US. See below
devicestringRequiredDevice model, for example iPhone 15 Pro Max
osstringRequiredOperating system and version, for example iOS 17.0
platformstringRequiredPlatform type, for example ios
appVersionstringRequiredApp version, for example 1.0.0
appUserIdstringRecommendedYour app user ID, for example user-123
localestringOptionalLocale code, for example en_US
appBuildstringOptionalBuild number
ipAddressstringOptionalIP address. Returned as ip
advertisingIdstringOptionalAdvertising identifier
idfastringOptionalApple identifier for advertisers
emailstringOptionalEmail address
phonestringOptionalPhone number
usernamestringOptionalUsername
genderstringOptionalGender

platform accepts android, ios, ipados, tvos, macos, watchos, visionos, and stripe.

country takes a two-letter ISO 3166-1 alpha-2 code, or an uppercase three-letter alpha-3 code that Botsi can map to one. An alpha-3 value it cannot map is rejected with 400.

Unmodelled fields are discarded, not rejected

The API strips any field it does not model, so currency, billingCountry, timezone, osVersion, sessionId, and pushToken are accepted and silently ignored. They are not stored and never appear in the response.

A request carrying them succeeds, which means a typo in a field name fails the same quiet way. Check the response for the values you expect rather than assuming a 201 stored everything you sent.

curl -X POST "https://api.botsi.com/v2/profiles" \
  -H "Authorization: $BOTSI_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "country": "US",
    "device": "iPhone 15 Pro Max",
    "os": "iOS 17.0",
    "platform": "ios",
    "appVersion": "1.0.0",
    "appUserId": "user-123",
    "locale": "en_US",
    "appBuild": "100",
    "advertisingId": "6D92078A-8246-4BA4-AE5B-76104861E7DC",
    "ipAddress": "203.0.113.7"
  }'

Response#

The response echoes only the fields Botsi stores. Note that ipAddress comes back as ip.

{
  "ok": true,
  "data": {
    "profileId": "0072102a-c00c-4ea5-9271-1b6e975f2d63",
    "appUserId": "user-123",
    "country": "US",
    "locale": "en_US",
    "ip": "203.0.113.7",
    "device": "iPhone 15 Pro Max",
    "os": "iOS 17.0",
    "platform": "ios",
    "appVersion": "1.0.0",
    "appBuild": "100",
    "advertisingId": "6D92078A-8246-4BA4-AE5B-76104861E7DC",
    "createdAt": "2026-08-27T10:30:00.000Z",
    "updatedAt": "2026-08-27T10:30:00.000Z"
  }
}

Errors#

CodeMessageCause
400country must be a 2-letter ISO 3166-1 alpha-2 code or an uppercase 3-letter alpha-3 codeAn alpha-3 code Botsi cannot map, or a malformed value