-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Add Stadium app integration with actions #21227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| # Overview | ||
|
|
||
| Stadium is a global recognition, gifting, and branded swag platform. Use the Stadium API to embed gift, rewards, and branded swag capabilities into your own applications. | ||
|
|
||
| With Stadium's Pipedream integration, you can: | ||
|
|
||
| - Manage stores and browse product catalogs | ||
| - Place and checkout orders programmatically | ||
| - Send points and rewards to recipients | ||
| - Create and monitor automation orders | ||
| - Track order shipment status | ||
|
|
||
| ## Limitations | ||
|
|
||
| - Stadium's API is available only to customers on Business and Enterprise packages. | ||
| - Access tokens are valid for 24 hours and must be refreshed. | ||
| - Automation orders may take up to 30 minutes to process. | ||
|
|
||
| # Example Use Cases | ||
|
|
||
| 1. **Automated Employee Rewards** — Trigger Stadium point sends when milestones are reached in your HR system. | ||
| 2. **E-commerce Integration** — Automatically place Stadium orders when customers make purchases on your platform. | ||
| 3. **Event-Driven Gifting** — Send branded swag to attendees after event registration via webhook. | ||
| 4. **Order Tracking** — Monitor shipment status and notify recipients when their gifts are on the way. | ||
| 5. **Catalog Sync** — Keep your product catalog in sync with Stadium's latest offerings. | ||
|
|
||
| # Getting Started | ||
|
|
||
| ## Creating a Stadium Account | ||
|
|
||
| 1. Sign up for a free Stadium account at [bystadium.com](https://www.bystadium.com/). | ||
| 2. Create a Stadium Shop and curate your product catalog. | ||
| 3. Set up your funding source (wallet funds for order payments). | ||
| 4. Contact [engineering@bystadium.com](mailto:engineering@bystadium.com) to receive API credentials. | ||
|
|
||
| ## Connecting to Pipedream | ||
|
|
||
| 1. In your Pipedream workflow, search for the **Stadium** app. | ||
| 2. Click **Connect Stadium** and enter your Client ID and Client Secret. | ||
| 3. Pipedream will handle token generation and renewal automatically. | ||
|
|
||
| ## Sandbox Environment | ||
|
|
||
| For testing, Stadium provides a sandbox environment at `https://api.preprod.bystadium.com`. Contact [engineering@bystadium.com](mailto:engineering@bystadium.com) for sandbox credentials. | ||
|
Comment on lines
+42
to
+44
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Sandbox environment setup is incomplete: no guidance on switching the API endpoint. The README mentions a sandbox environment at Either:
🤖 Prompt for AI Agents |
||
|
|
||
| # Troubleshooting | ||
|
|
||
| ## Authentication Errors | ||
|
|
||
| If you receive a `401 Unauthorized` error, verify that: | ||
| - Your Client ID and Client Secret are correct. | ||
| - Your account is on a Business or Enterprise plan. | ||
| - Your access token has not expired (tokens are valid for 24 hours). | ||
|
|
||
| ## Order Errors | ||
|
|
||
| - `422` errors typically indicate invalid request data. Check that store numbers, product IDs, and addresses are correctly formatted. | ||
| - `404` errors mean the specified resource (order, store, automation) was not found. | ||
|
|
||
| ## Automation Orders | ||
|
|
||
| Automation orders may take up to 30 minutes to process. Use the **Check Automation Order Status** action to monitor progress. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import stadium from "../../stadium.app.mjs"; | ||
|
|
||
| export default { | ||
| key: "stadium-check-automation-order-status", | ||
| name: "Check Automation Order Status", | ||
| description: "Check the status of an automation order. [See the documentation](https://api.bystadium.com/api/v2/docs#tag/Automation-management/operation/checkOrderStatus)", | ||
| version: "0.0.1", | ||
| type: "action", | ||
| annotations: { | ||
| destructiveHint: false, | ||
| openWorldHint: true, | ||
| readOnlyHint: true, | ||
| }, | ||
| props: { | ||
| stadium, | ||
| apiKey: { | ||
| type: "string", | ||
| label: "Automation API Key", | ||
| description: "API key of the webhook automation (e.g., `ryfMiGzMp8ZTisWYbZUhjkVL`)", | ||
| secret: true, | ||
| }, | ||
| orderIdentifier: { | ||
| type: "string", | ||
| label: "Order Identifier", | ||
| description: "Identifier of the automation order to check", | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| const response = await this.stadium.checkAutomationOrderStatus({ | ||
| $, | ||
| apiKey: this.apiKey, | ||
| data: { | ||
| order_identifier: this.orderIdentifier, | ||
| }, | ||
| }); | ||
| $.export("$summary", `Successfully retrieved status for automation order ${this.orderIdentifier}`); | ||
| return response; | ||
| }, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| import stadium from "../../stadium.app.mjs"; | ||
|
|
||
| export default { | ||
| key: "stadium-checkout-order", | ||
| name: "Checkout Order", | ||
| description: "Checkout a placed order using the specified payment method. [See the documentation](https://api.bystadium.com/api/v2/docs#tag/Order-management/operation/orderCheckout)", | ||
| version: "0.0.1", | ||
| type: "action", | ||
| annotations: { | ||
| destructiveHint: false, | ||
| openWorldHint: true, | ||
| readOnlyHint: false, | ||
| }, | ||
| props: { | ||
| stadium, | ||
| orderNumber: { | ||
| propDefinition: [ | ||
| stadium, | ||
| "orderNumber", | ||
| ], | ||
| }, | ||
| paymentMethod: { | ||
| type: "string", | ||
| label: "Payment Method", | ||
| description: "Payment method to use for checkout", | ||
| options: [ | ||
| { | ||
| label: "Use Global Points", | ||
| value: "use_global_point", | ||
| }, | ||
| { | ||
| label: "Use Wallet Money", | ||
| value: "use_wallet_money", | ||
| }, | ||
| ], | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| const response = await this.stadium.checkoutOrder({ | ||
| $, | ||
| orderNumber: this.orderNumber, | ||
| paymentMethod: this.paymentMethod, | ||
| }); | ||
| $.export("$summary", `Successfully checked out order ${this.orderNumber}`); | ||
| return response; | ||
| }, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| import stadium from "../../stadium.app.mjs"; | ||
|
|
||
| export default { | ||
| key: "stadium-create-automation-order", | ||
| name: "Create Automation Order", | ||
| description: "Place an order for a webhook automation. May take up to 30 minutes to process. [See the documentation](https://api.bystadium.com/api/v2/docs#tag/Automation-management/operation/createAutomationOrder)", | ||
| version: "0.0.1", | ||
| type: "action", | ||
| annotations: { | ||
| destructiveHint: false, | ||
| openWorldHint: true, | ||
| readOnlyHint: false, | ||
| }, | ||
| props: { | ||
| stadium, | ||
| apiKey: { | ||
| type: "string", | ||
| label: "Automation API Key", | ||
| description: "API key of the webhook automation (e.g., `ryfMiGzMp8ZTisWYbZUhjkVL`)", | ||
| secret: true, | ||
| }, | ||
| contactEmails: { | ||
| type: "string[]", | ||
| label: "Contact Emails", | ||
| description: "Email addresses of recipients", | ||
| }, | ||
| recipientMessage: { | ||
| type: "string", | ||
| label: "Recipient Message", | ||
| description: "Message shown to the recipient at redemption. If not set, the message configured during automation setup will be used", | ||
| optional: true, | ||
| }, | ||
| senderName: { | ||
| type: "string", | ||
| label: "Sender Name", | ||
| description: "Name of the sender. If not provided, the sender name configured during automation setup will be used", | ||
| optional: true, | ||
| }, | ||
| budget: { | ||
| type: "integer", | ||
| label: "Budget", | ||
| description: "Amount of points to be gifted. If not provided, the points budget configured during automation setup will be used", | ||
| optional: true, | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| const data = { | ||
| contact_emails: this.contactEmails, | ||
| }; | ||
| if (this.recipientMessage) data.recipient_message = this.recipientMessage; | ||
| if (this.senderName) data.sender_name = this.senderName; | ||
| if (this.budget) data.budget = this.budget; | ||
|
Comment on lines
+50
to
+52
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win Avoid truthiness-gating optional payload fields. These checks silently omit valid falsy inputs (e.g., Suggested fix async run({ $ }) {
const data = {
contact_emails: this.contactEmails,
+ recipient_message: this.recipientMessage,
+ sender_name: this.senderName,
+ budget: this.budget,
};
- if (this.recipientMessage) data.recipient_message = this.recipientMessage;
- if (this.senderName) data.sender_name = this.senderName;
- if (this.budget) data.budget = this.budget;
const response = await this.stadium.createAutomationOrder({
$,🤖 Prompt for AI AgentsSources: Coding guidelines, Path instructions |
||
|
|
||
| const response = await this.stadium.createAutomationOrder({ | ||
| $, | ||
| apiKey: this.apiKey, | ||
| data, | ||
| }); | ||
| $.export("$summary", `Successfully created automation order — Identifier: ${response.identifier}`); | ||
| return response; | ||
| }, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| import { ConfigurationError } from "@pipedream/platform"; | ||
| import stadium from "../../stadium.app.mjs"; | ||
|
|
||
| export default { | ||
| key: "stadium-create-order", | ||
| name: "Create Order", | ||
| description: "Place a new order against a Stadium Shop. [See the documentation](https://api.bystadium.com/api/v2/docs#tag/Order-management/operation/createOrder)", | ||
| version: "0.0.1", | ||
| type: "action", | ||
| annotations: { | ||
| destructiveHint: false, | ||
| openWorldHint: true, | ||
| readOnlyHint: false, | ||
| }, | ||
| props: { | ||
| stadium, | ||
| storeNumber: { | ||
| propDefinition: [ | ||
| stadium, | ||
| "storeNumber", | ||
| ], | ||
| }, | ||
| countryIso: { | ||
| type: "string", | ||
| label: "Country ISO", | ||
| description: "ISO code of the country (e.g., `US`)", | ||
| }, | ||
| firstName: { | ||
| type: "string", | ||
| label: "First Name", | ||
| description: "Recipient's first name", | ||
| }, | ||
| lastName: { | ||
| type: "string", | ||
| label: "Last Name", | ||
| description: "Recipient's last name", | ||
| }, | ||
| phone: { | ||
| type: "string", | ||
| label: "Phone", | ||
| description: "Recipient's phone number", | ||
| optional: true, | ||
| }, | ||
| street1: { | ||
| type: "string", | ||
| label: "Address Line 1", | ||
| description: "First line of the shipping address", | ||
| }, | ||
| street2: { | ||
| type: "string", | ||
| label: "Address Line 2", | ||
| description: "Second line of the shipping address", | ||
| optional: true, | ||
| }, | ||
| city: { | ||
| type: "string", | ||
| label: "City", | ||
| description: "City", | ||
| }, | ||
| stateName: { | ||
| type: "string", | ||
| label: "State", | ||
| description: "State name", | ||
| }, | ||
| zipCode: { | ||
| type: "string", | ||
| label: "Zip Code", | ||
| description: "Zip code", | ||
| }, | ||
| products: { | ||
| type: "string", | ||
| label: "Products", | ||
| description: "JSON array of products to order. Each product should have `id` (variant ID, e.g., `10/1/9`), `quantity`, and `product_type` (e.g., `Spree::Product`). Example: `[{\"id\":\"10/1/9\",\"quantity\":1,\"product_type\":\"Spree::Product\"}]`", | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| let products; | ||
| if (typeof this.products === "string") { | ||
| try { | ||
| products = JSON.parse(this.products); | ||
| } catch (error) { | ||
| throw new ConfigurationError( | ||
| `Products must be valid JSON array. Each item needs \`id\` (variant ID, e.g., \`10/1/9\`), \`quantity\`, and \`product_type\` (e.g., \`Spree::Product\`). Example: [{"id":"10/1/9","quantity":1,"product_type":"Spree::Product"}]. Parse error: ${error.message}`, | ||
| ); | ||
| } | ||
| } else { | ||
| products = this.products; | ||
| } | ||
|
|
||
| const response = await this.stadium.createOrder({ | ||
| $, | ||
| data: { | ||
| store_number: this.storeNumber, | ||
| country_iso: this.countryIso, | ||
| address: { | ||
| first_name: this.firstName, | ||
| last_name: this.lastName, | ||
| phone: this.phone, | ||
| zip_code: this.zipCode, | ||
| street_1: this.street1, | ||
| street_2: this.street2, | ||
| city: this.city, | ||
| state_name: this.stateName, | ||
| }, | ||
| products, | ||
| }, | ||
| }); | ||
| $.export("$summary", `Successfully created order ${response.number}`); | ||
| return response; | ||
| }, | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import stadium from "../../stadium.app.mjs"; | ||
|
|
||
| export default { | ||
| key: "stadium-get-order-details", | ||
| name: "Get Order Details", | ||
| description: "Get details for a placed order. [See the documentation](https://api.bystadium.com/api/v2/docs#tag/Order-management/operation/orderDetails)", | ||
| version: "0.0.1", | ||
| type: "action", | ||
| annotations: { | ||
| destructiveHint: false, | ||
| openWorldHint: true, | ||
| readOnlyHint: true, | ||
| }, | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| props: { | ||
| stadium, | ||
| orderNumber: { | ||
| propDefinition: [ | ||
| stadium, | ||
| "orderNumber", | ||
| ], | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| const response = await this.stadium.getOrderDetails({ | ||
| $, | ||
| orderNumber: this.orderNumber, | ||
| }); | ||
| $.export("$summary", `Successfully retrieved details for order ${this.orderNumber}`); | ||
| return response; | ||
| }, | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| import stadium from "../../stadium.app.mjs"; | ||
|
|
||
| export default { | ||
| key: "stadium-get-shipment-status", | ||
| name: "Get Shipment Status", | ||
| description: "Get shipment status and tracking details for a placed order. [See the documentation](https://api.bystadium.com/api/v2/docs#tag/Order-management/operation/orderShipmentDetails)", | ||
| version: "0.0.1", | ||
| type: "action", | ||
| annotations: { | ||
| destructiveHint: false, | ||
| openWorldHint: true, | ||
| readOnlyHint: true, | ||
| }, | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| props: { | ||
| stadium, | ||
| orderNumber: { | ||
| propDefinition: [ | ||
| stadium, | ||
| "orderNumber", | ||
| ], | ||
| }, | ||
| }, | ||
| async run({ $ }) { | ||
| const response = await this.stadium.getShipmentStatus({ | ||
| $, | ||
| orderNumber: this.orderNumber, | ||
| }); | ||
| $.export("$summary", `Successfully retrieved shipment status for order ${this.orderNumber}`); | ||
| return response; | ||
| }, | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Clarify what "API credentials" means in the setup instructions.
Line 34 directs users to contact engineering to "receive API credentials," but does not specify that these are the Client ID and Client Secret referenced in line 39. Users may be uncertain whether they have the right credentials when they receive them.
Revise to: "Contact engineering@bystadium.com to receive your Client ID and Client Secret."
🤖 Prompt for AI Agents