How to Use the Mockupanda GET /templates Endpoint to Build a Dynamic Template Picker Inside Your Own App

If you are building a print-on-demand platform, an Etsy automation tool, or any workflow that wraps mockup generation, there is a moment where your users need to choose a template. You could send them to a separate browser tab, make them copy an ID, and paste it back. Or you could surface the entire Mockupanda template library inside your own interface, filtered and sorted exactly the way your users need it.
That second path is what the GET /templates endpoint is for. It hands you the full library plus any custom templates tied to your API key, with a rich set of filters, metadata fields, and pagination controls. This guide covers everything from the basic request shape to the more advanced patterns for ratio matching and category-driven navigation.
Making Your First Request
Authentication and the base URL
Every request to the Mockupanda API uses Bearer token authentication. You include your API key in the Authorization header. The base URL for every endpoint is https://www.mockupanda.com/api/v1, so your templates endpoint lives at https://www.mockupanda.com/api/v1/templates.
Create your API key in the Dashboard under API Keys, then store it as an environment variable so it never ends up in your source code. The simplest possible request looks like this in cURL:
curl -X GET "https://www.mockupanda.com/api/v1/templates" \
-H "Authorization: Bearer YOUR_API_KEY"That returns every template your key has access to: the full built-in library plus any custom templates uploaded to the account that owns the key. With no filters applied, the response defaults to 50 items per page.
Reading the pagination object
Every response includes a pagination object with four fields: page, limit, total, and total_pages. Use these to build numbered pagination or infinite scroll in your picker UI.
The limit parameter accepts values up to 1000, so if you want to load the entire library in one shot for a client-side filter experience, you can request ?limit=1000. For most apps though, paginating at 50 or 100 and loading more on demand keeps the response fast and the UI snappy.
The response also carries a categories array listing all available category names. This is what you use to populate a category filter dropdown on the fly, since the list reflects what is actually available rather than a hardcoded enum you have to maintain.
Takeaway: Start with a plain request, read pagination.total to understand the library size, and decide whether you want client-side filtering with a large limit or server-side filtering with smaller pages. Build your category dropdown from the categories array in the response rather than hardcoding values.
Filtering Templates by Type, Category, and Source
Separating print templates from product templates
The type parameter lets you split the library into two fundamentally different groups. Pass type=print to get wall art and poster templates. Pass type=product to get apparel, mugs, tote bags, and other three-dimensional product templates. Omit it entirely to get both.
In your picker UI this distinction matters a lot. A seller uploading a square logo needs a t-shirt template. A seller uploading a portrait artwork needs a poster template. If you know what kind of product your user is making, pre-filter by type so they only see relevant options. The is_product_template boolean on each template object confirms which group a given template belongs to.
For product templates, also check supports_product_color. When that is true, the template accepts a product_color parameter at generation time, which means you can let users pick a garment color in your UI before they generate. When it is false, skip that UI element.
Filtering by category and source
The category parameter narrows results to a single category string, for example "Wall Art" or "Devices". Pair this with the categories array from any initial response to build a live filter sidebar: fetch the full list once, extract categories, render them as clickable filters, then re-fetch with ?category=Wall+Art when the user clicks.
The source parameter separates the built-in library from your own uploaded templates. Pass source=library for Mockupanda's ready-made scenes. Pass source=custom for templates tied to your account. Omit it to get both together. The is_user_template boolean on each object tells you the same thing at the item level, which is useful for rendering a "custom" badge in your picker grid.
If your account relies on custom templates created in the editor, you will want to surface them prominently. Fetching with source=custom gives you exactly that subset.
Takeaway: Use type to match your users' product intent, category for navigation, and source to separate platform-specific custom templates from the shared library. Build your filter UI from the data the API returns rather than from a static list.
Matching Templates to Artwork Shape
Why aspect ratio matters more than you think
Every print template expects a specific artwork aspect ratio. If the artwork does not match, it gets cropped or stretched to fill the frame, and the mockup looks wrong. The worst place to discover this mismatch is after you have already generated and delivered the image.
The ratio parameter solves this up front. You can pass a ratio in almost any format: "2:3", "4:5", "square", "portrait", "landscape", "A4", a print size like "8x10", or a decimal like 0.667. You can also comma-separate multiple values to accept several shapes at once.
So if your user has uploaded a 2:3 portrait piece and you want to show them every poster template that fits, you send ?ratio=2:3 and the response comes back pre-filtered. The ratio_tolerance parameter, which defaults to 3 percent, controls how strict the match is. Raise it toward 25 to include templates that will crop the artwork only slightly, which is often acceptable for lifestyle scenes.
Using artwork dimensions for automatic matching
An even more powerful approach is letting the API do the shape detection for you. Pass artwork_url with the public URL of the artwork your user just uploaded, and the API reads the image header, measures the shape, and returns only the templates that fit it. The docs note that only the image header is downloaded, so a large file costs no more than a small one.
If you already know the artwork's pixel dimensions from your upload flow, skip the download entirely with artwork_width and artwork_height. For example:
curl -X GET "https://www.mockupanda.com/api/v1/templates?artwork_width=4000&artwork_height=6000&type=print" \
-H "Authorization: Bearer YOUR_API_KEY"This pattern is the reliable way to bulk-render a catalog: for each artwork, list the templates that fit it, then pass those IDs to POST /api/v1/mockups/generate. No manual ratio checking, no mismatched crops.
The response in this mode also returns ratio_filter and artwork objects that echo back what you sent and what the API measured. Use those to show your users a confirmation like "Showing templates for 2:3 portrait artwork" directly in your picker UI.
The response also includes a ratios array listing every shape present in the print library for the current query, with name, orientation, label, aspect_ratio, and count. This is what you use to build a ratio picker UI. If a user's artwork does not match any template exactly, the ratios array tells them what shapes are available so they can choose the closest fit.
Takeaway: Pass artwork_width and artwork_height as soon as a user uploads artwork. Let the API filter templates automatically, and use the ratios array to build a shape picker that only shows real options.
Understanding the Template Object Fields
Fields for display and navigation
Each template object in the response carries everything you need to render a grid card in your picker UI. The id is what you will pass to POST /mockups/generate, so store it. The name is the human-readable display label. The category matches the values in the top-level categories array.
The thumbnail_url gives you a hosted image to show in the grid. Use it directly in an <img> tag. When thumbnail_url is null, render a placeholder. The aspect_ratio decimal and aspect_ratio_name string together let you display the ratio in the same vocabulary the editor uses, things like "2:3", "Square", or "A4", so the label feels familiar to sellers who have used the Mockupanda web app directly.
The orientation field ("portrait", "landscape", or "square") is useful for layout decisions in your grid, for example giving landscape templates a wider card.
Fields for generation logic
Several fields tell you how to generate correctly with a given template. The frame_count integer tells you how many artwork frames the template has. If it is greater than 1, the template is a diptych or triptych and you need to pass multiple artworks via artwork_urls rather than a single artwork_url. You can read more about handling multi-frame templates programmatically to see exactly how that mapping works.
The render_mode tells you whether the template uses "corners" perspective warp or "uvmap" for UV-mapped product surfaces. The blending_mode and surface_type fields give you additional hints about how the artwork is composited onto the surface, which can help you set user expectations (fabric surfaces behave differently from flat paper).
The is_product_template and supports_product_color booleans drive conditional UI: show a color picker only when supports_product_color is true, and change your artwork input label to something like "Upload your design" vs "Upload your artwork" based on is_product_template.
Takeaway: Use thumbnail_url, name, aspect_ratio_name, and orientation to render the picker grid. Use frame_count, render_mode, is_product_template, and supports_product_color to drive the generation form that follows template selection.
Adding Search to Your Picker
Hybrid search with the q parameter
Once your template library grows past a handful of options, users need to search. The q parameter runs a hybrid search across both the built-in library and your custom templates. It matches meaning as well as words, so a query like "beige bedroom" or "shop front" finds relevant scenes even when those exact words are not in the template name.
When you pass q, the response sets relevance_ranked: true. This flag tells your client not to re-sort the results by date or name, since they are already ordered by relevance. Use it as a signal to skip any client-side sort logic you would otherwise apply.
For a good search experience, debounce the user's input by 300 to 500 milliseconds before firing the request, then show a loading state while the response is in flight. The total from the pagination object lets you display "Showing 14 results for beige bedroom" directly in the UI.
Avoid the legacy search parameter for new integrations. It only does substring matching on name and category, which means "warm living room" would find nothing unless a template is literally named that. The q parameter is the right choice for any picker you are building today. If you want to go deeper on what the search can do, the patterns for using semantic search to find templates are worth reading alongside this guide.
Combining search with other filters
All parameters compose together. You can pass q=bedroom&ratio=2:3&type=print to find portrait bedroom poster templates in one request. This is the right approach for a faceted search UI where users refine their results incrementally.
Keep in mind the rate limits: each API key allows 100 requests per minute and 10,000 per day. For a live search field that fires on every keystroke, debouncing is not optional, it is necessary to stay within those limits, especially if multiple users are sharing one key. If you are running a platform with many concurrent users, the API supports creating multiple keys with no limit on the number of active keys per account, so you can assign per-service or per-client keys to distribute load.
When you hit the rate limit, the API returns a 429 Too Many Requests error with a retry_after field in seconds. Build retry logic that reads this field and waits the indicated time before the next attempt.
Takeaway: Wire the q parameter to a debounced search input, check relevance_ranked before sorting, and compose search with type and ratio filters for a faceted UI. Plan your key strategy around your expected request volume before you launch.
From Template Selection to Mockup Generation
Connecting the picker to the generate endpoint
The picker is not the final destination. Its job is to produce a list of template IDs that go straight into POST /api/v1/mockups/generate. Once a user selects one or more templates in your interface, you pass those IDs as template_ids in the generate request. The batch mode supports up to 12 template IDs per request, so if your user selects a handful of templates to preview, you can render all of them in a single call. That approach is covered in detail in the guide on batch mode for generating multiple mockup variations.
If your users tend to work with the same curated groups of templates repeatedly, consider exposing Sets in your UI as well. A Set is a named, ordered group of templates that can be rendered via a single set_id. Letting users pick from their saved Sets, listed via GET /sets, is a natural extension of the individual template picker you are building now.
Keeping the picker in sync
The template library changes over time. New templates get added, categories get reorganized, and your own users may upload or modify custom templates. Do not cache the full library indefinitely. A reasonable strategy is to cache for a short window, say 15 to 30 minutes, then re-fetch. For custom templates specifically, invalidate the cache any time a user modifies a template in your app.
The source field on each template object ("library" or "custom") lets you handle them differently in your cache logic. Library templates change infrequently and can be cached longer. Custom templates tied to a user's account should be treated as live data.
For the initial load of your picker, fetch with source=library&limit=50 to populate the grid quickly, then lazy-load additional pages as the user scrolls or navigates. Fetch custom templates separately with source=custom and merge them at the top of the list, since those are the templates your users are most likely to reach for first.
Takeaway: Store the id from each selected template and pass it directly to POST /mockups/generate. Cache library templates with a short TTL and treat custom templates as live. Build toward Sets when your users need to work with recurring template groups.
The GET /templates endpoint is straightforward on the surface, but it is designed to support a genuinely sophisticated picker. Between the aspect ratio matching, hybrid search, type and category filters, and the rich metadata on each template object, you have everything you need to build a UI that feels native to your app rather than bolted on. Start with a basic paginated grid, add ratio filtering as soon as users start uploading artwork, and layer in search once the library feels too large to browse. If you have not set up your API key yet, head to mockupanda.com and get started from the dashboard.
Keep reading

How to Upload a Custom PSD Smart Object Template and Expose It as an API-Renderable Resource in Your POD Workflow

How to Manage Multiple Mockupanda API Keys Across Dev, Staging, and Production Environments Without Leaking Credentials
