Webhooks
Learn how to receive real-time notifications from Reewild about receipt processing events, points awards, and transaction updates using webhooks.
Overview
Webhooks enable Reewild to notify your system in real-time when important events occur during receipt processing and points calculation. Instead of repeatedly polling our API to check for updates, webhooks push notifications directly to your server as soon as events happen.
Receipt processing involves multiple stages-from initial upload through OCR extraction, validation, scoring, and final completion. Webhooks keep you informed at each critical step, allowing you to update your user interface, send notifications, or trigger business logic immediately.
Key benefits:
- Real-time updates - Know instantly when receipts are processed and points are awarded
- Reduced API calls - No need to poll endpoints repeatedly
- Better UX - Update your app UI immediately when processing completes
- Error handling - Receive failure notifications with detailed error types
- Audit trail - Track the complete lifecycle of each receipt
How Webhooks Work
Registration
During onboarding, you provide Reewild with your webhook endpoint URL (e.g., https://bank.com/api/webhooks/reewild). This is where we'll send all event notifications.
Event Occurs
When something happens in the PlanetPoints system (receipt uploaded, processing completed, error occurred), Reewild generates an event payload.
HTTP POST Request
Reewild sends an HTTP POST request to your webhook URL with the event data in JSON format, including a signature header for security verification.
Your Response
Your server validates the signature, processes the event data, and responds with a 200 OK status code to acknowledge receipt.
Retry Logic
If your endpoint doesn't respond with 200 OK, Reewild automatically retries the webhook with exponential backoff (up to 3 attempts over 24 hours).
Webhook Events
Reewild sends webhook events that track the complete lifecycle from user enrollment through receipt processing and rewards:
Event Types
| Event | Description | When It's Sent |
|---|---|---|
user.enrolled | User successfully enrolled | After user completes enrollment through hosted page |
receipt.uploaded | Receipt session initiated | When upload session is created |
receipt.extracted | OCR extraction completed | After text/data extracted from image |
receipt.enriched | Merchant data enriched | After business details and branding added |
receipt.validated | Transaction data validated | After matching with transaction metadata |
receipt.scored | Products matched and scored | After sustainability scoring completed |
rewards.awarded | Points calculated and awarded | Final stage - points added to user account |
receipt.failed | Processing failed with error | When validation or processing fails at any stage |
Event Payloads
1. user.enrolled
Sent when a user successfully completes enrollment through the hosted enrollment page.
Use case: Confirm user account creation and store the generated userID for future API calls.
{
"eventType": "user.enrolled",
"data": {
"applicationDetails": {
"id": "34F67CBEA3CD42CCADCB5C7B358ACBA8",
"name": "your_app_name",
"sourceType": 2
},
"userID": "00B4N5",
"email": "user@example.com",
"availablePoints": 0,
"lifetimePoints": 0,
"numOfTransactions": 0,
"totalCarbonScore": 0,
"totalGreenProducts": 0,
"createdAt": "2025-11-21T15:00:45.1070976",
"updatedAt": "2025-11-21T15:00:45.1071064"
}
}Payload fields:
| Field | Type | Description |
|---|---|---|
eventType | String | Always user.enrolled |
data.applicationDetails | Object | Your application information |
data.userID | String | Generated user ID - save this for all future API calls |
data.email | String | User's email address |
data.availablePoints | Number | Initial available points (0) |
data.lifetimePoints | Number | Initial lifetime points (0) |
data.numOfTransactions | Integer | Initial transaction count (0) |
data.totalCarbonScore | Number | Initial carbon score (0) |
data.totalGreenProducts | Integer | Initial green products count (0) |
data.createdAt | String | Account creation timestamp |
data.updatedAt | String | Last update timestamp |
2. receipt.uploaded
Sent when a receipt upload session is successfully created (not when the actual image is uploaded).
Use case: Track receipt upload session creation and confirm the user has initiated the scan flow.
{
"eventType": "receipt.uploaded",
"data": {
"applicationDetails": {
"id": "34F67CBEA3CD42CCADCB5C7B358ACBA8",
"name": "your_app_name",
"sourceType": 2
},
"profileID": "027KO2",
"amount": 6.0,
"merchantName": "Tesco",
"transactionId": "TXN-123",
"transactionTimestamp": "2025-11-07T19:12:34.567Z",
"receiptID": "133f1eb5-2c91-4a95-ad87-2ae6de6e8df0",
"uploadedAt": "2025-11-21T15:05:02.5569459Z"
}
}Payload fields:
| Field | Type | Description |
|---|---|---|
eventType | String | Always receipt.uploaded |
data.applicationDetails | Object | Your application information |
data.profileID | String | User's profile ID |
data.amount | Number | Transaction amount provided |
data.merchantName | String | Merchant name provided |
data.transactionId | String | Your transaction reference |
data.transactionTimestamp | String | Transaction timestamp |
data.receiptID | String | Generated receipt ID for tracking |
data.uploadedAt | String | Upload session creation timestamp |
3. receipt.extracted
Sent after OCR processing completes and product data has been extracted from the receipt image.
Use case: Show users the extracted items for verification or display processing progress.
{
"eventType": "receipt.extracted",
"data": {
"applicationDetails": {
"id": "34F67CBEA3CD42CCADCB5C7B358ACBA8",
"name": "your_app_name",
"sourceType": 2
},
"userID": "027KO2",
"blobUri": "https://storage.example.com/receipts/20251008105428.jpg",
"country": "GBR",
"currency": "GBP",
"items": [
{
"description": "Tesco Maris Piper Potatoes 2kg",
"quantity": 1,
"totalPrice": 1.8,
"accuracy": 0.995,
"cleanedName": "",
"category": ""
},
{
"description": "Tesco Tenderstem Broccoli Spears 330g",
"quantity": 1,
"totalPrice": 2.4,
"accuracy": 0.995,
"cleanedName": "",
"category": ""
},
{
"description": "Tesco Fine Beans 200g",
"quantity": 1,
"totalPrice": 1.3,
"accuracy": 0.994,
"cleanedName": "",
"category": ""
}
],
"merchantAddress": "",
"merchantName": "TESCO",
"receiptID": "fb2cdc63-6d13-4176-89ae-7a424b69d7b5",
"receiptSource": 1,
"receiptType": "Supplies",
"subTotal": 6.33,
"transactionDate": "2025-10-08T00:00:00+00:00",
"transactionTime": "11:47:00"
}
}Payload fields:
| Field | Type | Description |
|---|---|---|
eventType | String | Always receipt.extracted |
data.userID | String | User's ID |
data.blobUri | String | URL to stored receipt image |
data.merchantName | String | Extracted merchant name |
data.country | String | ISO 3166 country code (GBR, USA, etc.) |
data.currency | String | ISO currency code (GBP, USD, EUR) |
data.items | Array | Extracted product items |
data.items[].description | String | Product name/description from receipt |
data.items[].quantity | Integer | Quantity purchased |
data.items[].totalPrice | Number | Line item total price |
data.items[].accuracy | Number | OCR confidence score (0-1) |
data.receiptType | String | Receipt category |
data.merchantAddress | String | Store location (if available) |
data.subTotal | Number | Receipt subtotal |
data.transactionDate | String | Date from receipt |
data.transactionTime | String | Time from receipt |
data.receiptID | String | Receipt identifier |
data.receiptSource | Integer | Source type (1=scan, 2=API, etc.) |
4. receipt.enriched
Sent after merchant data has been enriched with business details and branding.
Use case: Access enhanced merchant information including logos and standardized business names.
{
"eventType": "receipt.enriched",
"data": {
"applicationDetails": {
"id": "34F67CBEA3CD42CCADCB5C7B358ACBA8",
"name": "your_app_name",
"sourceType": 2
},
"userID": "027KO2",
"accuracy": 0.989,
"brand": "TESCO",
"businessName": "TESCO",
"currency": "GBP",
"country": "GBR",
"items": [
{
"description": "Tesco Maris Piper Potatoes 2kg",
"quantity": 1,
"totalPrice": 1.8,
"accuracy": 0.995,
"cleanedName": "",
"category": ""
}
],
"logo": "https://logo.clearbit.com/tesco.com",
"merchantAddress": "",
"receiptID": "fb2cdc63-6d13-4176-89ae-7a424b69d7b5",
"subTotal": 6.33,
"transactionDate": "2025-10-08T00:00:00+00:00",
"transactionTime": "11:47:00"
}
}Payload fields:
| Field | Type | Description |
|---|---|---|
eventType | String | Always receipt.enriched |
data.brand | String | Standardized brand name |
data.businessName | String | Full business name |
data.logo | String | URL to merchant logo |
data.accuracy | Number | Overall processing accuracy |
data.items | Array | Same items from extraction stage |
data.receiptID | String | Receipt identifier |
5. receipt.validated
Sent after the extracted receipt data has been validated for authenticity and duplicate detection.
Use case: Confirm that the receipt passes validation checks (not a duplicate, authentic, etc.).
{
"eventType": "receipt.validated",
"data": {
"applicationDetails": {
"id": "34F67CBEA3CD42CCADCB5C7B358ACBA8",
"name": "your_app_name",
"sourceType": 2
},
"userID": "027KO2",
"country": "GBR",
"currency": "GBP",
"receiptID": "fb2cdc63-6d13-4176-89ae-7a424b69d7b5",
"receiptHash": "f548b3632fe57cdda0c259876e4f07f9",
"transactionTimeStamp": "2025-10-08T11:47:00"
}
}Payload fields:
| Field | Type | Description |
|---|---|---|
eventType | String | Always receipt.validated |
data.receiptHash | String | Unique hash for duplicate detection |
data.country | String | Validated country code |
data.currency | String | Validated currency |
data.transactionTimeStamp | String | Confirmed transaction timestamp |
data.receiptID | String | Receipt identifier |
6. receipt.scored
Sent after products have been matched to the sustainability database and scored.
Use case: Display product-level scoring information and matched ingredient details.
{
"eventType": "receipt.scored",
"data": {
"applicationDetails": {
"id": "34F67CBEA3CD42CCADCB5C7B358ACBA8",
"name": "your_app_name",
"sourceType": 2
},
"userID": "027KO2",
"currency": "GBP",
"items": [
{
"id": "14638b56",
"itemTotal": 1.8,
"name": "Tesco Maris Piper Potatoes 2kg",
"pricePerUnit": 1.8,
"quantity": 1,
"partnerType": 0,
"matchedIngredientName": "Potatoes, old, raw, flesh only"
},
{
"id": "9db37ade",
"itemTotal": 2.4,
"name": "Tesco Tenderstem Broccoli Spears 330g",
"pricePerUnit": 2.4,
"quantity": 1,
"partnerType": 0,
"matchedIngredientName": "Broccoli, green, raw"
}
],
"receiptID": "fb2cdc63-6d13-4176-89ae-7a424b69d7b5",
"receiptSource": 1,
"receiptType": "Supplies",
"subTotal": 6.33,
"transactionTimeStamp": "2025-10-08T11:47:00"
}
}Payload fields:
| Field | Type | Description |
|---|---|---|
eventType | String | Always receipt.scored |
data.items | Array | Matched and identified products |
data.items[].id | String | Product match ID |
data.items[].name | String | Product name |
data.items[].matchedIngredientName | String | Matched ingredient from database |
data.items[].partnerType | Integer | Partner status (0=standard) |
data.receiptID | String | Receipt identifier |
7. rewards.awarded
Sent when receipt processing is fully complete and points have been calculated and added to the user's account. This is the most important event as it contains the final points award and full transaction details.
Use case: Update user's points balance, send push notification, display detailed transaction breakdown.
{
"eventType": "rewards.awarded",
"data": {
"applicationDetails": {
"id": "34F67CBEA3CD42CCADCB5C7B358ACBA8",
"name": "your_app_name",
"sourceType": 2
},
"user": {
"id": "027KO2",
"email": "user@example.com",
"firstName": "",
"lastName": "",
"availablePoints": 1656.54,
"lifetimePoints": 1656.54,
"numOfTransactions": 38
},
"transaction": {
"applicationDetails": {
"id": "34F67CBEA3CD42CCADCB5C7B358ACBA8",
"name": "your_app_name",
"sourceType": 2
},
"businessID": "13bfe2ca-759b-46b7-bc0b-76ac0d4784b2",
"brand": "TESCO",
"externalTransactionID": "fb2cdc63-6d13-4176-89ae-7a424b69d7b5",
"items": [
{
"id": "R13bfe2ca__EXT14638b56",
"externalId": "14638b56",
"name": "Tesco Maris Piper Potatoes 2kg",
"pricePerUnit": 1.8,
"partnerType": 0,
"bonusPoints": 0,
"healthPoints": 10.8,
"qty": 1,
"totalAmount": 1.8,
"carbonImpactRating": 1,
"healthImpactRating": 1,
"carbonDataSource": "agribalyse",
"cO2ePerUnit": 0.599046174,
"totalCO2e": 0.599046174,
"totalPlanetPoints": 21.6,
"matchedIngredientName": "Potatoes, old, raw, flesh only",
"cleanedName": "Maris Piper Potatoes"
},
{
"id": "R13bfe2ca__EXT9db37ade",
"externalId": "9db37ade",
"name": "Tesco Tenderstem Broccoli Spears 330g",
"pricePerUnit": 2.4,
"partnerType": 0,
"bonusPoints": 0,
"healthPoints": 14.4,
"qty": 1,
"totalAmount": 2.4,
"carbonImpactRating": 1,
"healthImpactRating": 1,
"carbonDataSource": "agribalyse",
"cO2ePerUnit": 0.678984282,
"totalCO2e": 0.678984282,
"totalPlanetPoints": 28.8,
"matchedIngredientName": "Broccoli, green, raw",
"cleanedName": "Tenderstem Broccoli Spears"
}
],
"partnerType": 0,
"totalAmount": 6.33,
"totalBonusPoints": 0,
"totalCO2e": 2.55,
"totalGreenProducts": 4,
"totalHealthPoints": 37.14,
"totalPoints": 74.28,
"transactionID": "080c2949-b9fc-493d-85b5-906330bb3d7b",
"transactionSource": 5
}
}
}Payload fields:
| Field | Type | Description |
|---|---|---|
eventType | String | Always rewards.awarded |
data.user | Object | Updated user account information |
data.user.id | String | User ID |
data.user.email | String | User email |
data.user.availablePoints | Number | Current available points balance |
data.user.lifetimePoints | Number | Total points earned all-time |
data.user.numOfTransactions | Integer | Total transaction count |
data.transaction | Object | Complete transaction details |
data.transaction.transactionID | String | Generated transaction ID |
data.transaction.externalTransactionID | String | Your original receipt/transaction reference |
data.transaction.brand | String | Merchant brand name |
data.transaction.businessID | String | Merchant business ID |
data.transaction.items | Array | Fully scored product items |
items[].id | String | Unique item ID |
items[].externalId | String | Product match ID |
items[].name | String | Full product name |
items[].cleanedName | String | Simplified product name |
items[].pricePerUnit | Number | Unit price |
items[].qty | Integer | Quantity purchased |
items[].totalAmount | Number | Line item total |
items[].partnerType | Integer | Partner status (0=standard) |
items[].bonusPoints | Number | Bonus points from partnerships |
items[].healthPoints | Number | Nutritional score points |
items[].carbonImpactRating | Integer | Carbon rating (1=best, 5=worst) |
items[].healthImpactRating | Integer | Health rating (1=best, 5=worst) |
items[].carbonDataSource | String | Data source (agribalyse, epd, etc.) |
items[].cO2ePerUnit | Number | CO2 equivalent per unit (kg) |
items[].totalCO2e | Number | Total CO2 for this item |
items[].totalPlanetPoints | Number | Total points for this item |
items[].matchedIngredientName | String | Matched ingredient from database |
data.transaction.totalAmount | Number | Receipt total |
data.transaction.totalPoints | Number | Total PlanetPoints awarded |
data.transaction.totalGreenProducts | Integer | Count of eco-friendly items |
data.transaction.totalHealthPoints | Number | Sum of all health points |
data.transaction.totalBonusPoints | Number | Sum of all bonus points |
data.transaction.totalCO2e | Number | Total carbon footprint (kg CO2e) |
data.transaction.transactionSource | Integer | Source type (5=receipt scan) |
Points calculation: Each item's totalPlanetPoints is calculated from health points, carbon impact, and bonus points. The transaction.totalPoints is the sum awarded to the user's account.
8. receipt.failed
Sent when receipt processing fails at any stage due to validation errors, unsupported formats, or policy violations.
Use case: Inform users why their receipt was rejected and guide them to fix the issue.
{
"eventType": "receipt.failed",
"data": {
"applicationDetails": {
"id": "34F67CBEA3CD42CCADCB5C7B358ACBA8",
"name": "your_app_name",
"sourceType": 2
},
"userID": "07BVG7",
"errorMessage": "Receipt validation failed",
"failureStage": 5,
"failureStageName": "FAILED_VALIDATE",
"receiptID": "491d44e2-a2b7-4107-87db-4d5b566e6d2b",
"receiptSource": 1,
"receiptUrl": "https://storage.example.com/receipts/20251008105428.jpg"
}
}Payload fields:
| Field | Type | Description |
|---|---|---|
eventType | String | Always receipt.failed |
data.userID | String | User ID |
data.receiptID | String | Receipt ID that failed |
data.errorMessage | String | Human-readable error description |
data.failureStage | Integer | Numeric failure stage identifier |
data.failureStageName | String | Stage name where failure occurred |
data.receiptSource | Integer | Source type (1=scan) |
data.receiptUrl | String | URL to the failed receipt image |
Failure stages:
| Stage Code | Stage Name | Description | User Action |
|---|---|---|---|
| 1 | FAILED_UPLOAD | Upload failed | Check image file and retry |
| 2 | FAILED_EXTRACT | OCR extraction failed | Ensure receipt is clear and legible |
| 3 | FAILED_ENRICH | Merchant enrichment failed | Receipt may be from unsupported merchant |
| 4 | FAILED_SCORE | Product scoring failed | No matching products found in database |
| 5 | FAILED_VALIDATE | Validation checks failed | Receipt may be duplicate, too old, or tampered |
Important: Always display the errorMessage to users and check the failureStageName to provide specific guidance on resolution.
Security & Verification
Webhook Signatures
Every webhook request includes a signature header to verify authenticity and prevent tampering.
Header: X-Reewild-Signature
Value: HMAC SHA-256 hash of the request body using your webhook secret
Verifying Signatures
You must verify webhook signatures before processing events to ensure the request genuinely came from Reewild. The signature is computed using HMAC SHA-256 with your webhook secret (provided during onboarding).
Verification process:
- Extract the
X-Reewild-Signatureheader from the incoming request - Compute the expected signature by creating an HMAC SHA-256 hash of the raw request body using your webhook secret
- Compare the received signature with your computed signature using a constant-time comparison function
- Only process the webhook if signatures match
Never skip signature verification! Without it, attackers could send fake webhooks to manipulate user balances or trigger unintended actions.
For webhook payload examples and schemas, refer to the individual API endpoint documentation pages that generate webhook events.
Best Practices
1. Respond Quickly
Your webhook endpoint should respond with 200 OK within 5 seconds. If your processing takes longer:
- Return
200 OKimmediately to acknowledge receipt - Queue the event for asynchronous processing
- Handle the event in a background worker or job queue
This prevents timeouts and ensures Reewild doesn't trigger unnecessary retries.
2. Handle Idempotency
Webhooks may be delivered more than once due to network issues or retries. Always process events idempotently by:
- Tracking processed receipt IDs in your database
- Checking if an event has already been processed before taking action
- Using unique identifiers (
receipt_id) to prevent duplicate processing
3. Log Everything
Maintain comprehensive webhook logs for debugging and audit trails:
- Log all incoming webhook requests with full payload
- Record processing status (success/failure)
- Include timestamps for delivery and processing
- Store receipt IDs and customer identifiers for traceability
This helps with debugging, compliance, and understanding user behavior.
4. Monitor Delivery Health
Track webhook delivery success rates and set up alerts for failures:
- Success rate - Should be greater than 99%
- Average response time - Should be less than 500ms
- Failed deliveries - Alert if more than 5 failures in 1 hour
- Processing errors - Monitor for exceptions in webhook handlers
5. Handle Event Order
Events may arrive out of order due to network conditions or processing delays. Design your system to handle this gracefully:
- Don't assume events arrive in chronological order
- Use timestamps to determine event sequence
- Store event state and check for outdated updates
- Focus on final state (
receipt_completedorreceipt_failed) rather than intermediate stages
Testing Webhooks
Local Development
Use tools like ngrok or localtunnel to expose your local development server to the internet for webhook testing. This allows Reewild to send webhooks to your localhost during development.
Steps:
- Install a tunneling tool (ngrok, localtunnel, or similar)
- Start your local development server
- Create a secure tunnel to your localhost
- Use the tunnel URL as your webhook endpoint in the Reewild dashboard
- Test webhook delivery and monitor incoming events
Webhook Testing Tool
Reewild provides a webhook testing dashboard in your account portal:
- Navigate to Settings → Webhooks
- Click Send Test Event
- Select event type (e.g.,
receipt_completed) - Click Send
- View delivery logs and your server's response
This allows you to test your webhook handler without processing real receipts.
Manual Testing
You can manually send webhook payloads to your endpoint using tools like cURL, Postman, or your preferred HTTP client. Use the JSON examples provided in this documentation as test payloads.
Remember to include the X-Reewild-Signature header when manually testing to verify your signature validation logic works correctly.
Retry Policy
If your webhook endpoint fails to respond with 200 OK, Reewild automatically retries delivery:
| Attempt | Delay | Total Elapsed |
|---|---|---|
| 1st retry | 5 minutes | 5 minutes |
| 2nd retry | 1 hour | 1 hour 5 minutes |
| 3rd retry | 6 hours | 7 hours 5 minutes |
| Final retry | 16 hours | 23 hours 5 minutes |
After the final retry fails, the webhook is marked as permanently failed and you'll receive an alert email.
Manual replay: You can manually replay failed webhooks from the dashboard if needed.
Webhook Endpoint Requirements
Your webhook endpoint must meet these requirements:
✅ HTTPS only - HTTP endpoints are not supported (security requirement)
✅ Valid SSL certificate - Self-signed certificates will be rejected
✅ Responds with 200 OK - Any other status code is treated as failure
✅ Responds within 5 seconds - Longer responses trigger timeout
✅ No redirects - 301/302 redirects are not followed
✅ Public accessibility - Must be reachable from internet (no VPN-only endpoints)
Common Integration Patterns
Pattern 1: Immediate UI Update
Update your user interface as soon as points are awarded:
When to use: Real-time apps, mobile apps with push notifications, dashboards
Flow:
- Receive
receipt_completedwebhook - Update user's points balance in database
- Send push notification to user's device
- Trigger real-time UI update via WebSocket or similar
Benefits: Users see their points immediately without refreshing
Pattern 2: Progress Tracking
Show users real-time processing status as their receipt moves through each stage:
When to use: Apps with receipt processing status screens, progress indicators
Flow:
- Track each webhook event (
receipt_uploaded,receipt_extracted,receipt_validated,receipt_completed) - Store progress state in cache (Redis) or database
- Update UI progress bar or status message in real-time
- Show detailed messages at each stage
Benefits: Better user experience, reduces support inquiries about processing status
Pattern 3: Analytics & Reporting
Track receipt processing metrics for business intelligence:
When to use: Data-driven teams, business analytics, user behavior analysis
What to track:
- Points earned per transaction
- Item counts and merchant patterns
- Green and healthy product purchases
- Processing success/failure rates by error type
- Average processing times
- User engagement metrics
Benefits: Understand user behavior, optimize offerings, measure sustainability impact
Troubleshooting
Webhooks Not Arriving
Check these common issues:
- Incorrect endpoint URL - Verify URL in dashboard settings
- Firewall blocking - Whitelist Reewild IPs:
52.51.12.34,35.178.45.67 - SSL certificate issues - Ensure valid, non-self-signed certificate
- Server downtime - Check your server logs and uptime
- Webhook disabled - Verify webhooks are enabled in dashboard
Signature Verification Failing
Common causes:
- Wrong secret - Using sandbox secret in production (or vice versa)
- Payload modification - Don't parse or modify JSON before verifying the signature
- Encoding issues - Ensure UTF-8 encoding is used consistently
- Timing attacks - Use constant-time comparison functions to prevent timing-based attacks
- Whitespace differences - Verify the raw request body exactly as received
Solution: Always verify the signature against the raw, unmodified request body before any parsing or processing.
Duplicate Events
If receiving duplicate receipt_completed events:
- Implement idempotency using receipt IDs
- Check retry logs in dashboard
- Ensure your endpoint returns
200 OKquickly
Next Steps
Receipt Scanning
Learn how to implement the receipt upload flow
Stats & Balance
Retrieve user points balances and transaction history
API Reference
Explore complete API endpoint documentation
Scoring Methodology
Understand how points are calculated
Need help? Contact our integration support team at info@reewild.com or join our developer Slack channel for real-time assistance.