-
Notifications
You must be signed in to change notification settings - Fork 1.8k
api
Creates a group and returns a UID (UUID formatted).
Groups do not have names, or any other descriptive attributes.
Instead they are always identified with a UUID, and they have
a metadata
property.
The metadata
property will always be given back to the client
in the same way it was provided. The extra
property, also an
object, may be changed by the backend. The behavior of setting
any property on extra
is currently undefined as all properties
are reserved for future use.
-
metadata: - optional
-
accepts:
object
- description: arbitrary metadata to describe the group
-
accepts:
-
extra: - optional
-
accepts:
object
- description: extra parameters (server may change these)
-
accepts:
await fetch(`${window.api_origin}/group/create`, {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({
metadata: { title: 'Some Title' }
}),
"method": "POST",
});
// { uid: '9c644a1c-3e43-4df4-ab67-de5b68b235b6' }
{
"uid": "9c644a1c-3e43-4df4-ab67-de5b68b235b6"
}
Adds one or more users to a group
-
uid: - required
-
accepts:
string
UUID of an existing group
-
accepts:
-
users:
Array<string>
usernames of users to add to the group
await fetch(`${window.api_origin}/group/add-users`, {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({
uid: '9c644a1c-3e43-4df4-ab67-de5b68b235b6',
users: ['first_user', 'second_user'],
}),
"method": "POST",
});
Remove one or more users from a group
-
uid: - required
-
accepts:
string
UUID of an existing group
-
accepts:
-
users:
Array<string>
usernames of users to remove from the group
await fetch(`${window.api_origin}/group/add-users`, {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({
uid: '9c644a1c-3e43-4df4-ab67-de5b68b235b6',
users: ['first_user', 'second_user'],
}),
"method": "POST",
});
List groups associated with the current user
none
{
"owned_groups": [
{
"uid": "c3bd4047-fc65-4da8-9363-e52195890de4",
"metadata": {},
"members": [
"default_user"
]
}
],
"in_groups": [
{
"uid": "c3bd4047-fc65-4da8-9363-e52195890de4",
"metadata": {},
"members": [
"default_user"
]
}
]
}
Grant permission from the current user to a group. This creates an association between the user and the group for this permission; the group will only have the permission effectively while the user who granted permission has the permission.
-
group_uid: - required
-
accepts:
string
UUID of an existing group
-
accepts:
-
permission: - required
-
accepts:
string
A permission string
-
accepts:
await fetch("http://puter.localhost:4100/auth/grant-user-group", {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({
group_uid: '9c644a1c-3e43-4df4-ab67-de5b68b235b6',
permission: 'fs:/someuser/somedir/somefile:read'
}),
"method": "POST",
});
Revoke permission granted from the current user to a group.
-
group_uid: - required
-
accepts:
string
UUID of an existing group
-
accepts:
-
permission: - required
-
accepts:
string
A permission string
-
accepts:
await fetch("http://puter.localhost:4100/auth/grant-user-group", {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({
group_uid: '9c644a1c-3e43-4df4-ab67-de5b68b235b6',
permission: 'fs:/someuser/somedir/somefile:read'
}),
"method": "POST",
});
-
TODO figure out how to manage documentation that could reasonably show up in two files. For example: this is a group endpoint as well as a permission system endpoint. (architecturally it's a permission system endpoint, and the permissions feature depends on the groups feature; at least until a time when PermissionService is refactored so a service like GroupService can mutate the permission check sequences)
Endpoints for managing notifications.
The /notif/mark-ack
endpoint marks the specified notification
as "acknowledged". This indicates that the user has chosen to either
dismiss or act on this notification.
Name | Description | Default Value |
---|---|---|
uid | UUID associated with the notification | required |
This endpoint responds with an empty object ({}
).
The /notif/mark-read
endpoint marks that the specified notification
has been shown to the user. It will not "pop up" as a new notification
if they load the gui again.
Name | Description | Default Value |
---|---|---|
uid | UUID associated with the notification | required |
This endpoint responds with an empty object ({}
).
await fetch("https://api.puter.local/notif/mark-read", {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
body: JSON.stringify({
uid: 'a14ea3d5-828b-42f9-9613-35f43b0a3cb8',
}),
method: "POST",
});
The puter-notifications
driver is an Entity Storage driver.
It is read-only.
await fetch("http://api.puter.localhost:4100/drivers/call", {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({
interface: 'puter-notifications',
method: 'select',
args: { predicate: ['unread'] }
}),
"method": "POST",
});
await fetch("http://api.puter.localhost:4100/drivers/call", {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({
interface: 'puter-notifications',
method: 'select',
args: {}
}),
"method": "POST",
});
await fetch("http://api.puter.localhost:4100/drivers/call", {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({
interface: 'puter-notifications',
method: 'select',
args: { offset: 200 }
}),
"method": "POST",
});
Share endpoints allow sharing files with other users.
The /share
endpoint shares 1 or more filesystem items
with one or more recipients. The recipients will receive
some notification about the shared item, making this
different from calling /grant-user-user
with a permission.
When users are specified by email they will receive a share link.
Each item specified in the shares
property is a tag-typed
object of type fs-share
or app-share
.
File shares grant permission to a file or directory. By default
this is read permission. If access
is specified as "write"
,
then write permission will be granted.
App shares grant permission to read a protected app.
If there is a subdomain associated with the app, and the owner
of the subdomain is the same as the owner of the app, then
permission to access the subdomain will be granted.
Note that the subdomain is only associated if the subdomain
entry has associated_app_id
set according to the app's id,
and will not be considered "associated" if only the index_url
happens to match the subdomain url.
If the app has shared_appdata
set to true
in its metadata
object, the recipient of the share will also get write permission
to the app owner's corresponding appdata directory. The appdata
directory must exist for this to work as expected
(otherwise the permission rewrite rule fails since the uuid
can't be determined).
{
"recipients": [
"user_that_gets_shared_to",
"[email protected]"
],
"shares": [
{
"$": "app-share",
"name": "some-app-name"
},
{
"$": "app-share",
"uid": "app-SOME-APP-UID"
},
{
"$": "fs-share",
"path": "/some/file/or/directory"
},
{
"$": "fs-share",
"path": "SOME-FILE-UUID"
}
]
}
-
recipients - required
-
accepts:
string | Array<string>
- description: recipients for the filesystem entries being shared.
-
notes:
- validation on
string
: email or username - requirement of at least one value
- validation on
-
accepts:
-
shares: - required
-
accepts:
object | Array<object>
- object is type-tagged
- type is either file-share or app-share
-
notes:
- requirement that file/directory or app exists
- requirement of at least one entry
-
accepts:
-
dry_run: - optional
-
accepts:
bool
- description: when true, only validation will occur
-
accepts:
-
$:
api:share
-
$version:
v0.0.0
-
status: one of:
"success"
,"mixed"
,"aborted"
-
recipients: array of:
api:status-report
orheyputer:api/APIError
-
paths: array of:
api:status-report
orheyputer:api/APIError
-
dry_run:
true
if present
await fetch("http://puter.localhost:4100/share", {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
body: JSON.stringify({
recipients: [
"user_that_gets_shared_to",
"[email protected]"
],
shares: [
{
$: "app-share",
name: "some-app-name"
},
{
$: "app-share",
uid: "app-SOME-APP-UID"
},
{
$: "fs-share",
path: "/some/file/or/directory"
},
{
$: "fs-share",
path: "SOME-FILE-UUID"
}
]
}),
method: "POST",
});
{
"$": "api:share",
"$version": "v0.0.0",
"status": "success",
"recipients": [
{
"$": "api:status-report",
"status": "success"
}
],
"paths": [
{
"$": "api:status-report",
"status": "success"
}
],
"dry_run": true
}
{
"$": "api:share",
"$version": "v0.0.0",
"status": "mixed",
"recipients": [
{
"$": "api:status-report",
"status": "success"
}
],
"paths": [
{
"$": "heyputer:api/APIError",
"code": "subject_does_not_exist",
"message": "File or directory not found.",
"status": 404
}
],
"dry_run": true
}
{
"$": "api:share",
"$version": "v0.0.0",
"status": "mixed",
"recipients": [
{
"$": "heyputer:api/APIError",
"code": "user_does_not_exist",
"message": "The user `non_existing_user` does not exist.",
"username": "non_existing_user",
"status": 422
}
],
"paths": [
{
"$": "api:status-report",
"status": "success"
}
],
"dry_run": true
}
The /sharelink/check
endpoint verifies that a token provided
by a share link is valid.
await fetch(`${config.api_origin}/sharelink/check`, {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({
token: '...',
}),
"method": "POST",
});
-
token: - required
-
accepts:
string
The token from the querystring parameter
-
accepts:
A type-tagged object, either of type api:share
or api:error
{
"$": "api:share",
"uid": "836671d4-ac5d-4bd3-bc0a-ec357e0d8f02",
"email": "[email protected]"
}
{
"$": "api:error",
"message":"Field `token` is required.",
"key":"token",
"code":"field_missing"
}
The /sharelink/apply
endpoint applies a share to the current
user if and only if that user's email is confirmed and matches
the email associated with the share.
await fetch(`${config.api_origin}/sharelink/apply`, {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({
uid: '836671d4-ac5d-4bd3-bc0a-ec357e0d8f02',
}),
"method": "POST",
});
-
uid: - required
-
accepts:
string
The uid of an existing share, received using/sharelink/check
-
accepts:
A type-tagged object, either of type api:status-report
or api:error
{"$":"api:status-report","status":"success"}
{
"message": "This share can not be applied to this user.",
"code": "can_not_apply_to_this_user"
}
The /sharelink/request
endpoint requests the permissions associated
with a share link to the issuer of the share (user that sent the share).
This can be used when a user is logged in, but that user's email does
not match the email associated with the share.
await fetch(`${config.api_origin}/sharelink/request`, {
"headers": {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
"body": JSON.stringify({
uid: '836671d4-ac5d-4bd3-bc0a-ec357e0d8f02',
}),
"method": "POST",
});
-
uid: - required
-
accepts:
string
The uid of an existing share, received using/sharelink/check
-
accepts:
A type-tagged object, either of type api:status-report
or api:error
{"$":"api:status-report","status":"success"}
{
"message": "This share is already valid for this user; POST to /apply for access",
"code": "no_need_to_request"
}
Reports permissions that the current user has granted to the specified user on the specified file, or any affecting parents of the file.
The response contains a property called permissions
which holds an object.
This object has file path keys, and each value is a list of permissions
granted on the respective file path. Typically there will only be one
permission per path if all access to shared resources was granted via
ACLService. It is possible to grant redundant permissions (i.e. both read and
write on the same file) via PermissionService directly. In this case, ACL
treats the most permissive permission as the effective permission. Any
further action through ACLService (ex: via /acl/set-user-user
) will result
in redundant permissions being removed.
-
user: - required
-
accepts:
string
username of the holder of permissions issued by the current user
-
accepts:
-
resource: - required
-
accepts:
string
path or UUID of a file
-
accepts:
await (await fetch("http://puter.localhost:4100/acl/stat-user-user", {
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${puter.authToken}`,
},
body: JSON.stringify({
user: 'ed3',
resource: '/admin/Desktop/shared_dir/sub_dir/share_test.txt'
}),
method: "POST",
})).json();
{
"permissions": {
"/admin/Desktop/shared_dir/sub_dir/share_test.txt": [
"fs:940685b5-5e96-4922-80b0-5504c417e1d6:write"
],
"/admin/Desktop/shared_dir": [
"fs:fc35cce1-0b1a-44ed-8b60-21455decd99c:read"
]
}
}
Revokes and/or grants permissions on a file to the specified user according to the specified desired access mode.
-
user: - required
-
accepts:
string
This is the user accessing the file. Permissions between the current user (the issuer), and this specified user (the holder), will be modified to achieve the desired access mode.
-
accepts:
-
resource: - required
-
accepts:
string
path or UUID of a file
-
accepts:
-
mode: - required
-
accepts:
string
The desired access mode;read
,write
,see
, orlist
.
-
accepts:
-
options: - optional
-
accepts:
object
This is an options object with the following parameters:-
only_if_higher -
If this is set to
true
, access will only be modified if the user doesn't have equivalent or higher access to the resource already. If the user has equivalent or higher access due to a parent directory, the permission will still be set on the resource.
-
only_if_higher -
If this is set to
-
accepts:
# Type-Tagged Objects
```js
{
"$": "some-type",
"$version": "0.0.0",
"some_property": "some value",
}
Type-Tagged objects are a convention understood by Puter's backend
to communicate meta information along with a JSON object.
The key feature of Type-Tagged Objects is the type key: "$"
.
The primary reason: to have a consistent convention we can use anywhere.
- Since other services rarely use
$
in their property names, we can safely use this without introducing reserved words and re-mapping property names. - Some places we use this convention might not need it, but staying consistent means API end-users can do more with less code.
- The
"$"
key indicates a type (or class) of object - Any other key beginning with
$
is a meta-key - Other keys are not allowed to contain
$
-
"$version"
must follow semver - Keys with multiple
"$"
symbols are reserved for future use
Puter's API will always send results in the format described above, which is called the "Standard Representation"
Any endpoint which accepts a Type-Tagged Object will also accept these alternative representations:
Depending on the architecture of your client, this format may be more convenient to work with:
{
"$": "$meta-body",
"type": "some-type",
"meta": { "version": "0.0.0" },
"body": { "some_property": "some value" }
}
In the array representation, meta values go at the end.
["some-type",
{ "some_property": "some value" },
{ "version": "0.0.0" }
]
If the second element of the list is not an object, it will implicitly be placed in a property called value. The following are equivalent:
["some-type", "hello"]
["some-type", { "value": "hello" }]
- name: name of the app
- uid: name of the app
- One of
name
oruid
must be specified
Share app by name
{
"$": "app-share",
"name": "some-app-name"
}
Share app by uid
{
"$": "app-share",
"uid": "app-0a7337f7-0f8a-49ca-b71a-38d39304fe04"
}
- path: file or directory's path or uuid
-
access: one of:
"read"
,"write"
(default:"read"
)
Share with read access
{
"$": "file-share",
"path": "/some/path"
}
Share with write access
{
"$": "file-share",
"path": "/some/path",
"access": "write"
}
Using a UUID
{
"$": "file-share",
"path": "b912c381-0c0b-466c-95a6-f9a4fc680a7d"
}
A share link is a link to Puter's origin which contains a token
in the query string (the key is share_token
; ex:
http://puter.localhost:4100?share_token=...
).
This token can be used to apply permissions to the user of the current session if and only if this user's email is confirmed and matches the share link's associated email.
You are reading documentation for the open-source repository of Puter.
Getting started on localhost is as simple as git clone
npm install
npm start
.