Skip to content
OpenTrain AIOpenTrain AIOpenTrain AIDocs

Ask OpenTrain

Answers from the documentation, with sources.

What would you like to do with OpenTrain?

AI answers can be mistaken. Check the linked sources. Don’t include private account information.

Open app

DEVELOPER DOCUMENTATION

Inspect Messaging Rosters, Conversations, and Email Evidence

Read job-scoped messaging membership, conversation response evidence, and privacy-safe notification email delivery observations.

Use these read-only operations when an agent needs to understand a job’s messaging surface without changing membership, creating conversations, or sending mail. Every operation requires messages:read, a claimed account, the messaging surface enabled for the account, and the relevant conversation or job access.

The same operations are available through the Public API, the OpenTrain CLI, the official SDK, and the product MCP server. The API’s OpenAPI document at /api/public/v1/openapi.json is the exact contract of record.

GET /api/public/v1/messaging/management/messaging_management.members.list

Pass conversationId. The response is a page of active members by default. Set includeRemoved=true to include historical membership rows. Set includeWorkEmail=true only when you hold participant_work_email:read; managed work addresses are returned only for that explicitly authorized read, and personal signup addresses are never returned.

Terminal window
curl -sS \
"https://app.opentrain.ai/api/public/v1/messaging/management/messaging_management.members.list?conversationId=<CONVERSATION_ID>&limit=50" \
-H "Authorization: Bearer $OT_API_TOKEN"
opentrain messages members list \
--conversation-id <CONVERSATION_ID> --limit 50 --json

Follow nextCursor while hasMore is true. The response identifies the conversation context, membership source, role, contract relationship, and privacy-safe display label. It does not return a personal email address.

GET /api/public/v1/messaging/management/messaging_management.members.get

Pass exactly one selector: userId, contractId, or a managed workEmail. An unknown or non-member selector returns membership: "none"; it is not a directory search. Channel responses may include an observational preflight with add/remove eligibility. The preflight never reserves permission and does not perform a membership write.

Terminal window
opentrain messages members get \
--conversation-id <CONVERSATION_ID> --contract-id <CONTRACT_ID> --json

GET /api/public/v1/messaging/management/messaging_management.conversations.list

Pass jobId and optionally filter by contextType (proposal_dm, job_dm, or channel), participantUserId, updatedAfter, or needsEmployerReply. updatedAfter filters conversation-row changes; it is not a complete message-edit change feed. Returned rows include participants, contract state, latest activity, and bounded pointers for the latest worker message and employer response. needsEmployerReply is organization-level response evidence, not proof that an issue is resolved.

Terminal window
curl -sS \
"https://app.opentrain.ai/api/public/v1/messaging/management/messaging_management.conversations.list?jobId=<JOB_ID>&contextType=job_dm&limit=50" \
-H "Authorization: Bearer $OT_API_TOKEN"
opentrain messages conversations list \
--job-id <JOB_ID> --context job_dm --limit 50 --json

Follow nextCursor until it is null. Compare the returned snapshot marker with a new read before acting; a freshness marker is an observation, not an atomic send precondition.

GET /api/public/v1/messages/email-audit

Provide one of these mutually exclusive selectors:

  • jobId plus messageIds (one to 50 IDs);
  • jobId plus conversationId, since, and until (a range of at most 31 days); or
  • jobId plus milestoneId, optionally narrowed by recipientUserId.

Use cursor and limit (1–100) for paging. The result is an observation of stored notification decisions and the delivery ledger. It never sends or resends an email.

Terminal window
curl -sS \
"https://app.opentrain.ai/api/public/v1/messages/email-audit?jobId=<JOB_ID>&messageIds=<MESSAGE_ID>" \
-H "Authorization: Bearer $OT_API_TOKEN"
opentrain messages email-audit \
--job-id <JOB_ID> --message-ids <MESSAGE_ID> --json

Interpret the status conservatively:

  • SENT means provider acceptance, not recipient delivery.
  • DELIVERED requires a primary-recipient delivery event.
  • A later complaint is separate evidence and does not erase delivery.
  • UNKNOWN and unobservedMessageIds mean the durable correlation is missing; they are not proof that a send failed or succeeded.
  • BCC counts describe the provider envelope. They do not prove delivery to a third-party recipient.

The response is privacy-safe: it exposes masked recipient labels and bounded delivery state, never raw addresses, provider payloads, signed URLs, or credentials.

The stdio and hosted MCP server expose the same read contracts as:

  • opentrain_list_messaging_members
  • opentrain_get_messaging_member
  • opentrain_list_job_conversations
  • opentrain_audit_notification_emails

The SDK methods are listManagedMessagingMembers, getManagedMessagingMember, listJobConversations, and auditNotificationEmails. Use response_format: "summary" or response_format: "json" on MCP reads; structured content remains the validated result in either mode.

MCP clients validate closed response schemas before returning data. SDK clients expose the same typed methods and response models, but callers should still treat a response as untrusted input at their application boundary. All four operations are read-only and require the matching server release.