Everything you need to integrate Legion Hand Technologies widgets and webhooks into your application.
iFrame Embed
Quick integration with simple iframe embedding
Web Components
Modern custom elements for seamless integration
JavaScript SDK
Full programmatic control with our SDK
Webhooks
Real-time event notifications
Legion Hand Technologies widgets can be integrated into your website using three different methods, each suited for different use cases.
iFrame Method
Simple iframe embedding for quick integration with any website. Best for static sites and CMS platforms.
Web Components
Modern web component approach for better integration with React, Vue, Angular, and other frameworks.
JavaScript API
Full programmatic control with our JavaScript SDK for advanced integrations and dynamic content.
Choose iFrame if you need quick setup with minimal code changes
Choose Web Components for modern apps requiring customization and style control
Choose JavaScript API when you need dynamic widget creation and lifecycle management
The simplest way to embed widgets using iframes. This method provides good isolation and works with any website.
1<!-- Profile Widget -->
2<iframe
3 src="https://your-domain.com/widget/profile"
4 width="100%"
5 height="400"
6 frameborder="0">
7</iframe>
8
9<!-- Campaigns Carousel Widget -->
10<iframe
11 src="https://your-domain.com/widget/campaigns-carousel"
12 width="100%"
13 height="320"
14 frameborder="0">
15</iframe>1<div style="position: relative; width: 100%; height: 0; padding-bottom: 56.25%;">
2 <iframe
3 src="https://your-domain.com/widget/profile"
4 style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
5 frameborder="0">
6 </iframe>
7</div>Web components provide better integration with modern web applications and allow for more customization.
1<!-- For Profile Widget -->
2<script src="https://your-domain.com/js/profile-widget.js"></script>
3
4<!-- For Campaigns Carousel Widget -->
5<script src="https://your-domain.com/js/campaigns-carousel-widget.js"></script>1<!-- Profile Widget -->
2<legion-profile-widget
3 user-id="123"
4 theme="light"
5 show-contact="true">
6</legion-profile-widget>
7
8<!-- Campaigns Carousel Widget -->
9<legion-campaigns-carousel
10 max-campaigns="5"
11 theme="light"
12 height="280"
13 show-expiration="true">
14</legion-campaigns-carousel>Profile Widget
user-idThe user ID to display
theme"light" or "dark"
show-contactShow contact info
widthWidget width
heightWidget height
Campaigns Carousel
max-campaigns1-10, default: 5
theme"light" or "dark"
height200-500px
show-expirationShow dates
api-keyOptional auth key
To open your Community Page when users click a social grid image, add community-url to <legion-social>.
1<script src="https://your-domain.com/js/social-widget.js"></script>
2<legion-social
3 layout="grid"
4 rows="3"
5 cols="3"
6 api-url="https://your-domain.com"
7 community-url="https://your-site.com/community">
8</legion-social>For advanced integration, use our JavaScript API to programmatically control widgets.
1<script src="https://your-domain.com/js/legion-sdk.js"></script>
2<script>
3 const legion = new LegionSDK({
4 apiKey: 'your-api-key',
5 baseUrl: 'https://your-domain.com'
6 });
7</script>1const profileWidget = legion.createWidget('profile', {
2 container: '#profile-container',
3 userId: '123',
4 theme: 'light',
5 onLoad: () => console.log('Widget loaded'),
6 onError: (error) => console.error('Widget error:', error)
7});1// Update widget data
2profileWidget.update({ userId: '456' });
3
4// Refresh widget
5profileWidget.refresh();
6
7// Destroy widget
8profileWidget.destroy();Webhook Types
Receive real-time notifications when events occur in your Legion Hand Technologies integration.
Authentication
Bearer Token
Method
Content Type
application/jsonSuccess Response
When a task verification is submitted, a webhook is sent to notify external systems about the verification details and status.
The webhook endpoint and authentication are configured through environment variables:
VERIFICATION_WEBHOOK_URL: The URL where the verification webhook will be sentVERIFICATION_WEBHOOK_SECRET: The secret token used for webhook authenticationMethod: POST
Headers:
Content-Type: application/json
Authorization: Bearer ${VERIFICATION_WEBHOOK_SECRET}The webhook sends a JSON payload with the following structure:
1const webhookData = {
2 // Verification Information
3 verification_id: string, // MongoDB ObjectId of the verification
4 user_id: string, // MongoDB ObjectId of the user
5 user_email: string | null, // Email of the user who submitted
6 claim_id: string, // MongoDB ObjectId of the claim
7 task_id: string, // MongoDB ObjectId of the task
8 approved: boolean, // Whether verification is approved
9 rejected: boolean, // Whether verification is rejected
10 rejected_reason: string | null, // Reason for rejection if rejected
11 reviewed: boolean, // Whether verification is reviewed
12 started: boolean, // Whether verification is started
13 started_at: DateTime | null, // When verification was started
14 submitted: boolean, // Whether verification is submitted
15 submitted_at: DateTime | null, // When verification was submitted
16 text: string | null, // Text content if any
17 link: string | null, // Link content if any
18 lat: number | null, // Latitude if location provided
19 long: number | null, // Longitude if location provided
20 created_at: DateTime, // Creation timestamp
21 updated_at: DateTime, // Last update timestamp
22
23 // Media Assets
24 assets: Array<{
25 caption: string | null; // Asset caption
26 duration: number; // Duration for video/audio
27 exif: string; // EXIF data for images
28 height: number; // Asset height
29 media_subtypes: string[]; // Media subtypes
30 media_type: string; // Media type
31 uri: string; // Asset URI/URL
32 width: number; // Asset width
33 created_at: DateTime; // Asset creation timestamp
34 updated_at: DateTime; // Asset update timestamp
35 }>,
36
37 // Survey Responses
38 survey_responses: Array<{
39 field_id: string; // Survey field ID
40 response: string; // User's response
41 created_at: DateTime; // Response creation timestamp
42 updated_at: DateTime; // Response update timestamp
43 }>,
44
45 // Associated Claim
46 claim:
47 {
48 id: string, // MongoDB ObjectId of the claim
49 completed: boolean, // Whether claim is completed
50 completed_at: DateTime | null, // When claim was completed
51 submitted: boolean, // Whether claim is submitted
52 submitted_at: DateTime | null, // When claim was submitted
53 opportunity:
54 {
55 // Associated opportunity
56 id: string, // MongoDB ObjectId of the opportunity
57 name: string, // Opportunity name
58 one_line_description: string, // Short description
59 image: string | null, // Opportunity image URL
60 } | null,
61 } | null,
62};A successful webhook call will receive a 2XX response. Any other response code indicates a failure.
The webhook implementation includes error handling:
1try {
2 const webhookResponse = await fetch(process.env.VERIFICATION_WEBHOOK_URL, {
3 method: "POST",
4 headers: {
5 "Content-Type": "application/json",
6 Authorization: `Bearer ${process.env.VERIFICATION_WEBHOOK_SECRET}`,
7 },
8 body: JSON.stringify(webhookData),
9 });
10
11 if (!webhookResponse.ok) {
12 console.error(
13 "Verification webhook call failed:",
14 await webhookResponse.text()
15 );
16 }
17} catch (error) {
18 console.error("Error calling verification webhook:", error);
19}When a claim is completed and all verifications are approved, a webhook is sent to notify external systems about the successful claim completion.
The webhook endpoint and authentication are configured through environment variables:
WEBHOOK_URL: The URL where the webhook will be sentWEBHOOK_SECRET: The secret token used for webhook authenticationMethod: POST
Headers:
Content-Type: application/json
Authorization: Bearer ${WEBHOOK_SECRET}The webhook sends a JSON payload with the following structure:
1const webhookData = {
2 // Claim Information
3 claim_id: string, // MongoDB ObjectId of the claim
4 verifications: TaskVerification[], // Array of task verifications
5 completed: boolean, // Whether the claim is completed
6 completed_at: DateTime | null, // When the claim was completed
7 created_at: DateTime, // When the claim was created
8 purchase_amount: number | null, // Purchase amount if applicable
9 rejected: boolean, // Whether the claim was rejected
10 submitted: boolean, // Whether the claim was submitted
11 submitted_at: DateTime | null, // When the claim was submitted
12 updated_at: DateTime, // Last update timestamp
13 user_id: string, // MongoDB ObjectId of the user
14 user_email: string, // Email of the user who made the claim
15 opportunity_id: string | null, // MongoDB ObjectId of the opportunity
16 opportunity_location_id: string | null, // MongoDB ObjectId of the opportunity location
17
18 // Opportunity Information (null if no opportunity associated)
19 opportunity: {
20 id: string, // MongoDB ObjectId of the opportunity
21 active: boolean | null, // Whether the opportunity is active
22 available_anywhere: boolean | null, // Whether it's available anywhere
23 reward: Reward | null, // Associated reward details
24 tasks: Task[], // Array of tasks
25 boost: boolean | null, // Whether it's boosted
26 budget: number | null, // Budget amount
27 created_at: DateTime, // Creation timestamp
28 currency: string | null, // Currency code
29 detailed_description: string | null, // Detailed description
30 draft: boolean | null, // Whether it's a draft
31 end_date: DateTime, // End date
32 gift: boolean | null, // Whether it's a gift
33 image: string | null, // Image URL
34 instance_limit: number | null, // Instance limit
35 location_dependent: boolean | null, // Whether it's location dependent
36 location_tag_ids: string[], // Array of location tag ObjectIds
37 location_limit: number | null, // Location limit
38 name: string, // Opportunity name
39 one_line_description: string, // Short description
40 perpetual: boolean | null, // Whether it's perpetual
41 start_date: string | null, // Start date
42 targeted: boolean | null, // Whether it's targeted
43 type: OpportunityType | null, // Opportunity type
44 updated_at: DateTime, // Last update timestamp
45 video: string | null, // Video URL
46 completed: boolean, // Whether it's completed
47 view_counter: number[], // View count array
48 click_counter: number[], // Click count array
49 save_counter: number[], // Save count array
50 counter_start_date: DateTime | null, // Counter start date
51 tags: string[] // Array of tag ObjectIds
52 } | null
53}A successful webhook call will receive a 2XX response. Any other response code indicates a failure.
The webhook implementation includes error handling:
1try {
2 const webhookResponse = await fetch(process.env.WEBHOOK_URL, {
3 method: "POST",
4 headers: {
5 "Content-Type": "application/json",
6 Authorization: `Bearer ${process.env.WEBHOOK_SECRET}`,
7 },
8 body: JSON.stringify(webhookData),
9 });
10
11 if (!webhookResponse.ok) {
12 console.error("Webhook call failed:", await webhookResponse.text());
13 }
14} catch (error) {
15 console.error("Error calling webhook:", error);
16}When a reward is generated after a successful claim completion, a webhook is sent to notify external systems about the reward details.
The webhook endpoint and authentication are configured through environment variables:
REWARD_WEBHOOK_URL: The URL where the reward webhook will be sentREWARD_WEBHOOK_SECRET: The secret token used for webhook authenticationMethod: POST
Headers:
Content-Type: application/json
Authorization: Bearer ${REWARD_WEBHOOK_SECRET}The webhook sends a JSON payload with the following structure:
1const webhookData = {
2 // Reward Information
3 reward_id: string, // MongoDB ObjectId of the reward
4 type: RewardType, // Type of reward (Voucher, CouponFixed, etc.)
5 description: string | null, // Reward description
6 restrictions: string | null, // Any restrictions on the reward
7 expiration_days: number, // Number of days until expiration
8
9 // Rank-based Information
10 rank_based: boolean, // Whether reward is rank-based
11 amount_bronze: number | null, // Amount for Bronze rank
12 amount_silver: number | null, // Amount for Silver rank
13 amount_gold: number | null, // Amount for Gold rank
14 amount_platinum: number | null, // Amount for Platinum rank
15
16 // SKU Information
17 sku_bronze: string | null, // SKU for Bronze rank
18 sku_silver: string | null, // SKU for Silver rank
19 sku_gold: string | null, // SKU for Gold rank
20 sku_platinum: string | null, // SKU for Platinum rank
21
22 // Redemption Location Information
23 redemption_tags: Array<{ // Redemption location tags
24 id: string, // Tag ID
25 name: string, // Tag name
26 description: string // Tag description
27 }>,
28 eligible_locations: Array<any>, // Eligible redemption locations
29 has_direct_locations: boolean, // Whether there are direct locations
30 has_tag_based_locations: boolean, // Whether there are tag-based locations
31
32 // Coupon Information (always included)
33 coupon: {
34 id: string, // MongoDB ObjectId of the coupon
35 amount: number | null, // Amount for fixed coupons
36 coupon_type: CouponType | null, // Type of coupon (Fixed, Percentage, Custom)
37 percentage: number | null, // Percentage for percentage coupons
38 expires: Date, // Expiration date
39 description: string | null, // Coupon description
40 restrictions: string | null, // Coupon restrictions
41 image: string | null // Coupon image URL
42 },
43
44 // User Information
45 user: {
46 id: string, // MongoDB ObjectId of the user
47 email: string, // User's email address
48 username: string | null, // User's username
49 rank: Rank // User's rank (Bronze, Silver, etc.)
50 },
51
52 // Claim Information
53 claim: {
54 id: string, // MongoDB ObjectId of the claim
55 completed: boolean, // Whether claim is completed
56 completed_at: Date, // When claim was completed
57 created_at: Date, // When claim was created
58 submitted: boolean, // Whether claim was submitted
59 submitted_at: Date | null, // When claim was submitted
60 verifications: Array<{ // Array of verification statuses
61 id: string, // Verification ID
62 approved: boolean, // Whether verification was approved
63 rejected: boolean, // Whether verification was rejected
64 rejected_reason: string | null, // Reason for rejection if any
65 submitted: boolean, // Whether verification was submitted
66 submitted_at: Date | null, // When verification was submitted
67 purchase_amount: number | null // Purchase amount if applicable
68 }>
69 },
70
71 // Opportunity Information
72 opportunity: {
73 id: string, // MongoDB ObjectId of the opportunity
74 name: string, // Opportunity name
75 one_line_description: string, // Short description
76 detailed_description: string | null, // Detailed description
77 image: string | null // Opportunity image URL
78 }
79}A successful webhook call will receive a 2XX response. Any other response code indicates a failure.
The webhook implementation includes error handling:
1try {
2 const webhookResponse = await fetch(process.env.REWARD_WEBHOOK_URL, {
3 method: "POST",
4 headers: {
5 "Content-Type": "application/json",
6 Authorization: `Bearer ${process.env.REWARD_WEBHOOK_SECRET}`,
7 },
8 body: JSON.stringify(webhookData),
9 });
10
11 if (!webhookResponse.ok) {
12 console.error("Reward webhook call failed:", await webhookResponse.text());
13 }
14} catch (error) {
15 console.error("Error calling reward webhook:", error);
16}When an external coupon is redeemed by a user, a webhook is sent to the configured external system to handle the redemption process.
The webhook endpoint is configured at the shop level via the Shop.webhookUrls array in the database. The system will select the first URL in this list that matches a coupon-specific pattern (e.g., contains "coupon"). The authentication is configured through environment variables:
EXTERNAL_COUPON_WEBHOOK_SECRET: The secret token used for webhook authenticationMethod: POST
Headers:
Content-Type: application/json
Authorization: Bearer ${EXTERNAL_COUPON_WEBHOOK_SECRET}The webhook sends a JSON payload with the following structure:
1const webhookPayload = {
2 // Coupon Information
3 coupon_id: string, // MongoDB ObjectId of the coupon being redeemed
4 user_id: string, // MongoDB ObjectId of the user redeeming the coupon
5
6 // User Information
7 user: {
8 id: string, // MongoDB ObjectId of the user
9 username: string, // User's username
10 email: string, // User's email address
11 },
12
13 // Coupon Details
14 coupon: {
15 id: string, // MongoDB ObjectId of the coupon
16 coupon_type: CouponType, // Type of coupon (Fixed, Percentage, Custom)
17 amount: number | null, // Amount for fixed coupons (in cents)
18 percentage: number | null, // Percentage for percentage coupons
19 description: string | null, // Coupon description
20 expires: Date, // Expiration date
21 restriction: string | null, // Coupon restrictions
22 },
23
24 // Metadata
25 timestamp: string, // ISO timestamp of redemption
26};The external webhook endpoint should return a JSON response with the following structure:
1{
2 success: boolean, // Whether the redemption was successful
3 message?: string, // Optional message to display to the user
4 instructions?: string, // Optional instructions for the user
5 externalId?: string, // Optional external reference ID
6 data?: any // Optional additional data
7}1// Example webhook endpoint implementation
2app.post("/webhook/coupon-redemption", (req, res) => {
3 const { coupon_id, user_id, user, coupon, timestamp } = req.body;
4
5 // Validate the Bearer token
6 const authHeader = req.headers.authorization;
7 if (!authHeader || !authHeader.startsWith("Bearer ")) {
8 return res.status(401).json({ error: "Unauthorized" });
9 }
10
11 const token = authHeader.substring(7);
12 if (token !== process.env.EXTERNAL_COUPON_WEBHOOK_SECRET) {
13 return res.status(401).json({ error: "Invalid token" });
14 }
15
16 try {
17 // Process the coupon redemption in your external system
18 const result = await processExternalCouponRedemption({
19 coupon_id,
20 user_id,
21 user,
22 coupon,
23 timestamp,
24 });
25
26 // Return success response
27 res.json({
28 success: true,
29 message: "Coupon redeemed successfully!",
30 instructions: "Present this confirmation at checkout.",
31 externalId: result.id,
32 });
33 } catch (error) {
34 console.error("Error processing coupon redemption:", error);
35 res.status(500).json({
36 success: false,
37 error: "Failed to process coupon redemption",
38 });
39 }
40});When an external voucher is redeemed by a user, a webhook is sent to the configured external system to handle the redemption process.
The webhook endpoint is configured at the shop level via the Shop.webhookUrls array in the database. The system will select the first URL in this list that matches a voucher-specific pattern (e.g., contains "voucher"). The authentication is configured through environment variables:
EXTERNAL_VOUCHER_WEBHOOK_SECRET: The secret token used for webhook authenticationMethod: POST
Headers:
Content-Type: application/json
Authorization: Bearer ${EXTERNAL_VOUCHER_WEBHOOK_SECRET}The webhook sends a JSON payload with the following structure:
1const webhookPayload = {
2 // Voucher Information
3 voucher_id: string, // MongoDB ObjectId of the voucher being redeemed
4 user_id: string, // MongoDB ObjectId of the user redeeming the voucher
5
6 // User Information
7 user: {
8 id: string, // MongoDB ObjectId of the user
9 username: string, // User's username
10 email: string, // User's email address
11 },
12
13 // Voucher Details
14 voucher: {
15 id: string, // MongoDB ObjectId of the voucher
16 text: string, // Voucher text/title
17 amount: number | null, // Amount for value vouchers (in cents)
18 description: string | null, // Voucher description
19 expires: Date, // Expiration date
20 restriction: string | null, // Voucher restrictions
21 },
22
23 // Metadata
24 timestamp: string, // ISO timestamp of redemption
25};The external webhook endpoint should return a JSON response with the following structure:
1{
2 success: boolean, // Whether the redemption was successful
3 message?: string, // Optional message to display to the user
4 instructions?: string, // Optional instructions for the user
5 externalId?: string, // Optional external reference ID
6 data?: any // Optional additional data
7}1// Example webhook endpoint implementation
2app.post("/webhook/voucher-redemption", (req, res) => {
3 const { voucher_id, user_id, user, voucher, timestamp } = req.body;
4
5 // Validate the Bearer token
6 const authHeader = req.headers.authorization;
7 if (!authHeader || !authHeader.startsWith("Bearer ")) {
8 return res.status(401).json({ error: "Unauthorized" });
9 }
10
11 const token = authHeader.substring(7);
12 if (token !== process.env.EXTERNAL_VOUCHER_WEBHOOK_SECRET) {
13 return res.status(401).json({ error: "Invalid token" });
14 }
15
16 try {
17 // Process the voucher redemption in your external system
18 const result = await processExternalVoucherRedemption({
19 voucher_id,
20 user_id,
21 user,
22 voucher,
23 timestamp,
24 });
25
26 // Return success response
27 res.json({
28 success: true,
29 message: "Voucher redeemed successfully!",
30 instructions: "Present this confirmation at the store.",
31 externalId: result.id,
32 });
33 } catch (error) {
34 console.error("Error processing voucher redemption:", error);
35 res.status(500).json({
36 success: false,
37 error: "Failed to process voucher redemption",
38 });
39 }
40});Contact Legion Hand Technologies support for assistance with widget integration or webhook configuration.