01
Overview
Partner guide for fetching published Ready to Roll plans as JSON from LGSF Design.
https://lgsfdesign.net
https://lgsfdesign.net/api/plans/ready-to-roll/
| Item | Detail |
|---|---|
| Endpoint | GET /api/plans/ready-to-roll/ |
| Auth | API key (required) |
| Format | JSON array |
| Scope | Published Ready to Roll plans only |
| CORS | Allowed for websites listed on your API key |
02
Get an API key
API keys are managed in Django admin under Plans → Plan API keys. Treat your key like a password.
- Click Contact us on this page and share your email (phone optional).
- We create a Plan API key in admin (Plans → Plan API keys).
- You receive access details and can list authorized website origins.
- Call GET /api/plans/ready-to-roll/ with the key on every request.
Authorized websites
Used for browser / JavaScript calls (CORS + origin check). One origin per line on the API key.
| Value | Meaning |
|---|---|
https://partner.com |
Allow that exact origin |
partner.com |
Same as https://partner.com |
(empty) |
Backend / server-to-server only (no browser Origin) |
* |
Allow any website for this key |
https://www.partner.com
https://app.partner.com
https://localhost:3000
03
Authentication
Send the key on every request using one of these headers. Without a valid active key, the API returns 403. If the request includes a browser Origin, that origin must be listed for the same key (unless the key uses *).
Authorization: Bearer YOUR_API_KEY
or
X-API-Key: YOUR_API_KEY
04
Request examples
cURL (Bearer)
bashcurl -sS \
-H "Authorization: Bearer YOUR_API_KEY" \
"https://lgsfdesign.net/api/plans/ready-to-roll/"
cURL (X-API-Key)
bashcurl -sS \
-H "X-API-Key: YOUR_API_KEY" \
"https://lgsfdesign.net/api/plans/ready-to-roll/"
JavaScript (browser)
jsOnly works when the page origin is listed on the API key. Prefer calling from your backend.
const API_URL = "https://lgsfdesign.net/api/plans/ready-to-roll/";
const API_KEY = "YOUR_API_KEY";
const response = await fetch(API_URL, {
method: "GET",
headers: {
Authorization: `Bearer ${API_KEY}`,
Accept: "application/json",
},
});
if (!response.ok) {
throw new Error(`API error ${response.status}`);
}
const plans = await response.json();
Python
pythonimport requests
url = "https://lgsfdesign.net/api/plans/ready-to-roll/"
headers = {"Authorization": "Bearer YOUR_API_KEY"}
response = requests.get(url, headers=headers, timeout=30)
response.raise_for_status()
plans = response.json()
PHP
php<?php
$url = 'https://lgsfdesign.net/api/plans/ready-to-roll/';
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer YOUR_API_KEY',
'Accept: application/json',
],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
throw new RuntimeException("API error {$status}");
}
$plans = json_decode($body, true);
05
Response
Status 200 OK. Body is a JSON array of plan objects. Unpublished plans are never included. Image and detail URLs are absolute.
Example (shortened)
[
{
"id": 12,
"code": "D100110",
"slug": "d100110",
"area": 100,
"bedrooms": 2,
"bathrooms": 1,
"parking": 1,
"floors": 1,
"price_usd": 12000,
"cover_image_url": "https://lgsfdesign.net/media/plans/ready-to-roll/covers/...",
"floor_plan_image_url": "https://lgsfdesign.net/media/plans/ready-to-roll/floor-plans/...",
"description_html": "<p>...</p>",
"gallery": [{ "id": 1, "url": "...", "order": 0 }],
"packages": [{ "label": "Architectural drawings", "price_usd": 500, "order": 0 }],
"steels": [{ "specification": "C89×41×1.0", "order": 0 }],
"is_featured": false,
"is_published": true,
"detail_url": "https://lgsfdesign.net/content/d100110/"
}
]
Field reference
| Field | Type | Description |
|---|---|---|
id |
number |
Internal ID |
code |
string |
Plan code (unique) |
slug |
string |
URL slug |
area |
number |
Area |
bedrooms |
number |
Bedrooms |
bathrooms |
number |
Bathrooms |
parking |
number |
Garage / parking |
floors |
number |
Number of floors |
price_usd |
number | null |
Effective price (from packages when set) |
full_package_usd |
number | null |
Same effective package total |
cover_image_url |
string |
Absolute cover image URL |
floor_plan_image_url |
string |
Absolute floor plan image URL |
description_html |
string |
HTML description |
paragraphs |
array |
Optional paragraph data |
hot_rolled_steel |
string |
Engineering note |
structure_weight_kg |
number | null |
Structure weight |
longest_member_m |
number | null |
Longest member length |
designing_code |
string |
Design code |
snow_load_kn_m2 |
number | null |
Snow load |
wind_velocity_m_s |
number | null |
Wind velocity |
wind_pressure_kn_m2 |
number | null |
Wind pressure |
peak_ground_acc_m_s2 |
number | null |
Peak ground acceleration |
gallery |
array |
{ id, url, order } gallery images |
packages |
array |
{ label, price_usd, order } package lines |
steels |
array |
{ specification, order } steel lines |
is_featured |
boolean |
Featured flag |
is_published |
boolean |
Always true in this feed |
created_at |
string |
ISO datetime |
updated_at |
string |
ISO datetime |
detail_url |
string |
Public plan page URL |
06
Errors
| Status | When |
|---|---|
403 |
Missing key, invalid key, inactive key, or browser origin not authorized |
404 |
Wrong URL |
405 |
Method other than GET / OPTIONS |
{ "detail": "Valid Plan API key required." }
07
CORS (browser)
For cross-origin browser requests, add your site origin under Authorized websites for the key. The browser sends an OPTIONS preflight; LGSF responds with CORS headers when the origin is registered. Allowed headers include Authorization, X-API-Key, and Content-Type. Allowed methods: GET, OPTIONS.
Security tip
Prefer calling the API from your backend, then serving data to your frontend. That keeps the API key off public JavaScript bundles.
08
Support
Need a key, website allowlist change, or integration help? Request access below and we will contact you soon.