> For the complete documentation index, see [llms.txt](https://docs.bitbond.com/asset-tokenization-suite/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.bitbond.com/asset-tokenization-suite/offering-manager/offering-manager-api.md).

# Offering Manager API

The Bitbond Offering Manager Platform provides a public REST API under `/api/public` to integrate investor-facing flows into your own applications. You can:

* Retrieve offering details
* Create and manage investor orders
* Track abandoned checkouts
* Process payments (SEPA/wire bank transfer, card via <https://www.checkout.com>, on-chain stablecoin)
* Integrate identity verification (Sumsub <https://sumsub.com> and Blockpass <https://www.blockpass.org>)
* Manage investor profiles and multi-chain wallets (EVM, Solana, Stellar, XRPL)
* Export or erase investor data (GDPR)
* Unsubscribe from activation emails

The API follows RESTful conventions and returns JSON responses.

Integration with issuer management APIs (for creating offerings, documents, discount tiers, and administrative workflows) is available under `/api/*` and requires a tenant API key or session JWT. Refer to the [Public API Reference](https://om.bitbond.com/api/docs) for details.

## Two Hostnames: Docs vs. API Calls

The platform uses two hostnames for API-related traffic:

* **om.bitbond.com** hosts the app itself and the interactive API docs UI at `/api/docs`. Browse the docs here in a real browser.
* **api.om.bitbond.com** is a dedicated hostname for programmatic (server-to-server) API calls under `/api/*` (offerings, orders, investors, settings, etc.). Always call the API here – om.bitbond.com runs a browser bot challenge in front of `/api/*` that blocks non-browser clients.

Always browse the docs at <https://om.bitbond.com/api/docs>, but call the API at <https://api.om.bitbond.com>.

## Public API Base URLs

Investor-facing endpoints under `/api/public` (browser and mobile clients using a Privy ID token) are called against the app origin:

```
https://om.bitbond.com/api/public
```

Issuer and integration endpoints (under `/api/*`, authenticated with a tenant API key or session JWT) should be called against the dedicated API host:

```
https://api.om.bitbond.com/api
```

Tenants are identified by a `subdomain` slug passed as a query parameter or URL path segment (for example, `/invest/acme-gmbh/my-offering`). There are NO tenant-specific domains like `acme.om.bitbond.com`.

## Authentication

### Investor-Facing Endpoints (`/api/public/*`)

* **Public endpoints** (e.g. retrieving offering details, token metadata) require no authentication.
* **Protected endpoints** (orders, payments, KYC, profile, checkout-intent, GDPR export/erase) require a Privy ID token. Include it in the `Authorization` header:

  ```
  Authorization: Bearer <PRIVY_ID_TOKEN>
  ```

  Requests without a valid token receive a `401 Unauthorized` response.

### Issuer Integration Endpoints (`/api/*`)

Require either:

* A **tenant API key** (Enterprise plan) generated in **Settings > API Access**, or
* A **session JWT** obtained via the authentication endpoints.

Include it as:

```
Authorization: Bearer <token>
```

Call these endpoints against `https://api.om.bitbond.com`, not `https://om.bitbond.com`.

## Idempotency

Write endpoints in the public API accept an `Idempotency-Key` header so retries cannot create duplicates. Supported routes include:

* `POST /public/orders`
* `POST /public/orders/{id}/cancel`
* `POST /public/payments/checkout-session`
* `POST /public/payments/checkout-pay`
* `POST /public/kyc/init`
* `PATCH /public/investor/profile`
* `POST /public/checkout-intent`
* `POST /public/investor/gdpr/erase`

Header format:

```
Idempotency-Key: <opaque string, 1–255 chars>
```

The same key and body within 24 hours returns the cached response with `Idempotent-Replayed: true`. After 24 hours the key is forgotten.

## API Documentation (OpenAPI/Swagger)

The full, interactive API reference is available as the [Public API Reference](https://om.bitbond.com/api/docs). This portal provides:

* A complete list of available endpoints
* Request and response schemas
* Ability to try out calls directly from the browser
* Authentication setup instructions

Browse the docs at <https://om.bitbond.com/api/docs>, but make real API calls against <https://api.om.bitbond.com>.

## Available Endpoints

### Offerings

**GET /offerings/:slug?subdomain=\<tenant\_subdomain>**\
Retrieve offering details, live fundraising totals, payment configuration, and investor wallet policy.

Query parameter:

* `subdomain` (required): the tenant’s subdomain

Successful response includes:

* Core offering fields (`slug`, `name`, `description`, `funding_target`, `hard_cap`, etc.)
* `documents`: array of `{ id, display_name, requires_agreement }`
* `discount_tiers`: array of `{ id, min_amount, max_amount, discount_pct, label }`
* `liveStats`: current totals and progress
* `tenantBankDetails`: `{ bankName, accountHolderName, iban, bic }`
* `paymentConfig`:
  * `hasCheckoutCom` (boolean)
  * `checkoutComPublicKey` (string or `null`)
  * `hasEvmCrypto` (boolean)
  * `hasCustodian` (boolean)
  * `custodianProvider` (string)
  * `acceptedTokens` (array of stablecoin symbols)
  * `acceptedChains` (array of supported blockchain IDs)
* `investorWalletPolicy` (string): one of `byo_only`, `investor_choice`, `custodial_only`

Error cases:

* `400 Bad Request` if `subdomain` is missing
* `403 Forbidden` if the investor’s country (via `CF-IPCountry` header) is blocked
* `404 Not Found` if the tenant or offering is not found, or not active

### Documents

**GET /documents/:docId/download**\
Download an offering document (PDF). Returns the PDF inline with:

* `Content-Disposition: inline; filename="<display_name>.pdf"`
* `Content-Type: application/pdf`

### Token Info

**GET /token-info?chain=\<chain\_id>\&address=\<contract\_address>**\
Lookup on-chain token metadata (name, symbol, decimals).

Query parameters:

* `chain` (required)
* `address` (required)

Successful response:

```json
{ "name": "...", "symbol": "...", "decimals": 18 }
```

Error responses:

* `400 Bad Request` for missing/invalid parameters
* `404 Not Found` if unknown
* `429 Too Many Requests` when rate limited

### Order Management

**POST /orders**\
Create a new investor order. Requires a Privy ID token.

Request body:

* `offeringId` (string, required)
* `fiatAmount` (number, required)
* `tokenAmount` (number, required)
* `paymentMethod` (one of `bank_transfer`, `checkout_com`, `stablecoin`, required)
* `walletAddress` (string, optional)
* `walletChainType` (string, optional)
* `cryptoNetwork` (string, optional)
* `agreedDocumentIds` (array of IDs, optional)
* `investorProfile` (object, optional)

Returns `201 Created` with:

* `order`: the newly created order
* `bankDetails` (for `bank_transfer`)
* `cryptoDepositAddress` (for `stablecoin`)

**GET /orders/investor/portfolio?subdomain=\<tenant\_subdomain>**\
Retrieve the authenticated investor’s orders for a tenant.

Query parameter:

* `subdomain` (required)

Response:

* `orders`: array of orders, each including `cancellationDeadline`, `canCancel`
* `walletAddress` (string or `null`): primary EVM address
* `wallets`: map of chain types to addresses

**GET /orders/:referenceCode**\
Retrieve details for a single order by its reference code (includes `cancellationDeadline`, `canCancel`).

**POST /orders/:id/cancel**\
Cancel a pending order within its allowed window.

### Checkout Intent

**POST /checkout-intent**\
Track or update an abandoned checkout intent. Requires a Privy ID token.

Request body:

* `offeringId` (string, required)
* `fiatAmount` (number, optional)
* `lastSeenStep` (string, required)

Successful response:

```json
{ "id": "..." }
```

Error cases:

* `401 Unauthorized` if missing/invalid token
* `404 Not Found` if the offering is not active
* `500 Internal Server Error` on failure

### Payment Processing

**GET /payments/checkout-config?subdomain=\<tenant\_subdomain>**\
Retrieve the tenant’s Checkout.com public key configuration. No authentication required.

Query parameter:

* `subdomain` (required)

Response:

```json
{ "publicKey": "...", "configured": true }
```

**POST /payments/checkout-session**\
Create a Checkout.com payment session for a pending order. Requires a Privy ID token.

Request body:

* `orderId` (string, required)

Returns:

* `sessionId`
* `sessionToken`
* `publicKey`

**POST /payments/checkout-pay**\
Complete a card payment via Checkout.com using a Frames.js card token. Requires a Privy ID token.

Request body:

* `orderId` (string, required)
* `cardToken` (string, required)

Returns the payment result or error details (`402` if not authorized).

### KYC Workflow

Configure your identity verification provider in **Settings**:

* Sumsub: <https://sumsub.com>
* Blockpass: <https://www.blockpass.org>

Endpoints:

**POST /kyc/init**\
Initialize KYC for an offering. Requires a Privy ID token.

Request body:

* `offeringId` (string, required)
* `investorType` (`individual` or `institutional`, defaults to `individual`)

Returns:

* For Sumsub:

  ```json
  { "provider": "sumsub", "sdkToken": "...", "levelName": "..." }
  ```
* For Blockpass: provider response with redirect/widget parameters

Error cases:

* `404 Not Found` if offering not found or KYC not required
* `400 Bad Request` if investor type not allowed or no provider configured

**GET /kyc/status**\
Poll the status of the authenticated investor’s verification. Requires a Privy ID token.

Response:

```json
{ "kyc_status": "...", "kyc_record_id": "..." }
```

### Investor Profile & Wallets

**GET /investor/profile**\
Fetch the authenticated investor’s profile. Requires a Privy ID token.

Response:

```json
{
  "profile": { /* personal and company fields, kyc_status, kyc_record_id */ },
  "wallets": { /* map of chain types to { address, source } */ },
  "walletList": [ /* array of { chain_type, address, source } */ ],
  "walletHistory": [ /* audit entries { id, wallet_address, chain_type, set_at, replaced_at } */ ],
  "hasConfirmedOrder": true
}
```

**PATCH /investor/profile**\
Add, update, or remove a wallet address. Requires a Privy ID token.

Request body:

* `walletAddress` (string or `null`, required)
* `chainType` (one of `evm`, `solana`, `stellar`, `xrpl`; defaults to `evm`)

Response:

```json
{ "message": "Wallet address updated", "walletAddress": "...", "chainType": "evm" }
```

Error cases:

* `400 Bad Request` if invalid address for the chosen chain
* `404 Not Found` if the user is not found

### GDPR

**GET /investor/gdpr/export**\
Export the authenticated investor’s data as JSON. Requires a Privy ID token.\
Response: JSON object containing the investor’s profile, orders, wallets, KYC records, and audit logs.

**POST /investor/gdpr/erase**\
Request erasure of the authenticated investor’s personal data. Requires a Privy ID token.\
Response:

* `204 No Content` on success

### Activation Emails

**GET /activation-emails/unsubscribe?tenant=\<tenant\_id>\&token=\<token>**\
Unsubscribe the specified tenant from activation emails. Returns an HTML confirmation page.

**GET /unsubscribe-activation?tenant=\<tenant\_id>\&token=\<token>**\
Alias of the unsubscribe endpoint for backward compatibility.

## Common Use Cases

* Build a custom investor UI powered by offering data, documents, and live stats
* Integrate investor data, order statuses, or payment sessions with CRM or accounting tools
* Automate workflows: programmatic order creation, KYC initiation, wallet management
* Support on-chain stablecoin deposits alongside traditional payment rails
* Provide investor self-service data export or erasure to comply with GDPR
* Allow workspace administrators to unsubscribe from activation emails via a simple link

## API Scope

The public API covers all investor-facing flows, including offering discovery, order management, checkout intents, payment sessions, KYC initiation, wallet management, GDPR export/erase, and activation-email unsubscribe. It does **not** include administrative operations (use the admin panel for offering configuration, team settings, and audit exports).

For the complete request and schema reference, see the [Public API Reference](https://om.bitbond.com/api/docs). Remember: browse the docs at <https://om.bitbond.com/api/docs>, but call the API at <https://api.om.bitbond.com>.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.bitbond.com/asset-tokenization-suite/offering-manager/offering-manager-api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
