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.
Read a conversation roster
Section titled “Read a conversation roster”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.
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 --jsonFollow 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.
Inspect one member or eligibility
Section titled “Inspect one member or eligibility”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.
opentrain messages members get \ --conversation-id <CONVERSATION_ID> --contract-id <CONTRACT_ID> --jsonList a job’s conversations
Section titled “List a job’s conversations”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.
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 --jsonFollow 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.
Audit notification email observations
Section titled “Audit notification email observations”GET /api/public/v1/messages/email-audit
Provide one of these mutually exclusive selectors:
jobIdplusmessageIds(one to 50 IDs);jobIdplusconversationId,since, anduntil(a range of at most 31 days); orjobIdplusmilestoneId, optionally narrowed byrecipientUserId.
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.
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> --jsonInterpret the status conservatively:
SENTmeans provider acceptance, not recipient delivery.DELIVEREDrequires a primary-recipient delivery event.- A later complaint is separate evidence and does not erase delivery.
UNKNOWNandunobservedMessageIdsmean 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.
MCP and SDK names
Section titled “MCP and SDK names”The stdio and hosted MCP server expose the same read contracts as:
opentrain_list_messaging_membersopentrain_get_messaging_memberopentrain_list_job_conversationsopentrain_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.