Referrals API
Read recommendation links and referral relationships, inspect aggregate economics, and safely manage recommendation presentation through the Bkper Referrals API.
The Referrals API exposes the same self-scoped behavior used by the Bkper Referrals application. Scripts and agents can read the authenticated user’s recommendation link and relationships, inspect aggregate economics, update public recommendation copy, or remove a relationship.
Endpoints and discovery
| Resource | URL |
|---|---|
| Production API | https://referrals.bkper.app |
| Development API | https://referrals-dev.bkper.app |
| OpenAPI 3.1 contract | https://referrals.bkper.app/openapi.json |
| OAuth protected-resource metadata | https://referrals.bkper.app/.well-known/oauth-protected-resource |
| Agent index | https://referrals.bkper.app/llms.txt |
Use production for real user automation. Development uses the Bkper development environment and does not provide a public sandbox for production accounts.
Supported operations
| Operation | Method and path | Effect |
|---|---|---|
| Get recommendation link and relationships | GET /api/v1/referrals | Read-only |
| Get aggregate referred subscription value | GET /api/v1/economics?scope=user|billing | Read-only |
| Get public recommendation presentation | GET /public/v1/recommendations/{username} | Public and read-only |
| Publish or reset recommendation copy | PUT /api/v1/recommendation | Changes public presentation |
| Remove the caller’s current referrer | DELETE /api/v1/referrer | Removes a relationship |
| Remove one direct referral | DELETE /api/v1/referrals/{referredUserId} | Removes a relationship |
The API does not:
- send a recommendation link through email, messaging, or social services;
- create or claim a referral relationship from arbitrary user IDs;
- replace an established referrer;
- configure custom URLs, campaign parameters, rewards, or payouts.
A relationship is established only after someone follows an ordinary recommendation or Book invitation link and completes verified Bkper sign-in. The first established referrer wins. Self-referrals and circular relationships are rejected.
Authentication
Every /api/v1/* request requires a Bkper OAuth access token:
Authorization: Bearer BKPER_ACCESS_TOKENThe public recommendation endpoint and discovery resources do not require authentication.
For local scripts, authenticate the official CLI and place its short-lived token in an environment variable:
bkper auth loginexport BKPER_TOKEN="$(bkper auth token)"Do not put access tokens in source files, prompts, logs, URLs, or recommendation text.
Authenticated routes do not provide broad cross-origin browser access. Call them from server-side scripts or use the Referrals application on its own origin.
Get the recommendation link
curl --fail-with-body --silent \ --header "Authorization: Bearer ${BKPER_TOKEN}" \ "https://referrals.bkper.app/api/v1/referrals"The recommendationUrl field contains the exact public URL to share. It is null when the authenticated profile has no Bkper username.
A sharing automation should:
- Read
recommendationUrlfrom this response. - Ask the user to confirm the recipient and delivery channel.
- Pass the exact URL to the separately authorized email, messaging, or social tool.
The Referrals API itself does not contact recipients.
Read relationships
The same response returns:
profile: the authenticated user’s current public profile;referrer: the user’s current referrer ornull;referrals: direct referrals only;recommendationUrl: the canonical recommendation link.
Each relationship contains an immutable userId, current public profile when available, attribution source, and createdAt timestamp. A null related profile does not prevent relationship removal.
Only these attribution sources are returned:
RECOMMENDATION_LINKBOOK_INVITATION
Read aggregate economics
Request the user’s direct-referral scope:
curl --fail-with-body --silent \ --header "Authorization: Bearer ${BKPER_TOKEN}" \ "https://referrals.bkper.app/api/v1/economics?scope=user"Use scope=billing when the result should follow the caller’s current shared subscription billing owner. This gives members of the same billing scope one stable aggregate without exposing the billing owner’s relationship rows.
Important response semantics:
monthlyValueNanoUsdis an integer amount in USD nano-units.contributingCountcounts deduplicated eligible subscriptions.referralPlanscontains current plan labels for the caller’s direct referrals, without individual values.availability=unavailablemeans the valuation is unknown. Never interpret null amounts or counts as zero.- The API returns current subscription valuation, not AI allowance, cash, commission, or an earned balance.
Bkper AI separately applies the current Referral Program benefit policy.
Publish recommendation copy
Recommendation copy appears publicly on the user’s Bkper recommendation page. Obtain explicit approval of the final text before publishing it.
curl --fail-with-body --silent \ --request PUT \ --header "Authorization: Bearer ${BKPER_TOKEN}" \ --header "Content-Type: application/json" \ --data '{ "header": "Books that stay clear.", "subheader": "Automate repetitive work while keeping every balance reviewable." }' \ "https://referrals.bkper.app/api/v1/recommendation"Both fields are written together and both must be non-empty after normalization.
| Field | Maximum length |
|---|---|
header | 64 Unicode characters |
subheader | 140 Unicode characters |
The service trims surrounding whitespace, collapses repeated spaces and tabs, and rejects:
- line breaks;
- URLs and email addresses;
- angle brackets or markup-like text;
- control and bidirectional control characters;
- abusive, unsafe, impersonating, misleading, or unrelated promotional content.
A rejected or unavailable validation leaves the previously published message unchanged.
Reset recommendation copy
Obtain confirmation before resetting. Send both fields as null to restore the default Marketing presentation:
curl --fail-with-body --silent \ --request PUT \ --header "Authorization: Bearer ${BKPER_TOKEN}" \ --header "Content-Type: application/json" \ --data '{"header":null,"subheader":null}' \ "https://referrals.bkper.app/api/v1/recommendation"Remove relationships
Relationship removal does not assign a replacement or retain history. A future relationship requires a fresh recommendation or Book invitation. Always show the related public profile and obtain explicit confirmation immediately before either request.
Remove the authenticated user’s current referrer:
curl --fail-with-body --silent \ --request DELETE \ --header "Authorization: Bearer ${BKPER_TOKEN}" \ "https://referrals.bkper.app/api/v1/referrer"Remove one of the authenticated user’s direct referrals:
curl --fail-with-body --silent \ --request DELETE \ --header "Authorization: Bearer ${BKPER_TOKEN}" \ "https://referrals.bkper.app/api/v1/referrals/REFERRED_USER_ID"Both endpoints return 204 when the relationship is removed, absent, or unrelated. This idempotent behavior prevents relationship-existence disclosure. A client must not report that a relationship existed based only on the 204 response.
Errors
| Status | Meaning |
|---|---|
400 | Invalid parameters or recommendation format |
401 | Missing, expired, or invalid Bkper bearer token |
404 | Unknown username on the public recommendation endpoint |
422 | Recommendation copy rejected by safety validation |
503 | Identity, profile, validation, valuation, or referral storage unavailable |
Error responses use this shape:
{ "error": { "code": "INVALID_REQUEST", "message": "Invalid request parameters." }}Preserve the service’s safe error message for the user. Do not log access tokens or raw upstream authentication errors.
Automation safety
Before mutating Referrals data, an agent should:
- Read the current state.
- Explain the exact proposed change.
- Show the final recommendation text or related profile.
- Obtain explicit user confirmation.
- Perform only the confirmed request.
- Report the API response without inferring undisclosed relationship state.
Reading relationships, recommendation links, public presentation, and economics does not require mutation confirmation.