A booster panel is a small web application built in AYETO Booster Studio. A panel can have its own database, and the endpoints on this page let your server read and change that database with an API key: import data into a panel, sync it with another system, or process what the panel's users entered.
All endpoints are under /api/v3/booster/database/private/. Panels themselves reach
their database through a separate access path that is not covered here.
Concepts
Panels and their database
Each panel has at most one database. It exists when the panel's Database access
setting (panel details in the app) is Public database or Private database;
with No database every endpoint on this page answers 403. Both public and
private mode can be used through this API. The database is created on first use and
is deleted together with the panel.
Every request names the panel in the panel-id header. The panel's ID is shown, with
a copy button, at the top of the panel details in the app.
Collections and records
A database holds collections, and a collection holds records. Collections do
not need to be created: a collection exists as soon as it has a record. Collection
names may contain only letters, digits and underscores (orders, contact_requests).
A record has exactly two fields:
| Field | Type | Description |
|---|---|---|
key |
UUID | Identifier of the record, unique across the databases of all panels (not only within its collection). |
value |
any | The data you stored. Any JSON value is accepted; use an object if you want to filter or sort on its fields. |
Records carry no other metadata: responses do not include the collection name,
timestamps or the author. If you need any of these, store them in value.
Endpoints that work with one record (get, update, delete and their batch
variants) address it by key alone; the collection is taken from the stored record.
Endpoints that work with a whole collection (create, find, count, locks) take
the collection name in the body.
{
"key": "8f14e45f-ceea-467a-9b1c-4e1f2a6b3c70",
"value": {
"customer": {"name": "Jana Nováková", "email": "jana@example.com"},
"status": "open",
"priority": 3,
"created_at": "2026-10-01T09:15:00Z"
}
}
Who can access a panel's data
Requests act as the user who owns the API key. That user must:
- own the panel (be its creator, or a member of the group that owns it, for example the administrators of an organization that received the panel from a partner), or
- have the panel shared with them, directly or through a group they belong to.
Owners and users the panel is shared with (read or write sharing) can read and write the database, in both database modes: writing to the database counts as using the panel, not editing it (changing the panel itself still needs write sharing). Membership in the panel's organization does not by itself give access, and neither do AYETO administrator accounts. The API key must also carry the matching scope:
| Scope | Endpoints |
|---|---|
ayeto.booster.database |
get, find, count |
ayeto.booster.database.write |
create, create-many, update, update-many, delete, delete-many, lock/acquire, lock/release |
The write scope does not include the read scope; a key that reads and writes needs both.
Writes made through this API are writes to the panel's database like any other: they start workflows with a booster record trigger on the panel and run the panel's webhook and e-mail notification modules.
Collection rules
A panel can define collection rules that decide what the panel's anonymous visitors may do. Rules apply only in public database mode; a panel in private mode ignores them, and every endpoint on this page works on all its collections.
For a panel in public mode, only one part of the rules matters for requests on this page:
- An operation set to none for a collection (or for the
*rule that covers it) is disabled for everyone, including this API. The request fails with403. - Every other level (public, secret, private) allows API requests.
- A collection with no matching rule is fully accessible to the API.
The write constraints of a rule (validation schema, maximum value size, maximum number of records) are not applied to writes made through this API. Validate the data on your side before you write it.
Limits
| Limit | Value |
|---|---|
Records returned by one find |
up to 1000 when paging (limit_to is at most 1000, limit_from lower than 1000); all matching records when no limits are sent |
| Filter conditions in one query | 1000, including conditions inside AND / OR |
Nesting of AND / OR |
100 levels |
Values in one in condition |
100 |
| String filter value | 1000 characters |
| Lock time to live | more than 0.1 s, default 3600 s |
The batch endpoints have no fixed maximum number of items, but each item is written separately (see Create many records); keep batches to a few hundred items so that a request finishes well within your HTTP timeout.
Querying records
find and count take an optional params object. Its fields follow the general
query conventions, with the differences listed here.
| Field | Type | Required | Description |
|---|---|---|---|
filters |
array | no | Conditions, all of which must match. See Filters and below. |
sort_key |
string | no | Field to sort by: key or value.<field>. |
sort_order |
integer | no | 0 ascending (default when sort_key is set), 1 descending. |
limit_from |
integer | no | Index of the first record to return, from 0, lower than 1000. |
limit_to |
integer | no | Index after the last record to return (not a count), at most 1000. When only limit_from is sent, it is limit_from + 100 (at most 1000). |
Fields you can filter and sort on
Only two kinds of field names are accepted:
key, the record key (compare it with a UUID string).value.<path>, a field inside the record value, with dots for nested objects:value.status,value.customer.email.
Any other name fails with 422. Records whose value lacks the field (or is not an
object) simply do not match.
A condition is [field, operator, value] with the operators ==, !=, <, >,
<=, >=, regex (always case-insensitive) and in (the value is a list, any of
which may match). Conditions can be combined with {"AND": [...]} and
{"OR": [...]}; each of these needs at least two conditions and can be nested.
{
"collection": "tickets",
"params": {
"filters": [
["value.status", "in", ["open", "waiting"]],
{"OR": [
["value.priority", ">=", 3],
["value.customer.email", "regex", "@example\\.com$"]
]}
],
"sort_key": "value.created_at",
"sort_order": 1,
"limit_from": 0,
"limit_to": 50
}
}
Things to keep in mind when filtering on values:
- Types must match.
["value.priority", ">=", 3]does not match a stored"priority": "3". Store numbers as numbers and dates as ISO 8601 strings or as numbers, so that<and>compare them correctly. - UUID-like strings stay strings in
value.*conditions, so a UUID you stored as text is found as text. - The characters
<,>,"and'in a string filter value are escaped before the comparison, so a condition on text that contains them does not match. A string filter value must also not start with$.
Sorting and paging
Without sort_key, records come newest first. With sort_key, they are sorted by
that field.
limit_from and limit_to are positions in the result, so the second page of 50
is "limit_from": 50, "limit_to": 100. Because limit_to cannot exceed 1000,
paging with limits reaches only the first 1000 matching records. To go further,
page by value: sort on a field and filter on the last value you received, for
example ["value.created_at", "<", "2026-09-30T12:00:00Z"] with
"sort_key": "value.created_at", "sort_order": 1.
If you send neither limit_from nor limit_to, find returns all matching
records. Use that only for collections you know are small.
count applies the filters and ignores sorting and paging: it returns the total
number of matching records.
Common request headers and errors
Every endpoint on this page needs these headers:
| Header | Description |
|---|---|
uni-api-key |
Your API key. See Authentication. |
panel-id |
ID of the panel whose database you access. |
Content-Type |
application/json |
Errors are JSON of the form {"detail": "..."} (see Errors).
These can come from every endpoint:
| Status | detail |
Cause |
|---|---|---|
401 |
API key not provided / API key is invalid |
The key is empty, unknown, disabled or lacks the endpoint's scope. |
403 |
permission denied |
You neither own the panel nor have it shared with you. |
403 |
database access is not allowed for this panel |
The panel's database access is set to No database. |
403 |
operation '<operation>' is disabled for collection '<collection>' |
A collection rule of a panel in public mode sets this operation to none. The operation is create, read, update, delete, count or lock. |
404 |
panel not found |
No panel with this ID, or the panel is disabled. |
422 |
validation error | The panel-id header is missing or not a UUID, or the body does not match the request model. |
422 |
Collection name can only contain alphanumeric characters and underscores |
Invalid collection name (Collection cannot be empty for an empty one). |
429 |
rate limit message | Too many requests; wait for the time in the Retry-After header. See Rate limits. |
500 |
server error | Unexpected failure; retry later. |
Find records
Returns the records of a collection that match the query.
| Endpoint | POST /api/v3/booster/database/private/find |
| Scope | ayeto.booster.database |
| Rate limit | default |
Request
| Field | Type | Required | Description |
|---|---|---|---|
collection |
string | yes | Collection name. |
params |
object | no | Filters, sorting and paging; see Querying records. Without it, all records of the collection are returned, newest first. |
Response
An array of records (key, value). An unknown or empty
collection returns [].
Errors
| Status | detail |
Cause |
|---|---|---|
422 |
Field '<field>' is not allowed for filtering or sorting |
A filter or sort_key names something other than key or value.<path>. |
422 |
Each filter condition must be a list of [field, operator, value] |
Malformed condition. |
422 |
Operator '<operator>' is not allowed |
Unknown operator. |
422 |
'<AND/OR>' operator requires a list of at least 2 conditions |
The value of AND / OR is not a list of at least two conditions. |
422 |
Logical filter must have exactly one key ('AND' or 'OR') |
Malformed logical condition, e.g. {} or an object with several keys. |
422 |
limit_from must be lower than 1000 |
limit_from of 1000 or more (paging reaches only the first 1000 records). |
422 |
Maximum number of filter conditions is 1000 (including conditions inside AND/OR) |
Too many conditions. |
422 |
sort_order must be 0 (ASC) or 1 (DESC) |
Invalid sort_order. |
422 |
limit_to cannot exceed 1000 |
limit_to above 1000. |
422 |
limit_from cannot be greater than limit_to |
Inverted range. |
Examples
curl -X POST "https://ayeto.ai/api/v3/booster/database/private/find" \
-H "uni-api-key: $AYETO_API_KEY" \
-H "panel-id: 3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90" \
-H "Content-Type: application/json" \
-d '{
"collection": "tickets",
"params": {
"filters": [["value.status", "==", "open"]],
"sort_key": "value.priority",
"sort_order": 1,
"limit_from": 0,
"limit_to": 20
}
}'
[
{
"key": "8f14e45f-ceea-467a-9b1c-4e1f2a6b3c70",
"value": {
"customer": {"name": "Jana Nováková", "email": "jana@example.com"},
"status": "open",
"priority": 3,
"created_at": "2026-10-01T09:15:00Z"
}
},
{
"key": "c9f0f895-fb98-4b91-8f2a-6d3e5c1b0a47",
"value": {
"customer": {"name": "Petr Svoboda", "email": "petr@example.org"},
"status": "open",
"priority": 1,
"created_at": "2026-10-01T11:40:00Z"
}
}
]
Count records
Returns the number of records of a collection that match the filters.
| Endpoint | POST /api/v3/booster/database/private/count |
| Scope | ayeto.booster.database |
| Rate limit | default |
Request
| Field | Type | Required | Description |
|---|---|---|---|
collection |
string | yes | Collection name. |
params |
object | no | Same object as for Find records. Only filters affect the result; sorting and paging are validated but ignored. |
Response
An integer.
Errors
The query errors of Find records.
Examples
curl -X POST "https://ayeto.ai/api/v3/booster/database/private/count" \
-H "uni-api-key: $AYETO_API_KEY" \
-H "panel-id: 3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90" \
-H "Content-Type: application/json" \
-d '{"collection": "tickets", "params": {"filters": [["value.status", "==", "open"]]}}'
42
Get a record
Returns one record by its key.
| Endpoint | POST /api/v3/booster/database/private/get |
| Scope | ayeto.booster.database |
| Rate limit | default |
Request
| Field | Type | Required | Description |
|---|---|---|---|
key |
UUID | yes | Key of the record. |
Response
The record.
Errors
| Status | detail |
Cause |
|---|---|---|
404 |
Database record not found |
This panel's database has no record with the key. |
Examples
curl -X POST "https://ayeto.ai/api/v3/booster/database/private/get" \
-H "uni-api-key: $AYETO_API_KEY" \
-H "panel-id: 3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90" \
-H "Content-Type: application/json" \
-d '{"key": "8f14e45f-ceea-467a-9b1c-4e1f2a6b3c70"}'
{
"key": "8f14e45f-ceea-467a-9b1c-4e1f2a6b3c70",
"value": {
"customer": {"name": "Jana Nováková", "email": "jana@example.com"},
"status": "open",
"priority": 3,
"created_at": "2026-10-01T09:15:00Z"
}
}
Create a record
Adds a record to a collection.
| Endpoint | POST /api/v3/booster/database/private/create |
| Scope | ayeto.booster.database.write |
| Rate limit | default |
Request
| Field | Type | Required | Description |
|---|---|---|---|
collection |
string | yes | Collection name (letters, digits, underscores). The collection is created with its first record. |
value |
any | no | The data to store. Omitted means null. |
key |
UUID | no | Key of the new record. Generated when omitted; it must not be used by any existing record of any panel (otherwise 422). |
Response
The created record, including its key.
Errors
| Status | detail |
Cause |
|---|---|---|
422 |
a record with key '<key>' already exists |
The key you sent is used by an existing record (of this or another panel). |
500 |
error creating database record |
The record could not be stored (rarely, two requests created the same key at the same moment). |
Examples
curl -X POST "https://ayeto.ai/api/v3/booster/database/private/create" \
-H "uni-api-key: $AYETO_API_KEY" \
-H "panel-id: 3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90" \
-H "Content-Type: application/json" \
-d '{
"collection": "tickets",
"value": {
"customer": {"name": "Jana Nováková", "email": "jana@example.com"},
"status": "open",
"priority": 3,
"created_at": "2026-10-01T09:15:00Z"
}
}'
{
"key": "8f14e45f-ceea-467a-9b1c-4e1f2a6b3c70",
"value": {
"customer": {"name": "Jana Nováková", "email": "jana@example.com"},
"status": "open",
"priority": 3,
"created_at": "2026-10-01T09:15:00Z"
}
}
Create many records
Adds several records, possibly to different collections.
| Endpoint | POST /api/v3/booster/database/private/create-many |
| Scope | ayeto.booster.database.write |
| Rate limit | default |
Request
The body is a JSON array of objects of the same shape as for
Create a record (collection, value, optional key).
The items are written one by one, in order. The batch is not atomic: if an item
fails, the request returns the error, the records before it stay created and the
items after it are not written. An item whose key already exists stops the batch
with 422. Before retrying a failed batch, check what was
written, or send your own keys so that you can tell which items exist.
Response
An array of the created records, in request order.
Errors
The errors of Create a record, for the first item that failed.
Examples
curl -X POST "https://ayeto.ai/api/v3/booster/database/private/create-many" \
-H "uni-api-key: $AYETO_API_KEY" \
-H "panel-id: 3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90" \
-H "Content-Type: application/json" \
-d '[
{"collection": "products", "key": "0b6e8c1a-5d2f-4e3b-9a7c-1f4d6e8a2b30", "value": {"sku": "MUG-01", "name": "Mug", "quantity": 12}},
{"collection": "products", "key": "5a9d3f2e-8c1b-4a6e-b7d0-3e2f1c9a8b54", "value": {"sku": "TEE-M", "name": "T-shirt M", "quantity": 40}}
]'
[
{"key": "0b6e8c1a-5d2f-4e3b-9a7c-1f4d6e8a2b30", "value": {"sku": "MUG-01", "name": "Mug", "quantity": 12}},
{"key": "5a9d3f2e-8c1b-4a6e-b7d0-3e2f1c9a8b54", "value": {"sku": "TEE-M", "name": "T-shirt M", "quantity": 40}}
]
Update a record
Replaces the value of a record.
| Endpoint | POST /api/v3/booster/database/private/update |
| Scope | ayeto.booster.database.write |
| Rate limit | default |
Request
| Field | Type | Required | Description |
|---|---|---|---|
key |
UUID | yes | Key of the record. |
value |
any | no | The new value. It replaces the stored value completely; fields you leave out are removed. Omitted means null. |
To change a single field, read the record, change the field and send the whole value back. If other clients may write the same record at the same time, do this under a lock.
Response
The updated record.
Errors
| Status | detail |
Cause |
|---|---|---|
404 |
Database record not found |
This panel's database has no record with the key. |
Examples
curl -X POST "https://ayeto.ai/api/v3/booster/database/private/update" \
-H "uni-api-key: $AYETO_API_KEY" \
-H "panel-id: 3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90" \
-H "Content-Type: application/json" \
-d '{
"key": "8f14e45f-ceea-467a-9b1c-4e1f2a6b3c70",
"value": {
"customer": {"name": "Jana Nováková", "email": "jana@example.com"},
"status": "closed",
"priority": 3,
"created_at": "2026-10-01T09:15:00Z"
}
}'
{
"key": "8f14e45f-ceea-467a-9b1c-4e1f2a6b3c70",
"value": {
"customer": {"name": "Jana Nováková", "email": "jana@example.com"},
"status": "closed",
"priority": 3,
"created_at": "2026-10-01T09:15:00Z"
}
}
Update many records
Replaces the values of several records.
| Endpoint | POST /api/v3/booster/database/private/update-many |
| Scope | ayeto.booster.database.write |
| Rate limit | default |
Request
The body is a JSON array of objects of the same shape as for
Update a record (key, value). Items are written one by one, in
order, and the batch is not atomic: a failing item stops the request, the items before
it stay updated.
Response
An array of the updated records, in request order.
Errors
The errors of Update a record, for the first item that failed.
Examples
curl -X POST "https://ayeto.ai/api/v3/booster/database/private/update-many" \
-H "uni-api-key: $AYETO_API_KEY" \
-H "panel-id: 3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90" \
-H "Content-Type: application/json" \
-d '[
{"key": "0b6e8c1a-5d2f-4e3b-9a7c-1f4d6e8a2b30", "value": {"sku": "MUG-01", "name": "Mug", "quantity": 10}},
{"key": "5a9d3f2e-8c1b-4a6e-b7d0-3e2f1c9a8b54", "value": {"sku": "TEE-M", "name": "T-shirt M", "quantity": 37}}
]'
[
{"key": "0b6e8c1a-5d2f-4e3b-9a7c-1f4d6e8a2b30", "value": {"sku": "MUG-01", "name": "Mug", "quantity": 10}},
{"key": "5a9d3f2e-8c1b-4a6e-b7d0-3e2f1c9a8b54", "value": {"sku": "TEE-M", "name": "T-shirt M", "quantity": 37}}
]
Delete a record
Deletes one record.
| Endpoint | POST /api/v3/booster/database/private/delete |
| Scope | ayeto.booster.database.write |
| Rate limit | default |
Request
| Field | Type | Required | Description |
|---|---|---|---|
key |
UUID | yes | Key of the record. |
Response
null.
Errors
| Status | detail |
Cause |
|---|---|---|
404 |
Database record not found |
This panel's database has no record with the key (also when it was already deleted). |
Examples
curl -X POST "https://ayeto.ai/api/v3/booster/database/private/delete" \
-H "uni-api-key: $AYETO_API_KEY" \
-H "panel-id: 3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90" \
-H "Content-Type: application/json" \
-d '{"key": "8f14e45f-ceea-467a-9b1c-4e1f2a6b3c70"}'
Delete many records
Deletes several records.
| Endpoint | POST /api/v3/booster/database/private/delete-many |
| Scope | ayeto.booster.database.write |
| Rate limit | default |
Request
The body is a JSON array of objects with a key field, as for
Delete a record. Records are deleted one by one, in order; a failing
item (for example a key that does not exist) stops the request, and the records before
it stay deleted.
Response
null.
Errors
The errors of Delete a record, for the first item that failed.
Examples
curl -X POST "https://ayeto.ai/api/v3/booster/database/private/delete-many" \
-H "uni-api-key: $AYETO_API_KEY" \
-H "panel-id: 3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90" \
-H "Content-Type: application/json" \
-d '[
{"key": "0b6e8c1a-5d2f-4e3b-9a7c-1f4d6e8a2b30"},
{"key": "5a9d3f2e-8c1b-4a6e-b7d0-3e2f1c9a8b54"}
]'
Locks
Locks let several clients (your servers, the panel itself) take turns on the same data. A lock has a time to live and is one of two kinds:
- Record lock:
collectionandkey. Use the record's actual collection; a lock taken under another collection name does not protect the record. - Collection lock:
collectionwithoutkey.
Locks are advisory: the server does not check them. get, find, count,
create, update, delete and their batch variants go through whether a record or
collection is locked or not. A lock only makes other lock/acquire calls for the same
lock wait, so it protects data only when every client that writes it takes the lock
first; coordinating that is up to the panel and your code.
- Record and collection locks are independent. Holding a collection lock does not stop anyone from taking a record lock in it, and the other way round.
- Anyone may release a lock.
releasefrees the lock whoever took it, and a secondacquireof a lock you already hold waits like anyone else's. Release a lock only from the code that acquired it. - Locks expire. Every lock is freed automatically after its
ttl, even if it was never released. Choose a TTL longer than your work takes, but short enough that a crashed client does not block others for long.
Locking is the lock operation of collection rules; both
endpoints need the write scope and the same access to the panel as writing.
Acquire a lock
Takes a record or collection lock, waiting until it is free.
| Endpoint | POST /api/v3/booster/database/private/lock/acquire |
| Scope | ayeto.booster.database.write |
| Rate limit | default |
Request
| Field | Type | Required | Description |
|---|---|---|---|
collection |
string | yes | Collection name. |
key |
UUID | no | Record key. Omit it to take the collection lock. |
acquire_timeout |
number | no | Seconds to wait for the lock. 0 fails at once when the lock is taken. When omitted, the request waits as long as it takes, up to the remaining TTL of the current holder; always send a value shorter than your HTTP timeout. |
ttl |
number | no | Seconds after which the lock is released automatically. Must be greater than 0.1. Default 3600. |
Response
null, once the lock is yours.
Errors
| Status | detail |
Cause |
|---|---|---|
423 |
Failed to acquire lock for collection '<collection>' and key '<key>' |
The lock stayed taken for acquire_timeout seconds (<key> is None for a collection lock). Retry later. |
422 |
validation error | ttl is 0.1 or less. |
Examples
curl -X POST "https://ayeto.ai/api/v3/booster/database/private/lock/acquire" \
-H "uni-api-key: $AYETO_API_KEY" \
-H "panel-id: 3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90" \
-H "Content-Type: application/json" \
-d '{"collection": "products", "key": "0b6e8c1a-5d2f-4e3b-9a7c-1f4d6e8a2b30", "acquire_timeout": 10, "ttl": 30}'
Release a lock
Frees a record or collection lock, whoever holds it.
| Endpoint | POST /api/v3/booster/database/private/lock/release |
| Scope | ayeto.booster.database.write |
| Rate limit | default |
Request
| Field | Type | Required | Description |
|---|---|---|---|
collection |
string | yes | Collection name, as sent to lock/acquire. |
key |
UUID | no | Record key, as sent to lock/acquire. Omit it for the collection lock. |
Response
null. Releasing a lock that is not taken (or has expired) also succeeds.
Examples
curl -X POST "https://ayeto.ai/api/v3/booster/database/private/lock/release" \
-H "uni-api-key: $AYETO_API_KEY" \
-H "panel-id: 3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90" \
-H "Content-Type: application/json" \
-d '{"collection": "products", "key": "0b6e8c1a-5d2f-4e3b-9a7c-1f4d6e8a2b30"}'
Read-modify-write under a lock
update replaces the whole value, so two clients that each read a record, change it
and write it back can overwrite each other. Take the record lock around the whole
sequence and release it in a finally block; every client writing the record must do
the same:
import os
import time
import requests
BASE_URL = "https://ayeto.ai/api/v3/booster/database/private"
HEADERS = {
"uni-api-key": os.environ["AYETO_API_KEY"],
"panel-id": "3d2c5a8e-7b41-4f0e-9a6d-2c8b1e4f7a90",
}
def call(path: str, body):
response = requests.post(f"{BASE_URL}/{path}", json=body, headers=HEADERS, timeout=30)
response.raise_for_status()
return response.json()
def change_stock(key: str, delta: int, attempts: int = 3) -> dict:
"""Add `delta` to the quantity of a product record without losing concurrent changes."""
lock = {"collection": "products", "key": key}
for attempt in range(attempts):
try:
# wait at most 10 s; the lock frees itself after 30 s if this process dies
call("lock/acquire", {**lock, "acquire_timeout": 10, "ttl": 30})
break
except requests.HTTPError as e:
if e.response.status_code != 423 or attempt == attempts - 1:
raise
time.sleep(2)
try:
record = call("get", {"key": key})
value = record["value"]
value["quantity"] = value.get("quantity", 0) + delta
return call("update", {"key": key, "value": value})
finally:
call("lock/release", lock)
print(change_stock("0b6e8c1a-5d2f-4e3b-9a7c-1f4d6e8a2b30", -2))