11 operations. Every schema and example on this page is generated from the platform contract.
Returns the conversation between the signed-in customer and the given store, a page of its messages, the ids of messages deleted since `since`, the customer's send-permission state, and whether the store is currently typing. ⚠️ THIS READ CREATES THE CONVERSATION IF IT DOES NOT EXIST. That is deliberate and load-bearing, not an accident of implementation: opening the chat is what brings the thread into being, and the merchant's conversation list is fed from the row this call creates. It is safe to call repeatedly, at most one conversation ever exists per (customer, store) pair, and a concurrent first open resolves to the same row. Pagination has two modes that are never mixed. Pass `since` to POLL for what you missed (oldest→newest, with `deleted_ids` populated). Omit `since` to load HISTORY, the newest `limit` messages, oldest→newest, optionally older than `before` for scroll-up. The customer is resolved from the session; a client-supplied id is never trusted for identity.
Store whose conversation this refers to.
POLLING mode. ISO-8601 timestamp; returns only messages newer than this, oldest→newest, and populates `deleted_ids`. Use the newest `created_at` you already hold.
HISTORY mode. ISO-8601 timestamp; returns the newest messages OLDER than this, for scroll-up pagination. Use the oldest `created_at` you already hold. Ignored when `since` is set.
Maximum messages to return. Defaults to 50.
The conversation between this customer and this store.
Conversation id.
Messages the customer hasn't read yet.
Thread state. Sending into a 'blocked' conversation is rejected.
activearchivedblockedA page of messages, always oldest→newest.
Server row id for the message.
Conversation this message belongs to.
Who sent it. 'customer' is the member; 'store' is the merchant.
customerstoreId of the sending customer or store user.
Message kind. 'system' messages are generated by the platform, not a person.
textimagevideosystemText body. Null for media-only messages.
Full-size image or video URL, when this is a media message.
Thumbnail URL for a media message, when one was generated.
Media details captured at upload time (original name, mime type, byte size, pixel dimensions). Null on rows written before this was recorded.
Delivery state, which drives the tick indicator in the apps.
sendingsentdeliveredreadfailedWhen the recipient read the message, if they have.
When the message reached the recipient's device, if it has.
Set when this message is one recipient copy of a merchant broadcast.
When the message was sent.
When the row last changed.
When the message was last edited. Null if never edited.
When the message was deleted. Deleted messages are not returned in reads.
The sender's client-generated id, the idempotency key AND the client's stable bubble identity. Reconcile on this, not on `id`.
Ids of messages deleted since `since`, contains both server row ids and client_message_ids so a client can tombstone a bubble it only knows by its local id. Always empty in HISTORY mode.
The messaging profile gate. A customer may always READ a conversation, but may only SEND once they have supplied a name and an email, update them with `updateMessagingProfile`.
Whether the customer may send messages. False until both a name and an email are on file.
Whether the customer has a name on file.
Whether the customer has an email on file.
The customer's name, if set.
The customer's email, if set.
True when the store was typing within the last five seconds.
curl -G "https://www.membber.com/api/v1/messaging/conversation" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
--data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.GET("/api/v1/messaging/conversation", {
params: { query: { store_id: "6659c139-0000-4000-8000-d0c500000066" } },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.getMessagingConversation(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066")
).ok.body.json
print(response){
"conversation": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"unread": 1,
"status": "active"
},
"messages": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"conversation_id": "e701a257-0000-4000-8000-d0c5000000e7",
"sender_type": "customer",
"sender_id": "01eb2f65-0000-4000-8000-d0c500000001",
"content_type": "text",
"body": "<body>",
"media_url": "https://example.com/image.jpg",
"media_thumbnail_url": "https://example.com/image.jpg",
"media_metadata": {},
"status": "sending",
"read_at": "<read_at>",
"delivered_at": "<delivered_at>",
"broadcast_id": "0eae4559-0000-4000-8000-d0c50000000e",
"created_at": "<created_at>",
"updated_at": "<updated_at>",
"edited_at": "<edited_at>",
"deleted_at": "<deleted_at>",
"client_message_id": "279d4547-0000-4000-8000-d0c500000027"
}
],
"deleted_ids": [
"69349f01-0000-4000-8000-d0c500000069"
],
"profile": {
"can_message": true,
"has_name": true,
"has_email": true,
"name": "Example name",
"email": "alex@example.com"
},
"is_other_typing": true
}Marks every message the store has sent in this conversation as delivered, which is what turns the merchant's single tick into a double tick. Call it the moment a message arrives, over the WebSocket or as a push, without waiting for the customer to open the chat. Idempotent: only messages not already marked are touched, so the WebSocket and the push both firing produces one state change and one notification to the merchant, not two.
Store whose conversation this refers to.
Always true when the call succeeds.
curl -X POST "https://www.membber.com/api/v1/messaging/delivered" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/messaging/delivered", {
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.markMessagingDelivered(
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066"
))
).ok.body.json
print(response){
"acknowledged": true
}Sent as `multipart/form-data` with fields `file`, `store_id` and `client_message_id`. Uploads the file to storage and posts it as a media message in the customer's conversation with the store, creating the conversation if needed. Images are resized to at most 1200px, converted to WebP and given a thumbnail; videos are stored as uploaded. Limits: 10MB for images, 50MB for videos. IDEMPOTENT on `client_message_id` exactly as `sendMessagingMessage` is: a retry with the same id returns the original message rather than posting a second copy. Requires `profile.can_message`.
A single chat message.
Server row id for the message.
Conversation this message belongs to.
Who sent it. 'customer' is the member; 'store' is the merchant.
customerstoreId of the sending customer or store user.
Message kind. 'system' messages are generated by the platform, not a person.
textimagevideosystemText body. Null for media-only messages.
Full-size image or video URL, when this is a media message.
Thumbnail URL for a media message, when one was generated.
Media details captured at upload time (original name, mime type, byte size, pixel dimensions). Null on rows written before this was recorded.
Delivery state, which drives the tick indicator in the apps.
sendingsentdeliveredreadfailedWhen the recipient read the message, if they have.
When the message reached the recipient's device, if it has.
Set when this message is one recipient copy of a merchant broadcast.
When the message was sent.
When the row last changed.
When the message was last edited. Null if never edited.
When the message was deleted. Deleted messages are not returned in reads.
The sender's client-generated id, the idempotency key AND the client's stable bubble identity. Reconcile on this, not on `id`.
curl -X POST "https://www.membber.com/api/v1/messaging/media" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/messaging/media", {
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.uploadMessagingMedia().ok.body.json
print(response){
"message": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"conversation_id": "e701a257-0000-4000-8000-d0c5000000e7",
"sender_type": "customer",
"sender_id": "01eb2f65-0000-4000-8000-d0c500000001",
"content_type": "text",
"body": "<body>",
"media_url": "https://example.com/image.jpg",
"media_thumbnail_url": "https://example.com/image.jpg",
"media_metadata": {},
"status": "sending",
"read_at": "<read_at>",
"delivered_at": "<delivered_at>",
"broadcast_id": "0eae4559-0000-4000-8000-d0c50000000e",
"created_at": "<created_at>",
"updated_at": "<updated_at>",
"edited_at": "<edited_at>",
"deleted_at": "<deleted_at>",
"client_message_id": "279d4547-0000-4000-8000-d0c500000027"
}
}Removes a message the signed-in customer sent from both sides of the conversation. The row is retained with a deletion timestamp rather than destroyed, so the id appears in `deleted_ids` on the next poll and every client can tombstone its copy. Only the original sender may delete. Idempotent, deleting an already-deleted message succeeds and changes nothing.
Store whose conversation this refers to.
The message to delete.
Always true when the call succeeds.
curl -X DELETE "https://www.membber.com/api/v1/messaging/messages?store_id=6659c139-0000-4000-8000-d0c500000066&message_id=9b39a053-0000-4000-8000-d0c50000009b" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.DELETE("/api/v1/messaging/messages", {
params: { query: { store_id: "6659c139-0000-4000-8000-d0c500000066", message_id: "9b39a053-0000-4000-8000-d0c50000009b" } },
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.deleteMessagingMessage(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066", messageId: "9b39a053-0000-4000-8000-d0c50000009b")
).ok.body.json
print(response){
"deleted": true
}Posts a message into the customer's conversation with the store, creating the conversation if this is the first one. Delivers to the merchant over Realtime and push. IDEMPOTENT on `client_message_id`: sending the same id twice returns the original message instead of posting a duplicate. Always reuse the id when retrying, that is the whole mechanism that stops a flaky network from producing double messages. Requires the customer to have a name and an email on file (`profile.can_message`); without them the call is rejected and the customer should be sent to `updateMessagingProfile` first. Sending into a blocked conversation is rejected.
Store whose conversation this refers to.
Client-generated UUID identifying this message. REQUIRED. Reuse the SAME value on every retry of the same message, the server returns the original message rather than posting a duplicate. Generate a new one only for a genuinely new message.
Text body. Required for a text message; omit for a media message.
Message kind. Defaults to 'text'. Use `uploadMessagingMedia` to send a photo or video from a file.
textimagevideoURL of already-uploaded media. Required when `content_type` is image or video.
Thumbnail URL for the media, if you have one.
Free-form media details to store alongside the message.
A single chat message.
Server row id for the message.
Conversation this message belongs to.
Who sent it. 'customer' is the member; 'store' is the merchant.
customerstoreId of the sending customer or store user.
Message kind. 'system' messages are generated by the platform, not a person.
textimagevideosystemText body. Null for media-only messages.
Full-size image or video URL, when this is a media message.
Thumbnail URL for a media message, when one was generated.
Media details captured at upload time (original name, mime type, byte size, pixel dimensions). Null on rows written before this was recorded.
Delivery state, which drives the tick indicator in the apps.
sendingsentdeliveredreadfailedWhen the recipient read the message, if they have.
When the message reached the recipient's device, if it has.
Set when this message is one recipient copy of a merchant broadcast.
When the message was sent.
When the row last changed.
When the message was last edited. Null if never edited.
When the message was deleted. Deleted messages are not returned in reads.
The sender's client-generated id, the idempotency key AND the client's stable bubble identity. Reconcile on this, not on `id`.
curl -X POST "https://www.membber.com/api/v1/messaging/messages" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"client_message_id": "279d4547-0000-4000-8000-d0c500000027"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/messaging/messages", {
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066",
client_message_id: "279d4547-0000-4000-8000-d0c500000027"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.sendMessagingMessage(
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066",
clientMessageId: "279d4547-0000-4000-8000-d0c500000027"
))
).ok.body.json
print(response){
"message": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"conversation_id": "e701a257-0000-4000-8000-d0c5000000e7",
"sender_type": "customer",
"sender_id": "01eb2f65-0000-4000-8000-d0c500000001",
"content_type": "text",
"body": "<body>",
"media_url": "https://example.com/image.jpg",
"media_thumbnail_url": "https://example.com/image.jpg",
"media_metadata": {},
"status": "sending",
"read_at": "<read_at>",
"delivered_at": "<delivered_at>",
"broadcast_id": "0eae4559-0000-4000-8000-d0c50000000e",
"created_at": "<created_at>",
"updated_at": "<updated_at>",
"edited_at": "<edited_at>",
"deleted_at": "<deleted_at>",
"client_message_id": "279d4547-0000-4000-8000-d0c500000027"
}
}Replaces the body of a text message the signed-in customer sent, stamps `edited_at`, and appends the previous text to the message's edit history so the merchant can see what changed (read it with `getMessagingMessageEditHistory`). Only the original sender may edit, and only text messages can be edited, a photo or video cannot. Submitting the identical text is a no-op that returns the message unchanged and records no history entry.
Store whose conversation this refers to.
The message to edit.
The replacement text.
A single chat message.
Server row id for the message.
Conversation this message belongs to.
Who sent it. 'customer' is the member; 'store' is the merchant.
customerstoreId of the sending customer or store user.
Message kind. 'system' messages are generated by the platform, not a person.
textimagevideosystemText body. Null for media-only messages.
Full-size image or video URL, when this is a media message.
Thumbnail URL for a media message, when one was generated.
Media details captured at upload time (original name, mime type, byte size, pixel dimensions). Null on rows written before this was recorded.
Delivery state, which drives the tick indicator in the apps.
sendingsentdeliveredreadfailedWhen the recipient read the message, if they have.
When the message reached the recipient's device, if it has.
Set when this message is one recipient copy of a merchant broadcast.
When the message was sent.
When the row last changed.
When the message was last edited. Null if never edited.
When the message was deleted. Deleted messages are not returned in reads.
The sender's client-generated id, the idempotency key AND the client's stable bubble identity. Reconcile on this, not on `id`.
curl -X PUT "https://www.membber.com/api/v1/messaging/messages" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"message_id": "9b39a053-0000-4000-8000-d0c50000009b",
"body": "<body>"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.PUT("/api/v1/messaging/messages", {
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066",
message_id: "9b39a053-0000-4000-8000-d0c50000009b",
body: "<body>"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.editMessagingMessage(
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066",
messageId: "9b39a053-0000-4000-8000-d0c50000009b",
body: "<body>"
))
).ok.body.json
print(response){
"message": {
"id": "00000d1b-0000-4000-8000-d0c500000000",
"conversation_id": "e701a257-0000-4000-8000-d0c5000000e7",
"sender_type": "customer",
"sender_id": "01eb2f65-0000-4000-8000-d0c500000001",
"content_type": "text",
"body": "<body>",
"media_url": "https://example.com/image.jpg",
"media_thumbnail_url": "https://example.com/image.jpg",
"media_metadata": {},
"status": "sending",
"read_at": "<read_at>",
"delivered_at": "<delivered_at>",
"broadcast_id": "0eae4559-0000-4000-8000-d0c50000000e",
"created_at": "<created_at>",
"updated_at": "<updated_at>",
"edited_at": "<edited_at>",
"deleted_at": "<deleted_at>",
"client_message_id": "279d4547-0000-4000-8000-d0c500000027"
}
}Every revision made to a message, oldest first, so a reader can see what a message used to say. Read-only. Scoped to the signed-in customer's own conversation with the given store, a message in anybody else's thread reads as not found.
Store whose conversation this refers to.
The message whose edit history to read.
Every edit made to the message, oldest first. Empty if it has never been edited.
Edit record id.
Message that was edited.
The text before this edit.
The text after this edit.
Id of whoever made the edit.
Whether the customer or the store edited it.
customerstore1 for the first edit, 2 for the second, and so on.
When this edit was made.
curl -G "https://www.membber.com/api/v1/messaging/messages/edit-history" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
--data-urlencode "store_id=6659c139-0000-4000-8000-d0c500000066" \
--data-urlencode "message_id=9b39a053-0000-4000-8000-d0c50000009b"import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.GET("/api/v1/messaging/messages/edit-history", {
params: { query: { store_id: "6659c139-0000-4000-8000-d0c500000066", message_id: "9b39a053-0000-4000-8000-d0c50000009b" } },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.getMessagingMessageEditHistory(
query: .init(storeId: "6659c139-0000-4000-8000-d0c500000066", messageId: "9b39a053-0000-4000-8000-d0c50000009b")
).ok.body.json
print(response){
"edits": [
{
"id": "00000d1b-0000-4000-8000-d0c500000000",
"message_id": "9b39a053-0000-4000-8000-d0c50000009b",
"previous_body": "<previous_body>",
"new_body": "<new_body>",
"edited_by_id": "e10d726d-0000-4000-8000-d0c5000000e1",
"edited_by_type": "customer",
"edit_number": 1,
"created_at": "<created_at>"
}
]
}Sets the signed-in customer's name, email, phone and/or date of birth, and returns the resulting profile. A customer must have both a name and an email before they can send any message, so this is where a client sends someone whose `profile.can_message` is false. DETAILS CAN BE REPLACED BUT NOT REMOVED. Once a real email, a phone number, or a name the customer typed themselves is on file, clearing it is rejected, send a different value instead. An Apple private-relay email does not count as a real address and may be replaced freely. Only the signed-in customer's own profile can be changed.
Display name shown to the merchant. Cannot be set to an empty string.
Contact email. Must be a valid address.
Contact phone. A UK mobile (07xxxxxxxxx) or an international number in +447700900000 form.
Date of birth as YYYY-MM-DD.
The messaging profile gate. A customer may always READ a conversation, but may only SEND once they have supplied a name and an email, update them with `updateMessagingProfile`.
Whether the customer may send messages. False until both a name and an email are on file.
Whether the customer has a name on file.
Whether the customer has an email on file.
The customer's name, if set.
The customer's email, if set.
curl -X POST "https://www.membber.com/api/v1/messaging/profile" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"name": "Example name",
"email": "alex@example.com",
"phone": "+44 7700 900123",
"date_of_birth": "<date_of_birth>"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/messaging/profile", {
body: {
name: "Example name",
email: "alex@example.com",
phone: "+44 7700 900123",
date_of_birth: "<date_of_birth>"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.updateMessagingProfile(
body: .json(.init(
name: "Example name",
email: "alex@example.com",
phone: "+44 7700 900123",
dateOfBirth: "<date_of_birth>"
))
).ok.body.json
print(response){
"profile": {
"can_message": true,
"has_name": true,
"has_email": true,
"name": "Example name",
"email": "alex@example.com"
}
}Marks every message the store has sent in this conversation as read and clears the customer's unread count. Call it when the customer actually has the chat on screen. Idempotent: re-entering an already-read conversation changes nothing and notifies nobody.
Store whose conversation this refers to.
Always true when the call succeeds.
curl -X POST "https://www.membber.com/api/v1/messaging/read" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/messaging/read", {
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.markMessagingRead(
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066"
))
).ok.body.json
print(response){
"acknowledged": true
}Files a moderation report against a single message, or against the whole conversation when no message is named. The report is queued for human review. This endpoint exists to satisfy the App Store requirement that any app carrying user-generated content gives the receiving user a way to report abuse (App Review Guideline 1.2). It is a first-class part of the messaging surface, not an optional extra: any client that renders merchant-authored messages must expose a report action. Filing the same report twice is safe, a second report against the same target while the first is still pending returns the existing report id rather than creating a duplicate. Reporting requires an existing conversation with the store.
Store whose conversation this refers to.
The specific message being reported. Omit to report the whole conversation.
Why it is being reported. 'spam' unwanted or repetitive selling; 'harassment' abuse aimed at the customer; 'inappropriate' sexual, violent or otherwise objectionable content; 'other' anything else, best paired with `details`.
spamharassmentinappropriateotherThe reporter's own description of the problem, shown to the moderator.
Id of the report, for referencing it later.
Conversation the report was filed against.
curl -X POST "https://www.membber.com/api/v1/messaging/reports" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066",
"reason": "spam"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/messaging/reports", {
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066",
reason: "spam"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.reportMessagingContent(
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066",
reason: .spam
))
).ok.body.json
print(response){
"report_id": "eaf0a006-0000-4000-8000-d0c5000000ea",
"conversation_id": "e701a257-0000-4000-8000-d0c5000000e7"
}Records a typing heartbeat so the merchant sees the typing indicator. The signal expires five seconds after the last call, so send one every few seconds while the customer is actually typing and simply stop when they do, there is nothing to clear. Best-effort by design: this is a cosmetic signal and never blocks or fails a send.
Store whose conversation this refers to.
Always true when the call succeeds.
curl -X POST "https://www.membber.com/api/v1/messaging/typing" \
-H "Authorization: Bearer $MEMBBER_TOKEN" \
-H "Idempotency-Key: 1f0e2d3c-4b5a-4678-9abc-def012345678" \
-H "Content-Type: application/json" \
-d '{
"store_id": "6659c139-0000-4000-8000-d0c500000066"
}'import { createMembberClient } from "@membber/sdk-ts";
const membber = createMembberClient({
getAccessToken: () => process.env.MEMBBER_TOKEN,
});
const { data, error } = await membber.raw.POST("/api/v1/messaging/typing", {
body: {
store_id: "6659c139-0000-4000-8000-d0c500000066"
},
headers: { "Idempotency-Key": crypto.randomUUID() },
});
if (error) {
// Typed error envelope: { error: { code, message, requestId } }
throw new Error(`${error.error.code}: ${error.error.message}`);
}
console.log(data);import MembberSwift
let client = MembberClient(
serverURL: MembberClient.productionServerURL,
tokenProvider: { session.accessToken }
)
let response = try await client.api.setMessagingTyping(
body: .json(.init(
storeId: "6659c139-0000-4000-8000-d0c500000066"
))
).ok.body.json
print(response){
"acknowledged": true
}