API Quick Reference
On this page
One-page summary of the TNID API: environments, authentication, the two GraphQL servers, every feature area, webhooks and pagination. Written for developers and AI coding assistants.
This page condenses the TNID API into a single read. Where this site has a guide page, it is linked. Where an operation exists in the API but has no guide here yet, the row points at the API Reference, which is regenerated from the API source and documents every query, mutation, type and enum with request, variables and response examples.
For AI assistants: this site is served as Markdown at https://support.tsgglobal.com/docs/tnid/llms.txt and https://support.tsgglobal.com/docs/tnid/llms-full.txt, any page can be fetched by appending .md to its URL, and a read-only MCP server is available at https://support.tsgglobal.com/docs/tnid/mcp/. See AI Assistants & MCP.
What TNID is
TNID is an identity and consent platform for people and businesses. A user owns a personal profile (verified emails, phone numbers, addresses) and decides which companies may connect with them and message them on which channels. A company owns a business profile, connects with other companies (B2B) and with people (B2C), manages subscriptions and opt-outs, registers 10DLC brands and campaigns, and receives webhooks when any of that changes.
Environments
| Environment | API host | Web app |
|---|---|---|
| Staging | https://api.staging.v2.tnid.com |
https://app.staging.v2.tnid.com |
| Zero (pre-production) | https://api.zero.v2.tnid.com |
https://app.zero.v2.tnid.com |
| Production | Provided by TSG when your integration is approved. Contact support@tsgglobal.com. | https://app.tnid.com |
All requests must use HTTPS. Accounts are invite-only at present. Rate limits are applied per token; the current values are not published, contact support@tsgglobal.com for your account's limits.
Two GraphQL servers, one auth service
| Path | Who calls it | Token |
|---|---|---|
POST /user |
A person acting as themselves | User access token |
POST /company |
Software acting for a company | Company access token |
POST /auth/create-user-otp |
Start a user login (also accepted as /auth/create_user_otp) |
none |
POST /auth/token |
Exchange an OTP (user) or client credentials (company) for tokens | none |
POST /auth/refresh-token |
Exchange a refresh token for a new token pair | none |
The user and company schemas overlap in naming but are separate. A query that exists on /company (for example b2bConnections) is not available on /user, and vice versa.
Authentication
| Flow | Steps |
|---|---|
| User, by phone or email | 1. POST /auth/create-user-otp with {"telephone_number": "..."} or {"email": "..."}; add first_name, last_name, email to create a new user. Response includes expires_at, next_otp_at, remaining_otp_attempts. 2. POST /auth/token with {"telephone_number" or "email", "otp_code"}. Response: access_token, refresh_token. See User Authentication. |
| Company, by client credentials | Create a company as a user with provisionCompanyClientSecret: true, or mint a secret later with createCompanyClientSecret or in the web app. Then POST /auth/token with {"client_id", "client_secret"}. See Company Authentication. |
| Refresh | POST /auth/refresh-token with {"refresh_token"}. Access tokens last 7 days, refresh tokens 30 days. See Refresh Token. |
Send the token on every GraphQL call as Authorization: Bearer <access_token>. Client secrets are shown once at creation; store them in a secret manager and rotate by creating a new secret and deleting the old one (clientSecrets, createClientSecret, deleteClientSecret on /company).
Conventions
- Requests are JSON over
POST; GraphQL bodies are{"query": "...", "variables": {...}}. - Custom scalars:
JSON(free-form metadata),NaiveDateTime(2026-01-15T09:00:00),Date,Time. IDs are UUIDs. - Most list queries take
limitand return a plain array. Every list that can grow also has apaginated…twin (for examplepaginatedB2bConnections) that takeslimitandcursorand returnspaginationInfo { limit nextCursor }plusrecords; page untilnextCursoris null. 10DLC lists usepage/pageSizeinstead. See Pagination. - Profile fields carry visibility settings (
CompanyVisibilityType,UserVisibilityType); what a caller can see depends on their relationship to the record. - Connection and subscription requests follow one pattern:
create…Request→ the other side sees it inreceived…Requests→respond…RequestwithACCEPTorREJECT→ it appears in…Connections. The sender canrevoke…Requestwhile pending. - Unauthenticated calls return HTTP 401 with
{"error": {"summary": "Authorization failed…"}}. Validation failures return 400 with amessage.
Feature map
Coverage column: Guide means a walkthrough exists on this site; Reference means the operation is documented only in the API Reference so far.
/user server
| Area | Key operations | Coverage |
|---|---|---|
| Profile | currentUser, updateUser |
Guide: Update User profile |
| Contact details | createUserEmail, createUserEmailVerificationCode, verifyUserEmail, setPrimaryUserEmail, removeUserEmail; same set for telephone numbers; createUserAddress, updateUserAddress, removeUserAddress |
Reference: emails, addresses, phone numbers |
| People (C2C) connections | createC2cConnectionRequest, createC2cInvite, pendingC2cConnectionRequests, receivedC2cConnectionRequests, respondC2cConnectionRequest, revokeC2cConnectionRequest, c2cConnections, removeC2cConnection |
Guide: Company Features (C2C pages) |
| Company (C2B) connections | createC2bConnectionRequest, pendingC2bConnectionRequests, receivedB2cConnectionRequests, respondB2cConnectionRequest, revokeC2bConnectionRequest, removeC2bConnection, b2cConnections |
Guide: Connections |
| Subscriptions | respondB2cSubscriptionRequest, upsertB2cSubscription, removeB2cSubscription, b2cSubscriptions, pendingB2cSubscriptionRequests |
Guide: Respond to B2C Subscription Request, Remove B2C Subscription |
| Spam reporting | createSpamReport, spamReports, paginatedSpamReports |
Guide: Spam Reporting Features |
| Groups | groups, group, userGroups, userGroupMembers, createGroup, updateGroup, leaveGroup, updateGroupUserMemberRole, removeGroupUserMember, invites and join requests |
Guide: Group Features |
| Company management | createCompany, createCompanyClientSecret, deleteCompany, switchableCompanies, setupInvitationFromToken |
Guide: Create company profile; rest Reference: company management |
| Search | users, user, userByUsername, globalSearch (users, companies and groups in one list; 3-character minimum) |
Guide: Search User (People); globalSearch Reference: users and search |
| Documents and AI tasks | prepareFileUpload, prepareDocumentUpload, confirmDocumentUpload, folders, tags, trash, askUserDocumentQuestion, AI tasks (createUserAiTask, runUserAiTask, aiTaskRuns) |
Reference: documents |
| Notifications | notifications, recentNotifications, unreadNotificationCount, mark-as-read mutations, notification settings per group and per B2C connection |
Reference: notifications |
| Forms | receivedFormSubmissionRequests, rejectFormSubmissionRequest |
Reference: forms |
| Account | currentUserSettings, updateUserSettings, dashboardStats, onboardingStatus, completeOnboardingStep, createSupportRequest, interests, pendingActionCounts |
Reference: account |
| Docs assistant | askDocsQuestion answers a natural-language question from this documentation |
Reference: assistant |
/company server
| Area | Key operations | Coverage |
|---|---|---|
| Profile | currentCompany, updateCompany, companies (search), createB2bInvite |
Guide: Search Companies, Invite Company, Update Company Profile |
| Contact details | Create, verify, update, remove company emails, telephone numbers and addresses | Reference: emails, addresses, phone numbers |
| 10DLC | API keys (addTenDlcApiKey, authorizeTenDlcApiKey), brands (registerTenDlcBrandAsDraft, registerAndSubmitTenDlcBrand, updateAndSubmitTenDlcBrand, tenDlcBrands), campaigns (saveTenDlcCampaignAsDraft, registerAndSubmitTenDlcCampaign, registerTenDlcCampaignWhenReady, tenDlcCampaignWithTelephoneNumbers) |
Guide: 10DLC Brands, 10DLC Campaigns |
| B2B connections | createB2bConnectionRequest, b2bConnections, pendingB2bConnectionRequests, receivedB2bConnectionRequests, respondB2bConnectionRequest, revokeB2bConnectionRequest, removeB2bConnection |
Guide: B2B Features |
| B2C connections | createB2cConnectionRequest, createB2cInvite, b2cConnections, pendingB2cConnectionRequests, receivedC2bConnectionRequests, respondC2bConnectionRequest, revokeB2cConnectionRequest, removeB2cConnection |
Guide: B2C Features |
| Subscriptions and topics | createB2cSubscriptionRequest, b2cSubscriptions, pendingB2cSubscriptionRequests, revokeB2cSubscriptionRequest, removeB2cSubscription; topics: b2cSubscriptionTopics, createB2cSubscriptionTopic, updateB2cSubscriptionTopic, removeB2cSubscriptionTopic |
Guide: B2C Features; topics Reference: subscriptions |
| Opt-out and opt-in | optOutRequests, createOptOutRequest, generateSmsOptInQrCode |
Guide: List Opt-Out Requests, Create Opt-out Request, Generate SMS Opt-In QR Code |
| People search | users, user, userByUsername, globalSearch |
Guide: Search People |
| Documents and AI tasks | Same document, folder, tag, trash and AI-task operations as the user server, scoped to the company | Reference: documents |
| Forms | createForm, createFormVersion, publishFormVersion, companyForms, createB2cFormSubmissionRequest, createB2bFormSubmissionRequest, formSubmissions, formSubmission |
Reference: forms |
| Webhooks | companyWebhooks, createCompanyWebhook, updateCompanyWebhook, removeCompanyWebhook |
Guide: Webhooks |
| Invitation links | companyInvitationLinks, createCompanyInvitationLink, updateCompanyInvitationLink, deleteCompanyInvitationLink |
Reference: invitation links |
| Client secrets | clientSecrets, createClientSecret, updateClientSecret, deleteClientSecret |
Reference: client secrets |
| User imports | importUsersFromCsv (from a prepareFileUpload key; can create connections and request subscriptions in bulk), userImports, userImport |
Reference: user imports |
| Sentiment analysis | reportExternalCommunication (send message traffic for analysis; auto-subscribes or flags an unsubscribe and calls your webhook), feedbackOnDetectedUnsubscribe, sentimentAnalysisResults |
Reference: sentiment analysis |
| RCS and AI suggestions | companyRcsInformation, upsertCompanyRcsInformation, getAiCompanyProfileSuggestions, getAiRcsSuggestions, getAiFormSuggestionsFromUrl, getAiFormSuggestionsFromFile |
Reference: RCS and AI suggestions |
| Notifications, settings, assistant | notifications, unreadNotificationCount, companySettings, updateCompanySettings, companyDashboardStats, pendingActionCounts, askDocsQuestion |
Reference: notifications, settings |
| Reference data | organizationTypes, verticalTypes, specialties |
Guide: List Organization Types, List Vertical Types |
Webhooks
Companies register webhooks with createCompanyWebhook on /company: a target url, an optional bearerToken TNID sends back in the Authorization header, optional customHeaders, and one boolean per event type:
| Flag | Fires when |
|---|---|
receiveSubscriptionEvents |
A person subscribes, changes or removes a subscription to your company |
receiveOptOutEvents |
An opt-out is recorded |
b2bConnectionRequestReceivedWebhook |
Another company asks to connect |
b2bConnectionRequestResponseWebhook |
A company responds to your request |
b2cConnectionRequestResponseWebhook |
A person responds to your connection request |
c2bConnectionRequestReceivedWebhook |
A person asks to connect with you |
b2cSubscriptionRequestResponseWebhook |
A person responds to your subscription request |
companySocialNetworkStatusChangeWebhook |
A social-network link on your profile changes verification status |
b2bFormInstanceSubmissionRequestReceivedWebhook |
Another company asks you to fill in a form |
Sentiment analysis also posts to your webhook when it detects an unsubscribe: {"external_communication_id": "...", "timestamp": "...", "action": "unsubscribe"}. Confirm or deny it with feedbackOnDetectedUnsubscribe. Full guide: Webhooks.
Minimal examples
Request a login code, then a token (staging):
curl -X POST https://api.staging.v2.tnid.com/auth/create-user-otp \
-H "Content-Type: application/json" \
-d '{"telephone_number":"15555550100"}'
curl -X POST https://api.staging.v2.tnid.com/auth/token \
-H "Content-Type: application/json" \
-d '{"telephone_number":"15555550100","otp_code":"123456"}'
Authenticate as a company and search for companies:
TOKEN=$(curl -s -X POST https://api.staging.v2.tnid.com/auth/token \
-H "Content-Type: application/json" \
-d '{"client_id":"<client_id>","client_secret":"<client_secret>"}' | jq -r .access_token)
curl -X POST https://api.staging.v2.tnid.com/company \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"query":"query($name:String,$limit:Int){ companies(name:$name, limit:$limit){ id legalName brandName verified } }","variables":{"name":"Acme","limit":5}}'
Page through B2B connections:
curl -X POST https://api.staging.v2.tnid.com/company \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"query":"query($limit:Int,$cursor:String){ paginatedB2bConnections(limit:$limit, cursor:$cursor){ paginationInfo { limit nextCursor } records { id type connectedCompany { id legalName } } } }","variables":{"limit":50}}'
Pass paginationInfo.nextCursor back as cursor until it is null.
Support and related links
- Support: support@tsgglobal.com
- API Reference, regenerated from the API source (queries, mutations, types, enums and input types under "Definitions")
- Guides: Pagination, Webhooks, 10DLC Brands, 10DLC Campaigns, Changelog
- Postman setup and schema introspection: Accessing via Postman
- Machine-readable copies of this site:
https://support.tsgglobal.com/docs/tnid/llms.txt,https://support.tsgglobal.com/docs/tnid/llms-full.txt,<page>.md, MCP athttps://support.tsgglobal.com/docs/tnid/mcp/