Guides

Conversations

Conversations allow you to exchange messages within the context of a specific payment. Each payment can have one conversation thread where parties can discuss details, share documents, and resolve queries.


Before you start

You will need:

  • A valid API key to authenticate your requests.
  • A payment id — use the Payments API to create or retrieve one.

Getting a conversation

Retrieve the conversation for a payment. Returns an empty messages array if no conversation exists yet:

try {
  const response = await fetch('https://api.nexpay.com/v2/payments/123/conversation', {
    method: 'GET',
    headers: {
      'Authorization': 'ApiKey your-api-key-here',
    },
  });

  if (response.ok) {
    const data = await response.json();

    console.log(data);
  } else {
    throw new Error(`Request failed with status: ${response.status}`);
  }
} catch (error) {
  console.error(error);
}
{
  "id": 42,
  "paymentId": 123,
  "isClosed": false,
  "isRead": true,
  "messages": [
    {
      "userId": 300,
      "isAdminResponse": false,
      "subject": "Payment query",
      "text": "Can you confirm the enrollment letter was received?",
      "createdOn": "2026-03-15T09:00:00.000Z",
      "userFullName": "Jane Doe",
      "attachments": []
    },
    {
      "userId": 1,
      "isAdminResponse": true,
      "text": "Yes, we have received all documents. Payment is being processed.",
      "createdOn": "2026-03-15T10:30:00.000Z",
      "userFullName": "Support Team",
      "attachments": []
    }
  ]
}

Sending a message

Send a message in the payment conversation. If no conversation exists, one is created automatically:

try {
  const response = await fetch('https://api.nexpay.com/v2/payments/123/conversation/messages', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'ApiKey your-api-key-here',
    },
    body: JSON.stringify({
      "subject": "Payment query",
      "text": "Can you confirm the enrollment letter was received?",
      "attachments": [
        "f47ac10b-58cc-4372-a567-0e02b2c3d479"
      ]
    }),
  });

  if (response.ok) {
    const data = await response.json();

    console.log(data);
  } else {
    throw new Error(`Request failed with status: ${response.status}`);
  }
} catch (error) {
  console.error(error);
}

Message fields

FieldTypeRequiredDescription
textstringYesThe message content.
subjectstringNoOptional subject line for the message.
attachmentsstring[]NoArray of document UUIDs uploaded via the Documents API.

Attachments

Attachments must be uploaded via POST /documents before being referenced in a message. See Uploading documents.


Checking for unread messages

Check if a payment's conversation has unread messages without fetching the full thread:

try {
  const response = await fetch('https://api.nexpay.com/v2/payments/123/conversation/unread', {
    method: 'GET',
    headers: {
      'Authorization': 'ApiKey your-api-key-here',
    },
  });

  if (response.ok) {
    const data = await response.json();

    console.log(data); // { "hasUnread": true }
  } else {
    throw new Error(`Request failed with status: ${response.status}`);
  }
} catch (error) {
  console.error(error);
}

Downloading an attachment

Download a file attached to a conversation message:

try {
  const response = await fetch('https://api.nexpay.com/v2/payments/123/conversation/attachments/f47ac10b-58cc-4372-a567-0e02b2c3d479', {
    method: 'GET',
    headers: {
      'Authorization': 'ApiKey your-api-key-here',
    },
  });

  if (response.ok) {
    const blob = await response.blob();

    console.log('Downloaded attachment:', blob.size, 'bytes');
  } else {
    throw new Error(`Request failed with status: ${response.status}`);
  }
} catch (error) {
  console.error(error);
}

Closing a conversation

Close a conversation when it's no longer needed:

try {
  const response = await fetch('https://api.nexpay.com/v2/payments/123/conversation/close', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': 'ApiKey your-api-key-here',
    },
    body: JSON.stringify({}),
  });

  if (response.ok) {
    console.log('Conversation closed');
  } else {
    throw new Error(`Request failed with status: ${response.status}`);
  }
} catch (error) {
  console.error(error);
}

Closed conversations

Once a conversation is closed, no new messages can be sent. Attempting to send a message to a closed conversation will return a [CNV0002] error.


Things to know

  • Each payment can have at most one conversation.
  • Conversations are created automatically when the first message is sent.
  • The isAdminResponse field indicates whether a message was sent by the Nexpay admin team.
  • Attachment IDs are UUID v4 references to documents uploaded via the Documents API.
  • Conversations are scoped to your tenant — they cannot be accessed across organizations.
Previous
Commissions