> ## Documentation Index
> Fetch the complete documentation index at: https://developers.meet-oj.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Send a message

> Adds a message to the referral's conversation. There are two uses.

With `author: borrower`, you are relaying something the borrower said or uploaded inside your own product,
for example an answer typed into your chat, or a statement dropped into your inbox. O.J. treats it exactly
as if the borrower had said it on a hosted page. It answers a pending question, satisfies a document
request, or is read by O.J.'s agent. The borrower never has to leave your app.

With `author: partner`, you are telling O.J. something about the deal, such as "the owner is travelling
until the 12th" or "we already have the lease on file". O.J.'s agent reads it, and if it changes what is
needed, the referral's `todos` change too.

Posting a message does not contact the borrower on O.J.'s channels. O.J. decides on its own when to reply
and where, under your `contact_channels` policy. If you want O.J. to answer inside your product, register
a channel connector.




## OpenAPI

````yaml /api-reference/openapi.yaml post /referrals/{referral_id}/messages
openapi: 3.1.0
info:
  title: O.J. Agent Development Kit (ADK)
  version: 0.5.1
  summary: >-
    Send O.J. a business. Get back named lender matches, what's needed, offers
    and funding status.
  description: >
    The O.J. ADK lets platforms with small-business customers offer financing
    without becoming a lender or a

    broker. You send a business as a **referral**. O.J. matches it to lender
    programs, collects documents,

    submits to lenders and tracks the deal to funding. You earn a share of the
    commission on every funded loan.


    Integrate with **O.J. Embed** (drop-in screens), the **REST API** with
    webhooks, or **MCP** for agents. All

    three read and write the same referral.


    Conventions: OAuth 2.0 client credentials, amounts in cents, prefixed ids,
    cursor pagination, an

    `Idempotency-Key` on every POST, RFC 9457 errors, and Standard Webhooks
    signatures.
  license:
    name: Proprietary — O.J. partner terms
    identifier: LicenseRef-OJ-Partner
  contact:
    name: O.J. Developer Support
    email: developers@meet-oj.com
servers:
  - url: https://sandbox.api.meet-oj.com/partner/v0
    description: Sandbox
  - url: https://api.meet-oj.com/partner/v0
    description: Production
security:
  - oauth2: []
tags:
  - name: Referrals
    description: >-
      A referral is one business you sent to O.J. Every other resource belongs
      to a referral.
  - name: Matches
    description: >-
      The lenders a business matches, named, with estimated limits. `POST
      /match_checks` screens raw numbers without creating a referral. A match is
      not a credit decision; the lender decides.
  - name: Documents
    description: >-
      Documents O.J. still needs, and uploads by API. Most integrations show the
      `next_action` button instead.
  - name: Offers
    description: >-
      Offers returned by lenders. Indicative terms computed before a lender
      replies are marked `binding: false`.
  - name: Sessions
    description: >-
      Create a session to open an O.J. screen: a `client_token` for Embed, or a
      hosted `url` to redirect to.
  - name: Events
    description: >-
      Every change to a referral is an event, delivered by webhook, streamed
      over SSE, and kept for 30 days at `GET /events`.
  - name: Payouts
    description: >-
      Your share of the commission on each funded referral. Match rows to your
      bank statement with `statement_descriptor`. Payout destinations are set
      during onboarding and cannot be changed by API.
  - name: Conversation
    description: >-
      The message thread between O.J., the borrower and your team on a referral,
      across every channel.
  - name: Channels
    description: >-
      Channel connectors let O.J. reach your borrowers through channels you own
      (in-app inbox, SMS, Apple Business Messages, email), in your brand.
  - name: Policy
    description: >-
      Account-level rules: send approval, allowed Embed origins, contact
      channels, default intent and reminder cadence.
  - name: Programs
    description: >-
      For lenders running a program on O.J.: receive submissions, record
      decisions and report funding.
  - name: Webhooks
    description: >-
      Register endpoints that receive signed events. Deliveries follow Standard
      Webhooks.
paths:
  /referrals/{referral_id}/messages:
    post:
      tags:
        - Conversation
      summary: Send a message
      description: >
        Adds a message to the referral's conversation. There are two uses.


        With `author: borrower`, you are relaying something the borrower said or
        uploaded inside your own product,

        for example an answer typed into your chat, or a statement dropped into
        your inbox. O.J. treats it exactly

        as if the borrower had said it on a hosted page. It answers a pending
        question, satisfies a document

        request, or is read by O.J.'s agent. The borrower never has to leave
        your app.


        With `author: partner`, you are telling O.J. something about the deal,
        such as "the owner is travelling

        until the 12th" or "we already have the lease on file". O.J.'s agent
        reads it, and if it changes what is

        needed, the referral's `todos` change too.


        Posting a message does not contact the borrower on O.J.'s channels. O.J.
        decides on its own when to reply

        and where, under your `contact_channels` policy. If you want O.J. to
        answer inside your product, register

        a channel connector.
      operationId: createMessage
      parameters:
        - $ref: '#/components/parameters/ReferralId'
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MessageCreate'
      responses:
        '201':
          description: Message recorded
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Message'
        '400':
          $ref: '#/components/responses/Error'
        '404':
          $ref: '#/components/responses/Error'
        '422':
          $ref: '#/components/responses/Error'
components:
  parameters:
    ReferralId:
      name: referral_id
      in: path
      required: true
      schema:
        type: string
        examples:
          - ref_01K5X3K7Q2
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: true
      description: >
        IETF `Idempotency-Key` semantics
        (draft-ietf-httpapi-idempotency-key-header). Send a fresh unique value

        (a UUID) with every new request. A retry with the same key and the same
        payload returns the original

        response with the header `Idempotent-Replayed: true`. The same key with
        a different payload is rejected with

        422 and code `idempotency_key_reused`. Keys are kept for 24 hours.
      schema:
        type: string
        maxLength: 255
  schemas:
    MessageCreate:
      type: object
      description: >-
        The body for posting a message into a referral's conversation from your
        side.
      required:
        - author
        - parts
      properties:
        author:
          type: string
          enum:
            - borrower
            - partner
          description: >-
            `borrower` when you are relaying what the borrower said or uploaded
            in your product. `partner` when your team or system is telling O.J.
            something.
        author_name:
          type: string
        parts:
          type: array
          minItems: 1
          items:
            $ref: '#/components/schemas/MessagePart'
        in_reply_to:
          type: string
          description: The O.J. message the borrower is answering, if your UI knows it.
        next_action_id:
          type: string
          description: >-
            The action this message is about, if your UI knows it. O.J. works it
            out otherwise.
        external_id:
          type: string
    Message:
      type: object
      description: >
        One turn in a referral's conversation. `author` is who said it: `oj`
        (O.J.'s agent or a reviewer),

        `borrower`, or `partner` (your staff or your system). `channel` is where
        it went through. `parts` is the

        content. `next_action_id` is set when the message is about a specific
        action, for example O.J. asking for

        statements, or the borrower's reply that satisfied the request.


        Messages from the borrower on O.J.'s own channels appear here too, so
        your product always has the whole

        thread. The message carries the medium, not the number or address the
        borrower used.
      required:
        - id
        - referral_id
        - conversation_id
        - author
        - channel
        - parts
        - created_at
      properties:
        id:
          type: string
          examples:
            - msg_01K5X6D2E8
        object:
          type: string
          const: message
        referral_id:
          type: string
        conversation_id:
          type: string
          examples:
            - conv_01K5X3K7Q2
        author:
          type: string
          enum:
            - oj
            - borrower
            - partner
        author_name:
          type: string
          description: >-
            Display name to show: "O.J.", the borrower's first name, or your
            staff member's name.
          examples:
            - O.J.
        channel:
          $ref: '#/components/schemas/Channel'
        direction:
          type: string
          enum:
            - inbound
            - outbound
          description: From O.J.'s point of view. Outbound messages were sent by O.J.
        parts:
          type: array
          items:
            $ref: '#/components/schemas/MessagePart'
        next_action_id:
          type: string
        in_reply_to:
          type: string
          description: The id of the message this answers, when known.
        external_id:
          type: string
          description: Your own id for the message, if you posted it.
        created_at:
          type: string
          format: date-time
        delivered_at:
          type: string
          format: date-time
          description: When the channel confirmed delivery, if it does.
        read_at:
          type: string
          format: date-time
          description: When the recipient opened it, if the channel reports that.
    MessagePart:
      type: object
      description: >
        One piece of a message, in the same shape A2A uses. Exactly one of
        `text`, `file` or `data` is set. A

        `file` part is a document that was uploaded with the message, or a
        reference to one already on the

        referral. A `data` part is structured content: the borrower's answers to
        a question, or, on the first

        message of a new referral, a `ReferralCreate` body.
      required:
        - kind
      properties:
        kind:
          type: string
          enum:
            - text
            - file
            - data
        text:
          type: string
        file:
          type: object
          properties:
            document_id:
              type: string
              description: Set once O.J. has stored the file.
            filename:
              type: string
            media_type:
              type: string
              examples:
                - application/pdf
            url:
              type: string
              format: uri
              description: >-
                Where to fetch the bytes. Requires your API token or a partner
                session.
            type:
              $ref: '#/components/schemas/DocumentType'
        data:
          type: object
          description: >-
            Structured content. When answering a question, the keys are the
            question's field names.
        media_type:
          type: string
    Channel:
      type: string
      description: >
        Where a message went through. `embed` is the O.J. Embed component inside
        your product. `hosted_page` is

        an O.J.-hosted page. `sms`, `imessage`, `email` and `voice` are O.J.'s
        own channels, used only when your

        policy allows them. `partner_channel` means O.J. delivered through one
        of your channel connectors, in your

        brand. `api` means the message was posted by your system, your agent, or
        an A2A client.
      enum:
        - embed
        - hosted_page
        - sms
        - imessage
        - email
        - voice
        - partner_channel
        - api
    Error:
      type: object
      description: >
        RFC 9457 Problem Details, returned as `application/problem+json` with
        any 4xx or 5xx status. `type` is a

        URI that identifies the kind of problem and doubles as a link to its
        documentation; `title` is the short

        human name for that kind; `status` repeats the HTTP status; `detail`
        explains this occurrence for a

        developer; `instance` is the request path. Three extension members:
        `code`, a stable snake_case reason to

        branch on; `param`, the offending field when the request was invalid;
        `request_id`, to quote to support.

        One code deserves a note: `awaiting_approval` (HTTP 409) is not a
        failure. It means the action you asked

        for needs a person at your company to confirm it first, and the referral
        shows `needs_partner` until they do.
      required:
        - type
        - title
        - status
        - code
        - request_id
      properties:
        type:
          type: string
          format: uri
          examples:
            - https://api.meet-oj.com/problems/duplicate-external-id
        title:
          type: string
          examples:
            - Referral already exists
        status:
          type: integer
          examples:
            - 409
        detail:
          type: string
          examples:
            - >-
              A referral with external_id cust_8842 was created on 2026-09-20 as
              ref_01K5X3K7Q2.
        instance:
          type: string
          examples:
            - /partner/v0/referrals
        code:
          type: string
          description: >-
            Stable machine-readable reason. Categories are the prefixes;
            specific codes follow.
          examples:
            - invalid_request
            - authentication_failed
            - permission_denied
            - not_found
            - duplicate_external_id
            - business_already_referred
            - missing_consent
            - required_documents_missing
            - idempotency_key_reused
            - rate_limited
            - awaiting_approval
            - internal_error
        param:
          type: string
          description: The field that caused an invalid_request, in dot notation.
        request_id:
          type: string
          examples:
            - req_01K5X4A9M2
    DocumentType:
      type: string
      description: >-
        The kinds of documents O.J. can request or accept. `cim` is a
        confidential information memorandum, the summary document a business
        broker prepares for a sale. `quality_of_earnings` is an accountant's
        review of reported earnings, required by the SBA for acquisitions of $3M
        or more. `funding_account_auth` is the funding account verified through
        Plaid; `voided_check` is the fallback when the bank can't be verified.
      enum:
        - bank_statement
        - processing_statement
        - voided_check
        - funding_account_auth
        - tax_return
        - profit_and_loss
        - balance_sheet
        - ar_aging
        - ap_aging
        - debt_schedule
        - business_license
        - government_id
        - lease
        - ownership_document
        - cim
        - purchase_agreement
        - quality_of_earnings
        - other
  responses:
    Error:
      description: Problem Details (RFC 9457)
      headers:
        OJ-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/Error'
  headers:
    RequestId:
      description: >-
        Unique id for this request. Quote it to support; it is also in Problem
        Details as `request_id` and in O.J.'s traces.
      schema:
        type: string
        examples:
          - req_01K5X4A9M2
  securitySchemes:
    oauth2:
      type: oauth2
      description: >-
        One client per partner per environment. Access tokens expire after 15
        minutes. Scopes are granted per client. Sandbox clients use
        https://sandbox.api.meet-oj.com/oauth/token.
      flows:
        clientCredentials:
          tokenUrl: https://api.meet-oj.com/oauth/token
          scopes:
            referrals:write: Create referrals and upload documents
            referrals:read: Read referrals, matches, document requests, offers, events
            match_checks:write: Run identity-free match checks
            sessions:write: Mint hosted-session links
            webhooks:manage: Register and list webhook endpoints
            payouts:read: >-
              Read payouts (your statement). There is no payouts:write;
              destinations are managed in hosted onboarding by a person.
            messages:read: Read a referral's conversation
            messages:write: >-
              Send messages into a referral's conversation on behalf of the
              partner or the borrower
            channels:manage: Register and remove channel connectors
            policy:manage: Read and change the partner policy
            submissions:read: >-
              For banks running a program. List and read submissions awaiting
              review
            submissions:write: For banks running a program. Record decisions and report funding

````