1. Reviews Data API
TrustWILL
  • Reviews Widget Integration
  • Reviews Data API
    • Trustoo Open API — Quick Start
    • OAuth2
      • OAuth2 Merchant Authorization
      • Get OAuth2 Authorization URL
      • OAuth2 Get / Refresh Access Token
      • Revoke Token
    • Platform Management
      • Disconnect Platform Authorization
      • Get Shop Authorization Info
      • Get Shop Installation Status
      • Cancel Platform Authorization
    • Webhooks
      • Create Shop Webhook
      • Update Shop Webhook
      • Delete Shop Webhook
      • Get Shop Webhooks
    • Reviews
      • Get Review Detail
      • Get Review List
      • Create Review
      • Delete Review
      • Get Rating
    • Media Upload
      • Get Video Upload URL
      • Get Image Upload Credentials
    • Orders
      • Get Order List
    • Customer Events
      • Get Customer Event List
    • Customers
      • Email Unsubscribe
      • Create Customer Exclusion
      • Delete Customer Exclusion
      • Get Customer Exclusion List
  • Schemas
    • SuccessResponse
    • ErrorResponse
    • Pagination
    • OAuthTokenRequest
    • Webhook
    • CreateReviewRequest
    • Review
    • Rating
    • Order
    • CustomerEvent
    • CustomerExclusion
    • ImageUploadCredentials
  1. Reviews Data API

Trustoo Open API — Quick Start

Third-party applications can obtain a store's review data from Trustoo after being authorized by the store. By subscribing to webhooks, you can receive real-time updates on review data and customer events.
Base URL: https://rapi.trustoo.io
⚠️ Important Update (November 2025)
We have upgraded our signature algorithm from SHA-256 with salt to HMAC-SHA256 for enhanced security and better cross-platform compatibility.
Key Changes:
✅ More secure authentication using industry-standard HMAC
✅ JSON key order no longer affects signature
✅ Compatible with major platforms like Shopify and Stripe
⚠️ Breaking Change: Old signatures are no longer valid
Migration Required: All existing integrations must update their signature generation code. See Section 2.2 for updated implementation examples in all languages.

1. Authentication#

Trustoo Open API supports two authentication methods. The method is auto-detected based on request headers:
MethodHeadersUse Case
HMAC SignaturePublic-Token, Sign, TimestampShop owners integrating directly
OAuth 2.0 Bearer TokenAuthorization: Bearer <access_token>Third-party platforms integrating on behalf of merchants
Auto-detection rule: If the Authorization header is present and non-empty, OAuth 2.0 Bearer Token is attempted. Otherwise, HMAC Signature authentication is used.

1.1 HMAC Signature Authentication#

This is the simplest authentication method for shop owners who want to call the API directly.

Obtaining Your Tokens#

Merchants can obtain their tokens through the Trustoo dashboard or via API:
EndpointDescriptionAuthentication
GET /api/v1/openapi/get_open_api_informationRetrieve the shop's Public TokenJWT (shop merchant session)
GET /api/v1/openapi/get_open_api_private_tokenRetrieve the shop's Private TokenJWT (shop merchant session)
Public Token — The unique identifier of the store. Safe to share with third-party developers.
Private Token — The secret key used to compute HMAC signatures. Keep this confidential. If leaked, contact us immediately for a reset.
⚠️ After a reset, the original private token becomes immediately invalid. Update all authorized third-party applications with the new token.

Required Headers#

HeaderDescriptionExample
Public-TokenYour shop's public tokenGfKu22TCaj4gULtrA3/OgA==
timestampCurrent Unix timestamp (seconds)1700465771
signHMAC-SHA256 signature (lowercase hex)c3f6910a4dc12969c819f47621e5adf...
⚠️ The timestamp is valid for 15 minutes only. Regenerate it for each request.

1.2 OAuth 2.0 Bearer Token (for Third-Party Platforms)#

If you are building a third-party platform that integrates on behalf of multiple merchants, use OAuth 2.0.

OAuth Flow#

1.
Register as a platform — Obtain your client_id, client_secret, and a webhook_url (see System Webhooks)
2.
Redirect the merchant to the OAuth authorization URL with requested scopes
3.
Receive the authorization code at your redirect_uri
4.
Exchange the code for access_token and refresh_token
5.
Call the API using Authorization: Bearer <access_token>
6.
Refresh tokens when expired
7.
Disconnect — Call POST /api/v1/openapi/oauth/disconnect to revoke the platform's authorization for a shop

OAuth Endpoints#

EndpointMethodDescription
/api/v1/openapi/get_oauth_authorize_urlGETGet the one-click authorization URL for merchants
/api/v1/openapi/oauth/authorizeGETMerchant-facing authorization page (validates and redirects with code)
/api/v1/openapi/oauth/tokenPOSTExchange authorization_code or refresh_token for tokens
/api/v1/openapi/oauth_revoke_tokenPOSTRevoke an access or refresh token
Token Lifetimes:
access_token — 1 hour
refresh_token — 30 days

1.3 OAuth Lifecycle Webhooks (System Notifications)#

In addition to the subscription-based webhooks (Section 3), Trustoo automatically sends system-level webhooks to your platform's registered webhook_url when OAuth lifecycle events occur. These events do not require a subscription — they are always delivered.
EventTriggerDescription
app/authorizedOAuth flow completedA merchant successfully authorized your platform
integration/disconnectedPlatform disconnectedA platform's authorization for a shop was revoked (via oauth/disconnect or cancel_authorization)
app/uninstalledTrustoo app uninstalledA merchant uninstalled the Trustoo app from their Shopify store (all platform authorizations are revoked)
Payload Format:
All three events share the same JSON structure:
{
  "event": "app/authorized",
  "shop_id": 59730165893,
  "platform": "instafeed",
  "timestamp": 1732180800
}
FieldTypeDescription
eventstringEvent type: app/authorized, integration/disconnected, or app/uninstalled
shop_idintegerShopify shop ID (numeric)
platformstringPlatform client_id
timestampintegerEvent timestamp (Unix epoch seconds)
Signature Verification:
System webhooks use a different signing method than shop webhooks. Verify the request using the X-Trustoo-Signature header:
HeaderDescription
X-Trustoo-SignatureHMAC-SHA256 signature (lowercase hex)
Verification Steps:
HMAC-SHA256(platform_secret, raw_request_body) → compare with X-Trustoo-Signature
The platform_secret is the client_secret you received during platform registration
Sign the raw request body (the exact bytes received, before any parsing)
Compare the computed hex signature against the X-Trustoo-Signature header
⚠️ Difference from Shop Webhooks: Shop webhooks (Section 3.5) use Open-Trustoo-Webhook-Sign + Public-Token for HMAC authentication. System webhooks use X-Trustoo-Signature signed with your platform's client_secret.

OAuth Scopes#

ScopeDescriptionIncludes
read_reviewsRead reviews and ratings—
write_reviewsCreate and delete reviews, manage webhooksread_reviews
read_ordersRead order history—
read_customer_eventsRead customer interaction events—
read_customersRead customer exclusion list—
write_customersManage customer exclusions and unsubscribesread_customers
read_shop_install_statusCheck shop installation status—
Write scopes automatically include the corresponding read scope (following Shopify convention).

Webhook Topic → Scope Mapping#

Webhook TopicRequired Scope
review/createdwrite_reviews
review/updatedwrite_reviews
review/deletedwrite_reviews
customer_event/createdread_customer_events

2. HMAC Signature Algorithm#

2.1 Signature Generation Steps#

1.
Collect Parameters — Gather all query parameters and the timestamp
2.
Sort Alphabetically — Sort all parameter keys in ascending order (a-z)
3.
Build String — Concatenate as key1=value1&key2=value2&...
4.
Append Body (POST requests only) — If there is a request body, append it after a | separator
5.
Compute HMAC-SHA256 — Use the private token as the secret key
6.
Convert to Hex — Output as a lowercase hexadecimal string

2.2 Signature Examples#

GET Request Example#

Endpoint: GET /api/v1/openapi/get_reviews
Query parameters:
product_ids=9228589138176
page_size=20
page=1
Step 1 — Add timestamp:
product_ids=9228589138176&page_size=20&page=1&timestamp=1732180800
Step 2 — Sort alphabetically:
page=1&page_size=20&product_ids=9228589138176&timestamp=1732180800
Step 3 — Compute HMAC-SHA256:
HMAC-SHA256("page=1&page_size=20&product_ids=9228589138176&timestamp=1732180800", private_token)
→ c3648110bc3f1f63e7ed54fc4390448bfd2a131b405aeed91cd26a42b3ee9a93

POST Request Example#

Endpoint: POST /api/v1/openapi/create_shop_webhook
Request body:
{"topic":"review/created","url":"https://your-webhook-url.com"}
Step 1 — Query parameters (only timestamp for this POST):
timestamp=1732180800
Step 2 — Build signature string (params + | + body):
timestamp=1732180800|{"topic":"review/created","url":"https://your-webhook-url.com"}
Step 3 — Compute HMAC-SHA256:
HMAC-SHA256("timestamp=1732180800|{\"topic\":\"review/created\",\"url\":\"https://your-webhook-url.com\"}", private_token)
→ ee5d60dd3fbc3c70e49405564f4830466a11382f088eb127c5c5237c5c9b3e91
Important Notes:
Use the exact JSON string you're sending — do not parse and re-serialize
JSON key order doesn't matter because we use the raw string
The | separator is used between parameters and body

2.3 Code Examples#

Go
Java
PHP
Node.js
C#

2.4 cURL Example#


3. Webhooks#

Trustoo provides two types of webhooks:
TypeSubscription RequiredEventsSection
Subscription WebhooksYes — subscribe via create_shop_webhookreview/created, review/updated, review/deleted, customer_event/createdBelow
System WebhooksNo — always delivered to your platform's registered webhook_urlapp/authorized, integration/disconnected, app/uninstalled1.3 OAuth Lifecycle Webhooks
⚠️ System webhooks use a different signing method (X-Trustoo-Signature signed with your client_secret). Subscription webhooks use Open-Trustoo-Webhook-Sign + Public-Token. See the respective sections for verification details.

3.1 Subscription Webhooks#

Webhooks allow Trustoo to push real-time event data to your application via HTTP POST callbacks. When a subscribed event occurs, Trustoo sends a POST request to your registered webhook URL.
Response Requirement: Your endpoint must respond with HTTP 200 and the following JSON body within 5 seconds:
{
  "code": 0,
  "message": "success"
}
⚠️ The HTTP status code must be 200. Any other status code is treated as a failure and will trigger a retry.

3.2 Setting Up Webhooks#

Use the following endpoints to manage webhook subscriptions:
EndpointMethodDescription
/api/v1/openapi/create_shop_webhookPOSTRegister a new webhook subscription
/api/v1/openapi/update_shop_webhookPOSTUpdate an existing webhook's URL
/api/v1/openapi/delete_shop_webhookPOSTDelete a webhook subscription
/api/v1/openapi/get_shop_webhooksGETList all webhook subscriptions
Webhooks are scoped to the authenticated shop or platform. Platform isolation ensures each platform only receives events for its authorized shops.

3.3 Retry Mechanism#

If a webhook delivery fails, Trustoo retries up to 10 times with increasing delays:
AttemptDelay (min)Cumulative (min)
100
233
369
4918
51230
61545
71863
82184
924108
1027135

3.4 Supported Event Types#

Event TypeDescription
review/createdTriggered when a new review is created
review/updatedTriggered when an existing review is updated
review/deletedTriggered when a review is deleted
customer_event/createdTriggered when a new customer interaction event occurs

3.5 Webhook Request Format#

Headers#

HeaderValueDescription
Content-Typeapplication/jsonFixed value
Open-Trustoo-Webhook-Public-TokenxxxxYour shop's public token
Open-Trustoo-Webhook-Timestamp1732180800Unix timestamp of the request
Open-Trustoo-Webhook-Signa37084ab...HMAC-SHA256 signature (see Section 2)
Open-Trustoo-Webhook-RequestIdkfhgdsjk...Unique request trace ID

Body#

{
  "event": "review/created",
  "shop_id": "59730165893",
  "data": { /* event-specific payload — see below */ }
}
FieldTypeDescription
eventstringEvent type (see 3.4)
shop_idstringThe Shopify shop ID
dataobjectEvent payload (varies by event type)

3.6 Event Payloads#

review/created & review/updated#

{
  "event": "review/created",
  "shop_id": "59730165893",
  "data": {
    "id": "57748",
    "rating": 5,
    "author": "John Doe",
    "author_email": "[email protected]",
    "author_phone": "+1234567890",
    "author_country": "US",
    "title": "Great product!",
    "content": "This is an amazing product, highly recommend!",
    "commented_at": "2023-11-21T12:34:56Z",
    "item_type": "product",
    "order_id": "1001",
    "variant_id": "789",
    "source": "email",
    "is_verified": 1,
    "is_featured": 0,
    "is_published": 1,
    "is_top": 0,
    "tag": "",
    "media_type": 1,
    "media": [
      { "url": "https://cdn.example.com/image1.jpg", "thumbnail_url": "https://cdn.example.com/thumb1.jpg", "type": 1, "is_published": 1 },
      { "url": "https://cdn.example.com/video1.mp4", "thumbnail_url": "https://cdn.example.com/thumb2.jpg", "type": 2, "is_published": 1 }
    ],
    "reply": {
      "id": "reply_001",
      "content": "Thank you for your review!",
      "reply_at": "2023-11-22T09:00:00Z"
    },
    "product": {
      "id": "789",
      "title": "Awesome Product",
      "handle": "awesome-product",
      "image_src": "https://cdn.example.com/product.jpg",
      "url": "https://example.myshopify.com/products/awesome-product"
    },
    "created_at": "2023-11-21T12:34:56Z",
    "updated_at": "2023-11-21T12:45:00Z"
  }
}
FieldTypeDescription
idstringUnique review ID
ratingintegerRating 1–5
authorstringReviewer name
author_emailstringReviewer email
author_phonestringReviewer phone number
author_countrystringCountry code (ISO 3166-1 alpha-2)
titlestringReview title
contentstringReview text
commented_atstringReview timestamp (RFC 3339)
item_typestringItem type (e.g., product)
order_idstringAssociated order ID
variant_idstringProduct variant ID
sourcestringReview source (email, storefront, admin, etc.)
is_verifiedintegerVerified purchase: 1 = Yes, 0 = No
is_featuredintegerFeatured: 1 = Yes, 0 = No
is_publishedintegerPublished: 1 = Yes, 0 = No
is_topintegerPinned to top: 1 = Yes, 0 = No
tagstringTag label
media_typeintegerMedia type: 1 = Image, 2 = Video
mediaarrayList of attached media objects: url (string), thumbnail_url (string), type (integer: 1=image, 2=video), is_published (integer: 1=Yes, 0=No)
replyobjectMerchant reply with id, content, reply_at (null if no reply)
productobjectAssociated product info: id, title, handle, image_src, url
created_atstringCreated timestamp (RFC 3339)
updated_atstringLast updated timestamp (RFC 3339)

review/deleted#

{
  "event": "review/deleted",
  "shop_id": "59730165893",
  "data": {
    "id": "57853",
    "deleted_at": "2026-05-19T06:58:30Z"
  }
}
FieldTypeDescription
idstringDeleted review ID
deleted_atstringDeletion timestamp (RFC 3339)

customer_event/created#

{
  "event": "customer_event/created",
  "shop_id": "59730165893",
  "data": {
    "id": "12345",
    "client_id": "cli_abc123",
    "event_type": "VIEW_REVIEW",
    "event_source": "STOREFRONT",
    "device_type": "Mobile",
    "os_type": "IOS",
    "page_url": "https://example.myshopify.com/products/awesome-product",
    "created_at": "2023-11-21T14:30:00Z",
    "properties": "{\"review_id\":\"57748\",\"product_id\":\"789\"}"
  }
}
FieldTypeDescription
idstringUnique event ID
client_idstringClient identifier
event_typestringEvent type: VIEW_REVIEW, EXPAND_CONTENT, SUBMIT_REVIEW, CLICK_REVIEW, etc.
event_sourcestringSource: STOREFRONT, EMAIL, ADMIN
device_typestringDevice: Desktop, Mobile, Tablet
os_typestringOperating system: IOS, ANDROID, WINDOWS, etc.
page_urlstringPage URL where the event occurred
created_atstringEvent timestamp (RFC 3339)
propertiesstringJSON string with detailed event information

3.7 Testing Webhooks#

To accelerate integration development, you can manually trigger test webhook events without waiting for real user actions. Use the following endpoint to simulate webhook delivery:
EndpointMethodDescription
/api/v1/openapi/send_test_webhookPOSTSend a simulated webhook event to your registered webhook URL
Request Body:
{
  "topic": "review/created",
  "data": {
    "id": "99999",
    "rating": 5,
    "content": "This is a test review"
  }
}
FieldTypeRequiredDescription
topicstringYesEvent type to simulate. One of: review/created, review/updated, review/deleted, customer_event/created, app/authorized, integration/disconnected, app/uninstalled
dataobjectNoCustom payload data to include. If omitted, a sample payload is used.
Notes:
The webhook is sent to the same URL you registered via create_shop_webhook (for subscription events) or your platform's registered webhook_url (for system events)
The request is signed with the same signature mechanism as real webhooks (Open-Trustoo-Webhook-Sign for subscription events, X-Trustoo-Signature for system events)
This endpoint is intended for development and testing only — use it to verify your webhook handler's signature verification, payload parsing, and retry logic before going live
Example — Simulate a review/created event:
Example — Simulate with custom data:

4. API Overview#

Available Endpoints by Category#

OAuth2
EndpointMethodDescription
/api/v1/openapi/get_oauth_authorize_urlGETGet the one-click authorization URL for merchants
/api/v1/openapi/oauth/authorizeGETMerchant-facing authorization page (validates and redirects with code)
/api/v1/openapi/oauth/tokenPOSTExchange authorization_code or refresh_token for tokens
/api/v1/openapi/oauth_revoke_tokenPOSTRevoke an access or refresh token
Webhooks
EndpointMethodDescription
/api/v1/openapi/create_shop_webhookPOSTRegister a new webhook subscription
/api/v1/openapi/update_shop_webhookPOSTUpdate an existing webhook's URL
/api/v1/openapi/delete_shop_webhookPOSTDelete a webhook subscription
/api/v1/openapi/get_shop_webhooksGETList all webhook subscriptions
/api/v1/openapi/send_test_webhookPOSTSend a simulated webhook event for testing
Reviews
EndpointMethodDescription
/api/v1/openapi/get_reviewsGETList reviews with pagination and filters
/api/v1/openapi/get_reviewGETGet a single review by ID
/api/v1/openapi/get_ratingGETGet aggregate rating data
/api/v1/openapi/create_reviewPOSTCreate a new review
/api/v1/openapi/delete_reviewPOSTDelete a review
Orders
EndpointMethodDescription
/api/v1/openapi/get_ordersGETQuery order history
Customer Events
EndpointMethodDescription
/api/v1/openapi/get_customer_eventsGETQuery customer interaction events
Customers
EndpointMethodDescription
/api/v1/openapi/get_customer_excludesGETList customer exclusions
/api/v1/openapi/create_customer_excludePOSTAdd a customer to the exclusion list
/api/v1/openapi/delete_customer_excludePOSTRemove a customer from the exclusion list
/api/v1/openapi/email_unsubscribePOSTUnsubscribe a customer from emails
Media Upload
EndpointMethodDescription
/api/v1/openapi/get_video_upload_urlGETGet a pre-signed video upload URL
/api/v1/openapi/get_image_upload_policy_tokenGETGet an image upload policy token
Platform Management
EndpointMethodDescription
/api/v1/openapi/get_shop_install_statusGETCheck shop installation status
/api/v1/openapi/get_shop_authorization_infoGETGet shop authorization details
/api/v1/openapi/oauth/disconnectPOSTDisconnect (revoke) a platform's authorization

5. Error Handling#

All API responses use HTTP 200 with a JSON body containing a business status code:
{
  "code": 0,
  "reason_code": 0,
  "message": "success",
  "data": {},
  "request_id": "abc123",
  "time": 1732180800
}
FieldTypeDescription
codeinteger0 = success, non-zero = error (gRPC status code)
reason_codeintegergRPC status code for programmatic handling
messagestringUser-facing error description
dataobjectResponse payload (null on error)
request_idstringUnique request trace ID
timeintegerServer timestamp (Unix epoch seconds)

Status Codes#

CodeStatusMessageDescription
0OKsuccessRequest succeeded
1CanceledSorry, something went wrong. Please try again later.Operation was canceled
2UnknownSorry, something went wrong. Please try again later.Unknown error
3InvalidArgumentSorry, parameter error.Client specified an invalid argument
4DeadlineExceededSorry, the server is busy. Please try again later.Deadline expired (e.g., HMAC timestamp > 15 min)
5NotFoundSorry, data not found.Requested entity not found (e.g., shop, review)
6AlreadyExistsSorry, data already exists.Entity already exists (e.g., duplicate webhook)
7PermissionDeniedSorry, no permission.Insufficient OAuth scope or shop not authorized
8ResourceExhausted—Operation was rejected due to resource limits
11OutOfRangeSorry, data size too large.Data exceeds size limits
13Internal—Internal server error
16UnauthenticatedSorry, authentication failed.Invalid signature, expired token, or missing credentials

Common Error Scenarios#

ScenarioCodeFix
HMAC timestamp expired4Ensure your server clock is synchronized and the timestamp is within 15 minutes
HMAC signature mismatch16Verify signature computation: HMAC-SHA256(privateToken, sortedParams + | + body)
OAuth access token expired16Use refresh_token to obtain a new access_token
Insufficient OAuth scope7Re-authorize the merchant with the required scopes via /oauth/authorize
Shop not authorized for platform7The merchant needs to complete the OAuth authorization flow
Shop granted scopes changed7The merchant's granted scopes have been modified; re-authorization is needed
Invalid parameters3Check required fields and parameter formats
Webhook topic not supported3Use a valid topic: review/created, review/updated, review/deleted, customer_event/created

6. Full API Reference#

For detailed request/response schemas, authentication requirements, and parameter descriptions for every endpoint, see the OpenAPI specification:
📄 Default module.openapi.json — Complete OpenAPI 3.0.3 specification

Support#

API Support: [email protected]
Dashboard: Available in your Trustoo store backend
Modified at 2026-06-24 06:38:50
Previous
Reviews Widget Integration
Next
OAuth2 Merchant Authorization
Built with