Skip to content

Contact Support

One Contact Support gives every App a focused customer conversation system:

  • Send a Message
  • Report a Bug
  • Suggest a Feature
  • Complete customer/support conversation history
  • Optional email and push notifications when Support replies
  • Exact-thread notification deep links when the host supports push

The SDK generates an internal subject from the App and runtime. Do not show a subject field to customers.

Use @repo/sdk-web-core for Electron, macOS, Windows, or another headless JS runtime. Create one client for the app process and set its actual platform.

import { createOneClient, type SupportDiagnostics } from '@repo/sdk-web-core';
const one = createOneClient({
publicKey: onePublicKey,
platform: 'macos', // or 'windows'
appVersion
});
function collectSupportDiagnostics(): SupportDiagnostics {
return {
transferCount: currentTransferCount,
localNetworkAvailable: currentLocalNetworkState,
selectedFolder: selectedFolderName ?? null
};
}

Create a conversation:

const thread = await one.support.createThread({
category: 'bug', // 'message' | 'bug' | 'feature'
body: message,
email: customerEmail,
diagnostics: collectSupportDiagnostics()
});

Reply with fresh app data:

const updated = await one.support.reply(thread.id, {
body: reply,
diagnostics: collectSupportDiagnostics()
});

Collect diagnostics immediately before every create and reply. One separately attaches authoritative current customer, identity, entitlement, App, environment, platform, SDK, locale, and version context on the server for every customer message.

const page = await one.support.listThreads({ limit: 50 });
const conversation = await one.support.getThread(threadId);
const contact = await one.support.getContact();
await one.support.markRead(threadId);
await one.support.resolve(threadId);

Refresh on screen entry, after a customer action, or after a support notification. Do not poll or wrap these calls in another retry loop.

Use the complete customer UI from @repo/sdk-web inside OneProvider:

import { ContactSupport } from '@repo/sdk-web';
import '@repo/sdk-web/styles.css';
<ContactSupport
initialThreadId={supportThreadId}
defaultEmail={customerEmail}
emailRequirement="optional"
emailVerificationMode="optional"
magicLinkRedirectUrl="simpleshare://auth"
showsPushNotificationOption={true}
getDiagnostics={collectSupportDiagnostics}
/>

For a non-React webview or Desktop renderer, mount the same UI:

import { mountContactSupport } from '@repo/sdk-web';
const mounted = mountContactSupport({
client: one,
container: document.querySelector('#support')!,
initialThreadId: supportThreadId,
getDiagnostics: collectSupportDiagnostics
});
mounted.unmount();

Place the component under OneProvider, or pass a client explicitly:

<script lang="ts">
import { ContactSupport } from '@repo/sdk-svelte';
</script>
<ContactSupport
initialThreadId={supportThreadId}
defaultEmail={customerEmail}
getDiagnostics={collectSupportDiagnostics}
/>

Use the SDK’s prepare/upload/claim flow rather than sending file bytes through the message endpoint:

const bytes = await file.arrayBuffer();
const checksumSha256 = await sha256Hex(bytes);
const prepared = await one.support.prepareAttachmentUpload({
fileName: file.name,
contentType: file.type || 'application/octet-stream',
byteSize: file.size,
checksumSha256
});
await one.support.uploadAttachment(prepared, bytes, file.type);
await one.support.reply(thread.id, {
body: reply,
attachmentTokens: [prepared.uploadToken],
diagnostics: collectSupportDiagnostics()
});

The complete iOS and React support surfaces provide Camera, Photos, and Files. They compress Camera/Photos images before upload, allow up to five attachments per message, and keep the resulting objects private in One storage.

Section titled “Email, magic links, and notification deep links”

Email deliverability belongs to the customer’s One Auth identity rather than Support. Native apps can read customerInfo.emailUnreachable (or the refreshed AuthUser.emailUnreachable); web clients receive the same property on the Auth user. It becomes true only after a permanent provider rejection. Magic-link requests also return emailUnreachable; callers must not show “check your email” when it is true. Support reuses this signal for its email warning.

Support stores its email and push flags in the customer’s notification preferences. An unverified email can receive generic reply notifications. When verification is enabled, the tenant-owned magic-link template upgrades that email into the customer’s passwordless One Auth identity; Support does not keep a second email identity. Once One Auth supplies the email, Support displays it as account-managed and does not allow the notification settings to replace it. A verified support-only address remains editable. The standard SDK UI confirms a replacement, and separately warns before a magic link for a different address can sign in to or link that address’s customer account. One never parses inbound email replies or includes message or attachment content in notification email.

The tenant-owned support_reply_notification template is notification-only and must direct the customer back to the app. To show its optional Open conversation button, set the template variable supportDeepLinkBaseUrl to the app-owned support URL without a query string. One appends one_support_thread_id and one_support_message_id; the host reads the thread ID and opens the support surface with that conversation selected. Keep those IDs inside the link rather than displaying them as a customer-facing reference.

On iOS, first validate the app-owned scheme or universal-link host, then use SupportNotificationDestination(url:) and present SupportView(threadId: destination.threadId). On web/Desktop, use client.support.deepLinkDestination(url). Reuse an existing app URL scheme; plist or Associated Domains changes are only needed when no suitable route exists.

When a host receives notification data, recognize the support payload and open the exact conversation:

const destination = one.support.notificationDestination(notificationData);
if (destination) {
openContactSupport(destination.threadId);
}

This method parses support_reply data; it does not provision browser or Desktop push delivery. Use verified email until the host has a supported native notification transport. Never embed a One secret key in a website, renderer, or Desktop webview.