API / API reference

Account

Who the token belongs to, and the shape vocabulary.

Single resources and collections come back wrapped in data. Paginated collections add links and meta. Errors are never wrapped; see Errors.
GET /api/v1/masks Scope components:read

Every shape a component can take, including the designer's custom masks

Returns card and token arrays. Send an option's value verbatim as card_mask_type (cards) or shape (tokens).

Each option has a source: preset for a shape the app ships, or custom for one this designer drew in the Mask Editor. Custom masks vary per account, so the list cannot be hardcoded.

Every option carries exactly ONE ratio, aspect, written the way ratios are written: 1:1 square, 5:7 a portrait card, 7:5 landscape. It is the ratio the shape was authored at, not a decimal of it, so it is the same value the designer typed in the Mask Editor. null means the shape forces no footprint and the component keeps its own physical size. A shaped mask has to force its box, because a hexagon squeezed into a 2.5x3.5 card box is not a hexagon.

Call this before offering a shape picker. You may also send a custom mask's NAME as the value on a component write and it will be resolved for you.

A shape that is not in this list and is not one of the designer's own mask names is REJECTED with 422, rather than stored. A value the app does not recognise would come back describing a shape that appears nowhere here, and the next time the designer opened that component the shape dropdown would match nothing, so saving the form would clear the mask.

curl "https://dustinsdesignerden.com/api/v1/masks" \
  -H "Authorization: Bearer $DDD_TOKEN"
const res = await fetch('https://dustinsdesignerden.com/api/v1/masks', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await res.json();
$response = Http::withToken($token)->get('https://dustinsdesignerden.com/api/v1/masks');

$data = $response->json();
res = requests.get(
    'https://dustinsdesignerden.com/api/v1/masks',
    headers={'Authorization': f'Bearer {token}'},
)

data = res.json()
Response 200
{
    "card": [
        {
            "value": "rectangle",
            "label": "Rectangle",
            "source": "preset",
            "aspect": null
        },
        {
            "value": "rectangle_rounded",
            "label": "Rectangle (Rounded)",
            "source": "preset",
            "aspect": null
        },
        {
            "value": "square",
            "label": "Square",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "square_rounded",
            "label": "Square (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "circle",
            "label": "Circle",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "diamond",
            "label": "Diamond",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:diamond_rounded",
            "label": "Diamond (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "triangle",
            "label": "Triangle",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "triangle_rounded",
            "label": "Triangle (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:pentagon",
            "label": "Pentagon",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:pentagon_rounded",
            "label": "Pentagon (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "pointy",
            "label": "Hexagon (Pointy)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:hex_pointy_rounded",
            "label": "Hexagon (Pointy, Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "flat",
            "label": "Hexagon (Flat)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:hex_flat_rounded",
            "label": "Hexagon (Flat, Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:octagon",
            "label": "Octagon",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:octagon_rounded",
            "label": "Octagon (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:star",
            "label": "Star",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:star_rounded",
            "label": "Star (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "custom:1",
            "label": "My Swoosh",
            "source": "custom",
            "aspect": "1:1"
        }
    ],
    "token": [
        {
            "value": "rectangle",
            "label": "Rectangle",
            "source": "preset",
            "aspect": null
        },
        {
            "value": "rectangle_rounded",
            "label": "Rectangle (Rounded)",
            "source": "preset",
            "aspect": null
        },
        {
            "value": "square",
            "label": "Square",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "square_rounded",
            "label": "Square (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "circle",
            "label": "Circle",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:diamond_rounded",
            "label": "Diamond (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "triangle",
            "label": "Triangle",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "triangle_rounded",
            "label": "Triangle (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:pentagon",
            "label": "Pentagon",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:pentagon_rounded",
            "label": "Pentagon (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "hex_pointy",
            "label": "Hexagon (Pointy)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:hex_pointy_rounded",
            "label": "Hexagon (Pointy, Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "hex_flat",
            "label": "Hexagon (Flat)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:hex_flat_rounded",
            "label": "Hexagon (Flat, Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:octagon",
            "label": "Octagon",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:octagon_rounded",
            "label": "Octagon (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:star",
            "label": "Star",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "default:star_rounded",
            "label": "Star (Rounded)",
            "source": "preset",
            "aspect": "1:1"
        },
        {
            "value": "custom:1",
            "label": "My Swoosh",
            "source": "custom",
            "aspect": "1:1"
        }
    ]
}

Response: Shape option

card array
Every shape a card may use. Each entry has the value, label, source and aspect described below.
token array
Every shape a token may use. Entries have the same four fields as card.
value string
Send this verbatim as a card's card_mask_type or a token's shape. Never blank: every shape has a name, and a plain rectangle is rectangle.
label string
Human name, as the designer sees it in the app.
source string
Where the shape comes from, and there are only two: preset for the shapes the app ships, and custom for one this designer drew in the mask editor.
aspect string|null
The footprint this shape forces, written the way ratios are written: 1:1 is square, 5:7 is a portrait card, 7:5 is landscape. null means the shape forces nothing and the component keeps its own physical size, which is what a plain rectangle does. A shaped mask has to force its box, because a hexagon squeezed into a 2.5x3.5 card is not a hexagon. Divide it if you need a number for layout.
GET /api/v1/me Scope any

Who this token belongs to, plus quota and plan limits

Who the token acts for, what it is allowed to do, and how much room the designer has left. A good first call.

Worth reading before an upload or creating a project, so you can say they are out of space or at their project cap instead of failing halfway through. It also reports the scopes the token actually holds, which can be fewer than you asked for, and the app value your writes get stamped with, which is the same value that decides which rows your deletes can reach.

curl "https://dustinsdesignerden.com/api/v1/me" \
  -H "Authorization: Bearer $DDD_TOKEN"
const res = await fetch('https://dustinsdesignerden.com/api/v1/me', {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${token}`,
  },
});

const data = await res.json();
$response = Http::withToken($token)->get('https://dustinsdesignerden.com/api/v1/me');

$data = $response->json();
res = requests.get(
    'https://dustinsdesignerden.com/api/v1/me',
    headers={'Authorization': f'Bearer {token}'},
)

data = res.json()
Response 200
{
    "user": {
        "id": 1,
        "name": "Dustin",
        "email": "designer@example.com"
    },
    "storage": {
        "used_bytes": 4194304,
        "limit_bytes": 104857600,
        "remaining_bytes": 100663296,
        "used_human": "4.0 MB",
        "limit_human": "100.0 MB"
    },
    "projects": {
        "count": 1,
        "unlocked_count": 1,
        "can_create": true,
        "unlocked_limit": 2
    },
    "token": {
        "scopes": [],
        "app": "api:personal"
    }
}

Response: Account

user object
id, name and email of the designer this token acts for.
storage object
used_bytes, limit_bytes, remaining_bytes and human-readable equivalents. Check before uploading.
projects object
count, unlocked_count, can_create and unlocked_limit (null means uncapped).
token object
Facts about the calling token itself.
scopes array
Inside token: the scopes this token actually holds. Check here rather than assuming what you asked for was granted.
app string
Inside token: the identifier your writes are stamped with (api:{client}, or api:personal). Your deletes only ever reach rows carrying this value.