# Offering Manager API

The Bitbond Offering Manager Platform provides a public REST API under `/api/public` that allows you 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>, stablecoin), integrate identity verification, manage investor profiles and multi-chain wallets, export or erase investor data (GDPR), and 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.

## Public API Base URL

All public endpoints are available under:

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

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 under `/api/public` follow two patterns:

* Public endpoints (such as retrieving offering details and 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 under `/api/*` require either:

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

## 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 all available endpoints.
* Request and response schemas for each endpoint.
* The ability to try out API calls directly from the browser.
* Authentication setup instructions.

## 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 against fundraising targets
  * `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 for this offering.
  * `404 Not Found` if the tenant or offering is not found, or the offering is not active.

### Documents

* **GET /documents/:docId/download**\
  Download an offering document (PDF) for an active or closed offering. 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) for supported networks.

  Query parameters:

  * `chain` (required): the network ID
  * `address` (required): the token contract address

  Successful response:

  * `{ name, symbol, decimals }`

  Error responses may include:

  * `400 Bad Request` for missing or invalid parameters
  * `404 Not Found` if the token or chain is unknown
  * `429 Too Many Requests` when rate limiting
  * Error payload with `error` and `kind` fields for diagnostics

### 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` (string, one of `bank_transfer`, `checkout_com`, `stablecoin`, required)
  * `walletAddress` (string, optional)
  * `walletChainType` (string, optional)
  * `cryptoNetwork` (string, optional)
  * `agreedDocumentIds` (array of document IDs, optional)
  * `investorProfile` (object, optional) — to collect or update KYC/AML details

  Returns `201 Created` with:

  * `order`: the newly created order object
  * `bankDetails` (for `bank_transfer` payments)
  * `cryptoDepositAddress` (for stablecoin or on-chain payments)
* **GET /orders/investor/portfolio?subdomain=\<tenant\_subdomain>**\
  Retrieve the authenticated investor’s orders for a tenant.

  Query parameter:

  * `subdomain` (string, required)

  Response:

  * `orders`: array of order objects, each including:
    * `cancellationDeadline`
    * `canCancel` (boolean)
  * `walletAddress` (string or `null`): the investor’s primary EVM address
  * `wallets`: map of chain types to addresses (`{ [chainType]: address }`)
* **GET /orders/:referenceCode**\
  Retrieve details for a single order by its reference code. Response includes:
  * All order fields
  * `cancellationDeadline`
  * `canCancel` (boolean)
* **POST /orders/:id/cancel**\
  Cancel a pending order within its allowed cancellation window. Returns the updated order or an error if the window has passed.

### Checkout Intent

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

  Request body:

  * `offeringId` (string, required)
  * `fiatAmount` (number, optional) — last-entered amount
  * `lastSeenStep` (string, required) — identifier of the last UI step viewed

  Successful response:

  * `{ id: string }`: the checkout intent identifier

  Error cases:

  * `401 Unauthorized` if missing or invalid Privy token
  * `404 Not Found` if the offering is not active
  * `500 Internal Server Error` on failure to save the intent

### 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:

  * `publicKey` (string or `null`)
  * `configured` (boolean)
* **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.

### KYC Workflow

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

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

Endpoints:

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

  Request body:

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

  Returns provider-specific tokens or SDK configuration:

  * For Sumsub: `{ provider: "sumsub", sdkToken, levelName }`
  * For Blockpass: provider response with redirect or widget parameters
* **GET /kyc/status**\
  Poll the status of the authenticated investor’s verification. Requires a Privy ID token.

  Response:

  * `kyc_status` (`none`, `pending`, `approved`, `rejected`, etc.)
  * `kyc_record_id` (string or `null`)

### Investor Profile & Wallets

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

  Response:

  * `profile`: object containing personal and company fields (name, email, address, investor type, etc.), `kyc_status`, `kyc_record_id`
  * `wallets`: map of chain types to `{ address, source }` (supports `evm`, `solana`, `stellar`, `xrpl`)
  * `walletList`: array of `{ chain_type, address, source }` sorted by precedence
  * `walletHistory`: audit trail entries with `{ id, wallet_address, chain_type, set_at, replaced_at }`
  * `hasConfirmedOrder` (boolean)
* **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:

  * `message`: status message
  * `walletAddress`
  * `chainType`

  Error cases:

  * `400 Bad Request` if the wallet address is invalid 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: A 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 user and tenant management, 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).


---

# Agent Instructions: 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:

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

The question should be specific, self-contained, and written in natural language.
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.
