LedgyX — Quick Start Guide 🚀
Welcome to LedgyX!
This guide will help you launch your first API from SQL in just a few minutes.
🔹 What is LedgyX?
LedgyX lets you generate fully functional REST APIs by writing simple SQL queries.
Think of it as GraphQL-like flexibility, but with full SQL power — including JOINs and complex filters.
Ready to try for free ?
app.ledgyx.com (opens in a new tab)
Our landing.
ledgyx.com (opens in a new tab)
✅ Key Features
- SQL-based API generation
- JSON output structure builder
- Table linking (JOINs)
- REST endpoint configuration
- API key authentication
- Built-in rate limiting
- Analytics dashboard (coming soon)
Creating Tables
You’ll need to create tables for data storage where you can later insert data.
Here’s an example:
- Option A:
Run SQL query in Playground
Create new dictionay
CREATE DICTIONARY IF NOT EXISTS users (
id NUMERIC field not null,
name text(100) field,
PRIMARY KEY (id)
);
- Option B:
Create in schema builder
Click on the New button
select the Directory type and type name
Add fields and specify their type and, if necessary, a description
When finished, save the object and refresh the object tree.
Let's Create Events
Events are a fundamental system in this project, as practically everything we do next will be tied to events in one way or another.
By going to the "Events" tab, we see the event list panel and the event editing panel. In the event editing panel, there is a section with a name and a test identifier (used for calling nested events). Below that, we see panels where we can define SQL queries that will be executed for different types of RESTful requests: GET, POST, PUT, and DELETE.
Creating an Event
We have created a user directory, and now let's create an event to add a new user. In the POST field, we need to insert the following query:
INSERT INTO dictionary.users(ref, id, name)
SELECT uuid(x.id), x.id, x.name as name
FROM ¶ms as x(id int, name text)
ON CONFLICT(ref) DO UPDATE SET name = x.name, id = EXCLUDED.id;
Understanding the Query
In the line INSERT INTO dictionary.users(ref, id, name)
, we are making a standard call to add a new record.
The line SELECT uuid(x.id)
indicates that we need to convert the identifier obtained from JSON into an MD5 hash and convert it to UUID. This is a convenient way to create a unique identifier based on incoming data.
The FROM ¶ms
line indicates that we are selecting data from the incoming user data set provided in JSON format.
The line ON CONFLICT(ref) DO UPDATE
indicates that in case of a duplicate hash key, we update the data. If not specified, the system will neither throw an error for a duplicate row nor update anything.
Saving the Event
Let's save our event, for example, with the name "Users event."
To call our event, we need to create a named endpoint, which we can access externally.
Creating an API Endpoint
Go to the "API" tab. On this tab, we see an empty tree that has only the root tab. Click the "Add" button and give a name for our API group. Let's name it "Common."
After creating the "Common" group, select it in the tree, and now we can create an endpoint to call our event. Let's name it "users" and select the newly created "Users event" from the event list.
Now we have a ready endpoint for adding users. To call our endpoint, we need an access key to our API. It is created automatically during registration, and you can find it by going to the "Settings" tab and selecting "API keys." In the table, there will be a "key" field that we need to copy and paste into the call string.
The call should look like this:
curl -X POST https://app.ledgyx.com/rest/v2/{api key}/common/users -d '[{"id":1,"parent":"main","name":"Julio Radriges","value":"CEO"},{"id":2,"parent":"main","name":"Lia Thomas","value":"bookkeeper"}]'
After making the call, we can go to the Playground to see the result of the addition.
To do this, select the "Users" directory, right-click on it, and select "SELECT" from the context menu. The request window will be populated with the following query:
SELECT usr.name, usr.id
FROM Dictionary.users as usr
LIMIT 100 TYPE LIST;
Click "Execute," and we will see the newly added users in the result window:
[
{
"id": 1,
"name": "Julio Radriges"
},
{
"id": 2,
"name": "Lia Thomas"
}
]
Modifying the Event to Retrieve Users
Now, let's modify our event to retrieve a list of users. Copy our query and paste it in the API editor, selecting our "users" endpoint. Paste the copied query into the GET field and save the endpoint.
Now return to the terminal and execute the command:
curl -X GET https://app.ledgyx.com/rest/v2/{api key}/common/users
The response will contain the list of users.
Updating Users
For updates, we need to fill in the PUT field. As a filter, you can use any identifier or the system identifier "ref." For example:
UPDATE dictionary.users SET name = &name WHERE id = &id;
Deleting Users
For deletion, use the DELETE field. In this example, we use the system variable "ref" that was created when adding user records. Recall the line:
uuid(x.id)
To read it in the table, specify this field when creating the query:
delete from dictionary.users where ref = &ref;
The API is Ready
The API is ready and can be used.
To fill the tables with data, refer to the "hooks" and "subscription" sections.
You can also use SubGraph or any other source to obtain data from networks, saving it in this system. This will allow you to create more sophisticated selections or get and use data in other systems through APIs, combining them into more complex queries.
Creating an Event Handler
Next, in the Playground, you create a query for reading, writing, or updating data.
Then, go to the events list and create a new event handler.
Here’s an example:
SELECT usr.id, usr.name
FROM Dictionary.users as usr
LIMIT 100 TYPE LIST;
Fetching Transaction Logs from Ethereum Data
SELECT trn."timestamp", trn."contractAddress", trn."cumulativeGasUsed",
trn."from", trn."gasUsed", trn.status, trn."to", trn."transactionIndex",
trn.type, trn.address, trn.topics, trn.data, trn.logindex, trn.removed,
trn.selector
FROM Ethereum.transactions.log(WHERE "to" = &address LIMIT 100) as trn
LIMIT 100 TYPE LIST;
Query Parameters:
{"address": "0x6887246668a3b87f54deb3b94ba47a6f63f32985"}
Event Handlers
There are four types of handlers: POST
, GET
, DELETE
, and PUT
. Each handler can store a separate query. Once you've created the event handler, go to the API tree, where you can create a group and procedure. For example, create a "Users" group and a "List" procedure. In the procedure, you'll need to add the event handler from the events list. That's it, your first API branch is ready.
Now, you can get an access key from the settings and connect to your new API.
Here’s an example:
curl -X GET https://app.ledgyx.com/rest/v2/{api key}/pairs/list?pair=0x490ccb3c835597ff31e525262235487f9426312b
curl -X POST https://app.ledgyx.com/rest/v2/{api key}/users/add_user -d '[{"id":1,"parent":"main","name":"Julio Radriges","value":"CEO"},{"id":2,"parent":"main","name":"Lia Thomas","value":"bookkeeper"}]'
You can use various endpoints like SubGraph to consolidate data for further use.
Creating Event Subscriptions
The system offers several types of event subscriptions, including:
- A timer that triggers events every minute
- Data changes in the DB directory
- Blockchain network events, such as new block additions or contract events
Once you decide on the event type, simply link the pre-created event handler, which will be triggered whenever the event occurs.
Creating a Webhook
If you need to send the event to another endpoint, you can create a webhook by specifying your endpoint. The event data will be the result of the query you specified as the event handler.
Web Hosting
Our platform provides web hosting functionality. Data transmission over the internet takes time, especially when handling a large number of requests. To improve data processing speed and website performance, we offer the option to host websites on our platform. During website debugging, a random name is automatically generated, which you can view in the platform's settings.
Structure:
- Templates
- Site Structure
- File Storage
Templates
Templates are usually stored as files and are rendered when needed.
In our platform, the process is similar, but templates are stored in the database.
Don’t worry, template data is accessed just like files.
Here’s an example of a root template:
<!DOCTYPE html>
{{> include/_copyright-header}}
<html lang="en">
<head>
{{> include/_head}}
{{> inline/head-block}}
{{!-- Optional: page related CSS --}}
</head>
</body>
</html>
The templates use the Mustache templating style.
We plan to develop a Markdown-based templating engine soon.
Templates are organized into directory structures, making them easier to manage.
Site Structure
This part is simple. You create the site tree and specify the handler that will be triggered to generate the page. The main point is that you just need to fetch the data from the database and pass it to the rendering procedure. The system handles the rest.
File Storage
For a website to function, you'll need stylesheets, JavaScript files, and media files. You can upload an archive to our platform, which will be automatically extracted and made available for your site. For example, if your assets are stored in a directory named assets
, simply create an archive of that directory and upload it to the server. There's also support for uploading and deleting individual files.
This translation provides the MDX-friendly format and ensures everything is well-organized for an English-speaking audience.