Using the API from LSL PRO
Your scripts in Second Life can use the API directly, with llHTTPRequest. Everything here was tested in Second Life.
The pattern
Every script has the same three parts: your key at the top, a request, and an http_response that reads the answer.
string API = "https://api.fastyvendor.com/api/v1";
string KEY = "fsk_…"; // this script must be no-copy and no-modify
key gRequest = NULL_KEY;
default
{
touch_start(integer n)
{
gRequest = llHTTPRequest(API + "/me",
[HTTP_CUSTOM_HEADER, "Authorization", "Bearer " + KEY], "");
}
http_response(key id, integer status, list meta, string body)
{
if (id != gRequest) return;
gRequest = NULL_KEY;
if (status == 200)
llOwnerSay("Connected to " + llJsonGetValue(body, ["store", "name"]));
else
llOwnerSay("Fasty: " + llJsonGetValue(body, ["error", "message"]));
}
}Set the script to no-copy and no-modify
Anyone who can read the script can use your key. Set the script's permissions before you use a real key, and never give a copy of the object to someone else with your key inside.
Reading JSON
llJsonGetValue walks into the answer with a list of field names and positions:
llJsonGetValue(body, ["store", "name"]); // "Luna Couture"
llJsonGetValue(body, ["items", 0, "price"]); // the price of the first item
llJsonGetValue(body, ["error", "message"]); // the error message| What you get | What it means |
|---|---|
JSON_TRUE / JSON_FALSE | The value is true or false. Compare with these, not with the text. |
JSON_NULL | The value is null. |
JSON_INVALID | That field doesn't exist. |
Go through a list with a counter, stopping at JSON_INVALID:
integer i;
string name = llJsonGetValue(body, ["items", 0, "name"]);
while (name != JSON_INVALID)
{
llOwnerSay(name);
name = llJsonGetValue(body, ["items", ++i, "name"]);
}Sending data
Send HTTP_METHOD and HTTP_MIMETYPE, with the body as text. Build it with llList2Json so names with quotes can't break it:
string body = llList2Json(JSON_OBJECT, ["delta", 10, "note", "Won a round"]);
llHTTPRequest(API + "/customers/" + (string)winner + "/points",
[HTTP_METHOD, "POST", HTTP_MIMETYPE, "application/json",
HTTP_CUSTOM_HEADER, "Authorization", "Bearer " + KEY,
HTTP_CUSTOM_HEADER, "Idempotency-Key", "round-" + (string)gRound + "-" + (string)winner],
body);PATCH works too. Use HTTP_METHOD, "PATCH" and send only the fields you want to change.
What is different in LSL
Long answers get cut. LSL keeps only the first 2 KB of an answer. For lists, add HTTP_BODY_MAXLENGTH, 16384, and ask for small pages with limit. A license check only needs limit=1.
Errors arrive in the body. LSL can't read response headers, so read error.message and error.retry_after with llJsonGetValue.
One script, many requests. Answers arrive in any order. Keep the key llHTTPRequest returns and compare it in http_response, as in the pattern above.
Memory. A big answer takes a big piece of your 64 KB. Read what you need, then clear the variable.
Second Life's limit
One object can send about 25 requests every 20 seconds. Past that, llHTTPRequest returns NULL_KEY and the owner sees Too many HTTP requests too fast.
So spread your requests out, and remember the answers. A door that checks a license on every touch should keep the avatars it already checked:
list gAllowed; // avatars already checked in this session
integer known(key who) { return llListFindList(gAllowed, [who]) != -1; }
remember(key who)
{
gAllowed = llList2List(gAllowed + [who], -50, -1); // keeps the last 50
}Complete examples
| Guide | What it builds |
|---|---|
| Unlock something for buyers | An object that opens only for those who bought a product |
| Reward players with points | A game that gives loyalty points to the winner |
| Send prizes to winners | A contest that delivers a product to the winner |
The reference has an LSL example for every route.