> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Rank next-best products for a profile

> Stateless next-best-product ranking: given ONE profile's affinity traits + purchase/browse signals and your candidate catalog, returns the products that profile is most likely to buy next, each with a per-factor affinity breakdown (category / brand / tag / price-fit / popularity). Feed it from your CDP computed traits and event stream, then render the ranked list into an in-thread RCS / WhatsApp catalog carousel or a campaign. Pass an `experiment` with per-variant `weights` for deterministic A/B bucketing — the assigned variant is echoed back for attribution. Ranks only; it never dispatches a message. Requires owner/admin/developer.



## OpenAPI

````yaml /openapi.yaml post /api/v1/cdp/recommendations/rank
openapi: 3.1.0
info:
  title: Devotel CPaaS API
  description: Orbit by Devotel — Communications Platform as a Service API
  version: 1.0.0
  contact:
    name: Devotel
    url: https://devotel.io
    email: support@devotel.io
  license:
    name: Proprietary
servers:
  - url: https://api.orbit.devotel.io
    description: Production
security:
  - Bearer: []
  - ApiKey: []
tags:
  - name: Messages
    description: >-
      Send and manage messages across all channels (SMS, WhatsApp, RCS, Email,
      Viber, etc.)
  - name: Agents
    description: AI agent creation, configuration, and execution
  - name: Voice
    description: Voice calls, IVR, conferencing, and SIP trunking
  - name: Webhooks
    description: Webhook endpoint management and delivery logs
  - name: Numbers
    description: Phone number search, provisioning, and configuration
  - name: Contacts
    description: Contact management, segmentation, and lifecycle tracking
  - name: Campaigns
    description: Marketing campaign orchestration and analytics
  - name: Flows
    description: Automation flow builder and execution engine
  - name: Templates
    description: Message template management and approval workflows
  - name: Settings
    description: Organization, channel, and user preference settings
  - name: Verify
    description: OTP generation and verification across channels
  - name: Push
    description: Push notification delivery via FCM and APNs
  - name: Telegram
    description: >-
      Telegram bring-your-own-bot channel: connect a bot, verify a chat against
      the shared sandbox bot, and read unified channel state. Production sends
      go through the Messaging API.
  - name: USSD
    description: >-
      Menu-driven USSD for feature phones: define a menu tree, simulate session
      steps, and host the tenant-scoped aggregator callback.
  - name: Integrations
    description: Third-party service connections and OAuth management
  - name: Files
    description: >-
      Server-to-server media upload, listing, retrieval, and deletion
      (signed-URL backed)
  - name: Messaging Services
    description: >-
      Twilio MessagingService-parity containers bundling sender pool, opt-out
      list, inbound webhook, and sticky-sender/geomatch flags
  - name: Sender Pools
    description: >-
      Group sending numbers into pools with a selection strategy (sticky /
      round-robin / random) for outbound sends
  - name: Opt-Out Lists
    description: >-
      Per-list STOP / HELP / START keyword sets and auto-response copy (Twilio
      Advanced Opt-Out parity)
  - name: SMPP
    description: Tenant BYO-SMPP bind credentials and upstream termination carriers
  - name: Commerce
    description: >-
      Unified omnichannel conversational-commerce: cart/checkout state machine,
      cross-channel payment reconciliation, hosted pay-by-link, native WhatsApp
      checkout, and agentic-checkout payment mandates
  - name: Orby
    description: >-
      In-dashboard Orby operator assistant: streamed assistant turns,
      conversation threads, product knowledge-base search, and the tool-action
      approval gate. Available to signed-in operators only (dashboard session
      auth — API-key requests are rejected).
paths:
  /api/v1/cdp/recommendations/rank:
    post:
      tags:
        - CDP
      summary: Rank next-best products for a profile
      description: >-
        Stateless next-best-product ranking: given ONE profile's affinity traits
        + purchase/browse signals and your candidate catalog, returns the
        products that profile is most likely to buy next, each with a per-factor
        affinity breakdown (category / brand / tag / price-fit / popularity).
        Feed it from your CDP computed traits and event stream, then render the
        ranked list into an in-thread RCS / WhatsApp catalog carousel or a
        campaign. Pass an `experiment` with per-variant `weights` for
        deterministic A/B bucketing — the assigned variant is echoed back for
        attribution. Ranks only; it never dispatches a message. Requires
        owner/admin/developer.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - catalog
              properties:
                profile_id:
                  type: string
                  description: >-
                    The profile the ranking is for (contact id or external CDP
                    profile id) — used to bucket A/B experiments
                    deterministically.
                catalog:
                  type: array
                  items:
                    type: object
                  description: Candidate products to rank (1-2000).
                signals:
                  type: array
                  items:
                    type: object
                  description: The profile's purchase/browse/view signals (up to 5000).
                traits:
                  type: object
                  description: >-
                    The profile's affinity traits: category_affinity /
                    brand_affinity maps and preferred_tags.
                limit:
                  description: How many recommendations to return.
                experiment:
                  type: object
                  description: >-
                    Optional A/B experiment: a key plus named variants, each
                    with its own factor weights.
            example:
              profile_id: cnt_01J8XF3T4W5Q6N7V8R9M0K1P
              catalog:
                - product_id: sku_1042
                  title: Trail Running Shoes
                  category: footwear
                  brand: North Peak
                  price: 129.99
                  tags:
                    - trail
                    - running
                    - outdoor
                  popularity: 0.82
                  in_stock: true
                - product_id: sku_2150
                  title: Hydration Vest 5L
                  category: accessories
                  brand: HydraPak
                  price: 59
                  tags:
                    - hydration
                    - running
                  popularity: 0.41
                  in_stock: true
              signals:
                - product_id: sku_1042
                  category: footwear
                  type: view
                  age_days: 2
                - category: footwear
                  type: purchase
                  age_days: 40
                  value: 1
              traits:
                category_affinity:
                  footwear: 0.9
                  accessories: 0.4
                preferred_tags:
                  - trail
              limit: 2
      responses:
        '200':
          description: >-
            Ranked recommendations with per-factor score breakdown and the
            applied weights.
          content:
            application/json:
              schema:
                description: >-
                  Ranked recommendations with per-factor score breakdown and the
                  applied weights.
                type: object
                additionalProperties: true
                example:
                  data:
                    profile_id: cnt_01J8XF3T4W5Q6N7V8R9M0K1P
                    experiment: null
                    recommendations:
                      - product_id: sku_1042
                        title: Trail Running Shoes
                        category: footwear
                        brand: North Peak
                        price: 129.99
                        score: 0.87
                        rank: 1
                        factors:
                          category: 0.9
                          brand: 0
                          tag: 0.66
                          price_fit: 0.5
                          popularity: 0.82
                      - product_id: sku_2150
                        title: Hydration Vest 5L
                        category: accessories
                        brand: HydraPak
                        price: 59
                        score: 0.51
                        rank: 2
                        factors:
                          category: 0.4
                          brand: 0
                          tag: 0.33
                          price_fit: 0.9
                          popularity: 0.41
                    considered_count: 2
                    excluded_count: 0
                    weights:
                      category: 30
                      brand: 15
                      tag: 15
                      price_fit: 20
                      popularity: 20
                    half_life_days: 30
                    limit: 2
                  meta:
                    request_id: req_01J8Z9K3P4Q5R6S7T8U9V0W1X2
                    timestamp: '2026-08-19T12:00:00.000Z'
        '400':
          $ref: '#/components/responses/StandardError'
        '404':
          $ref: '#/components/responses/StandardError'
        '422':
          $ref: '#/components/responses/StandardError'
        '429':
          $ref: '#/components/responses/RateLimitedResponse'
        '500':
          $ref: '#/components/responses/StandardError'
      security: []
components:
  responses:
    StandardError:
      description: >-
        Standard error envelope. `error.code` is machine-readable; see the
        [error reference](https://docs.orbit.devotel.io/reference/error-codes)
        for the catalogue.
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: object
                required:
                  - code
                  - message
                  - status
                properties:
                  code:
                    type: string
                    description: Machine-readable error code (e.g. INVALID_PHONE_NUMBER)
                  message:
                    type: string
                    description: Human-readable error description
                  status:
                    type: integer
                    description: HTTP status code
                  details:
                    type: object
                    additionalProperties: true
                    description: Additional context about the error
              meta:
                type: object
                properties:
                  request_id:
                    type: string
                  timestamp:
                    type: string
                    format: date-time
                  docs_url:
                    type: string
                    format: uri
                    description: Link to relevant error documentation
    RateLimitedResponse:
      description: >-
        Rate limit exceeded. Wait `error.retry_after` seconds (or read the
        `Retry-After` header) before retrying. Returned when the request would
        exceed the bucket identified by `X-RateLimit-Bucket`.
      headers:
        X-RateLimit-Limit:
          description: Total request quota for the current window.
          schema:
            type: integer
            minimum: 0
        X-RateLimit-Remaining:
          description: Requests remaining in the current window.
          schema:
            type: integer
            minimum: 0
        X-RateLimit-Reset:
          description: >-
            Absolute unix-epoch-seconds timestamp at which the current window
            resets.
          schema:
            type: integer
            minimum: 0
        X-RateLimit-Bucket:
          description: >-
            Name of the rate-limit bucket the request was bound by (e.g.
            `auth-write`, `money`, `agent-invoke`, or `custom:<max>/<window>`).
            Stripe-style — lets clients see which named cap they hit.
          schema:
            type: string
        RateLimit-Limit:
          description: >-
            draft-ietf-httpapi-ratelimit-headers no-prefix mirror of
            `X-RateLimit-Limit`. Some SDKs read only this form.
          schema:
            type: integer
            minimum: 0
        RateLimit-Remaining:
          description: >-
            draft-ietf-httpapi-ratelimit-headers no-prefix mirror of
            `X-RateLimit-Remaining`.
          schema:
            type: integer
            minimum: 0
        RateLimit-Reset:
          description: >-
            draft-ietf-httpapi-ratelimit-headers no-prefix mirror — delta
            seconds from now until the window resets (NOT epoch).
          schema:
            type: integer
            minimum: 0
        Retry-After:
          description: >-
            RFC 7231 §7.1.3 — number of seconds the client should wait before
            retrying.
          schema:
            type: integer
            minimum: 1
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: object
                required:
                  - code
                  - message
                  - status
                  - retry_after
                properties:
                  code:
                    type: string
                    enum:
                      - RATE_LIMITED
                    description: >-
                      Always `RATE_LIMITED` — the global request-limiter 429.
                      Distinct from `RATE_LIMIT_EXCEEDED`, the live
                      per-recipient/per-tenant/per-resource frequency-cap 429
                      (not retired).
                  message:
                    type: string
                  status:
                    type: integer
                    enum:
                      - 429
                  retry_after:
                    type: integer
                    minimum: 1
                    description: >-
                      Seconds to wait before retrying. Mirrors `Retry-After`
                      header.
              meta:
                type: object
                properties:
                  request_id:
                    type: string
                  timestamp:
                    type: string
                    format: date-time
                  docs_url:
                    type: string
                    format: uri
  securitySchemes:
    Bearer:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Dashboard JWT token from Clerk
    ApiKey:
      type: apiKey
      name: X-API-Key
      in: header
      description: Server-to-server API key (dv_live_sk_*)

````