← Lab Notes
July 2, 2026 homelabgootenapi-integration

Building a Customer Order Tracker on the Gooten API (Without Leaking the Key)

Created an internal endpoint to securely check order statuses from our homelab, ensuring sensitive customer information stays safe.


Overview

I recently built a custom order tracking page for breadtoasting.com's merchandise. We use Gooten for print-on-demand services, but their API requires an RecipeID in the URL, which poses a security risk if exposed to frontend JavaScript. To mitigate this, I added a new endpoint to our existing amp-proxy container that handles these requests securely.

Background

Gooten's API uses an RecipeID for authentication, making it easy for anyone with access to the key to place orders and have them billed to my account. This is clearly not ideal, so we needed to find a way to keep this sensitive information away from the frontend while still allowing us to track order statuses.

How It Works

I added a new endpoint to our amp-proxy container using FastAPI in Python. The container already proxies requests for Zammad (our ticketing system) and VCloud Director (for capacity stats). Here's how it works:

  1. Validation: The endpoint validates the id parameter against a regular expression (^[A-Za-z0-9-]{4,64}$) to ensure only valid order IDs are processed.
  2. Rate Limiting: A rate limit of 12 lookups per IP per hour is implemented using a sliding window mechanism to prevent enumeration attacks.
  3. API Call: The endpoint makes an API call to Gooten with the validated RecipeID and id.
  4. Response Filtering: The raw response from Gooten includes sensitive customer information such as shipping address, email, phone number, and billing info. We filter this down to only product name, quantity, status, tracking number, tracking URL, and carrier.
  5. Caching: Results are cached for 30 seconds per order ID to reduce the load on Gooten's API.

Results

The frontend uses a static HTML page (order-status.html) that matches our site design. Users can enter an order ID or share a URL with ?id=12345. The page displays a progress bar for each item, showing "Received," "In Production," and "Shipped" statuses along with tracking links.

Testing Gotchas

  • Non-existent Orders: Gooten returns HTTP 200 with an empty {} body when an order does not exist. You must check if the Id field is missing in the response, rather than relying on a 404 status.
  • Invalid RecipeID: Gooten returns a 403 error ({"Message":"Invalid recipeId."}) for invalid RecipeIDs, which helps distinguish between unauthorized access and non-existent orders.
  • Order Listing: There is no endpoint to list all orders. GET /orders/ without an ID returns "method not supported," so you can only look up IDs that are already known, making end-to-end testing a bit awkward until real orders exist.

Lessons Learned

  1. Security First: Keeping sensitive information out of the frontend is crucial for security.
  2. Rate Limiting: Implementing rate limiting helps prevent enumeration attacks and ensures fair usage.
  3. API Response Handling: Carefully handling API responses to extract only necessary data can significantly reduce the risk of exposing sensitive customer information.

Deployment

To deploy this, I rebuilt the amp-proxy and homepage containers, recompiled Tailwind CSS (using a standalone CLI with no Node.js dependencies). Testing confirmed that the page returns 200 OK, /track redirects work correctly, and fake IDs return "not found" responses. The rate limit also kicked in as expected.

Conclusion

By adding this custom endpoint to our homelab setup, we've created a secure way to track order statuses without exposing sensitive customer information. This solution ensures that only authorized users can access the data they need, maintaining both security and functionality.

Was this useful?