Stocks
Ready-made units bought in batches.
This page covers the stock object, the stock batch object, the stock purchase object and the region object.
Endpoints
The stock object
Ready-made units you buy in batches ahead of time and that are kept in storage until orders use them. A variant can ship from a stock instead of being printed on demand.
Attributes
- idstring
Unique identifier of the stock, prefixed with
stk_. Treat it as an opaque string: store it and compare it, never parse it. - objectstring
Names the type of this object. Always
stock. - namestring
Display name.
- descriptionstring or null
Longer description, when provided.
- reviewReview
Review by 3DAPI. Anything that will be manufactured is reviewed before it can be sold or produced.
- units_per_batchinteger
How many units one purchased batch contains.
- batch_priceobject or null
What you pay for one batch, the same in every region. Set by 3DAPI when the stock is approved; null until then.
- unit_priceobject or null
What one unit costs you:
batch_pricedivided byunits_per_batch. Null until the stock is priced. - contentsarray of objects
What every unit of the stock is made of.
- inventoryobject
Units across every batch you bought.
- restockarray of object
Restock rule for each region the stock can be produced in. The regions are chosen by 3DAPI at approval.
- imagesarray of Image
Photos of the stock.
- attachmentsarray of objects
Production documents for this stock.
- created_attimestamp
Point in time, ISO 8601 in UTC.
- updated_attimestamp
Point in time, ISO 8601 in UTC.
{
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack",
"description": "Pre-assembled clickers, bagged.",
"review": {
"status": "approved",
"reason": null,
"reviewed_at": "2026-05-02T10:00:00Z"
},
"units_per_batch": 50,
"batch_price": {
"amount": 30000,
"currency": "usd"
},
"unit_price": {
"amount": 600,
"currency": "usd"
},
"contents": [
{
"type": "design",
"design": {
"id": "dsg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "design",
"name": "clicker.3mf"
}
},
{
"type": "extra",
"extra": {
"id": "xtr_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "extra",
"name": "M3 screw"
}
}
],
"inventory": {
"available": 32,
"in_production": 18,
"by_region": [
{
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"available": 32,
"in_production": 18
}
]
},
"restock": [
{
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"mode": "auto_buy",
"when_available_below": 10,
"reorder_units": 50
}
],
"images": [
{
"url": "https://cdn.example.com/clicker.png",
"primary": true
}
],
"attachments": [
{
"id": "att_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "attachment",
"name": "packing-guide.pdf"
}
],
"created_at": "2026-04-30T12:00:00Z",
"updated_at": "2026-05-02T10:00:00Z"
}List stocks
GET/
- Credentials
- An API key with the
stocks:readscope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
list_stocks
Lists your stocks, newest first, with how many units are available and in production. Filter on in_stock=true to see what can ship now. Designers only.
Query parameters
- review_statusarray of ReviewStatus
Only stocks in these review states.
Possible valuespendingapprovedrejected - in_stockstring
Only stocks with (or without) units available to ship.
Possible valuestruefalse - searchstring
Only stocks whose name contains this text, ignoring case.
- sortstring
Order of results. A leading
-means descending.namesorts alphabetically in a language-aware collation, which compares letters before spaces and case (test slicercomes aftertesting warnings); do not expect byte order.Possible values-created_atcreated_atname - limitinteger
How many results per page, from 1 to 100.
- cursorstring
Where to continue from: the
next_cursorof the previous page. Omit for the first page.
Returns200 OK
A page of stocks.
Responses
- 200
A page of stocks.
- 400
The request is invalid.
details.errorslists each problem (validation_failed), or anexpand[]path is unknown (invalid_expand). - 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 403
The credentials are valid but not allowed to do this: a scope is missing (
missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which casedetails.fix_urllinks to the dashboard page that fixes it. - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl "https://public-api.dapi.digital/v2/stocks" \
-H "x-api-key: $DAPI_API_KEY"{
"object": "list",
"data": [
{
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack",
"review": {
"status": "approved",
"reason": null,
"reviewed_at": "2026-05-02T10:00:00Z"
},
"units_per_batch": 50,
"batch_price": {
"amount": 30000,
"currency": "usd"
},
"unit_price": {
"amount": 600,
"currency": "usd"
},
"inventory": {
"available": 32,
"in_production": 18
},
"images": [
{
"url": "https://cdn.example.com/clicker.png",
"primary": true
}
],
"created_at": "2026-04-30T12:00:00Z",
"updated_at": "2026-05-02T10:00:00Z"
}
],
"has_more": false,
"next_cursor": null
}Create a stock
POST/
- Credentials
- An API key with the
stocks:writescope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
create_stock
Creates a stock (ready-made units you buy in batches) and submits it for review. It comes back pending, without a price or regions: 3DAPI sets the batch price and the production regions when approving it. Upload design files first with purpose design_file. Your plan must include prepaid stock. Designers only.
Headers
- Idempotency-Keystring
Any unique string, for example a UUID. Sending the same request again with the same key within 24 hours returns the first response without doing anything twice. Reusing a key with a different body is refused with
idempotency_key_reused. A refused request (4xx) frees the key so you can correct and resend it; a server error (5xx) is kept and returned again, because the write may already have happened: check the resource before retrying with a new key.
Request body
- namestringRequired
Display name.
- descriptionstring or null
Longer description. Null for none.
- units_per_batchintegerRequired
How many units one batch contains.
- extrasarray of string
Your extras packed into every unit. Each counts once per unit. An extra still pending review is accepted and is reviewed with the stock; a rejected one is refused (
extra_not_approved). - manufacturingobject
How the stock is produced. Applies to every design.
- imagesarray of objects
Stock photos, in display order. On create, every entry is a new
upload. On update the list replaces the current images: entries not sent are deleted, and kept ones use theurlthe stock returns. - attachmentsarray of objects
Production documents for the farm: new (
upload, purposeattachment) or kept (id, update only). On update the list replaces the current attachments. - designsarray of objectRequired
The model files of the stock. Add more later with
add_stock_design, which sends the stock back to review.
Returns201 Created
The new stock, pending review. Returns the stock object.
Responses
- 201
The new stock, pending review.
- 400
The request is invalid.
details.errorslists each problem (validation_failed), or anexpand[]path is unknown (invalid_expand). - 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 403
Your plan does not include prepaid stock, which stocks are part of (
plan_limit_reached);details.fix_urlpoints at upgrading. - 422
An extra id is not one of yours (
extra_not_found) or names an extra 3DAPI rejected (extra_not_approved, its name indetails.extra_name), a material id is not in the catalog (material_not_found), multicolor combinations have different slot counts (slot_count_mismatch), more than one image is primary (too_many_primary_images), an image or attachment is sent as one to keep although a new stock has none yet (unknown_image,unknown_attachment; send{ "upload": "upl_..." }), or an upload id is unknown, expired or for another purpose (unknown_upload,upload_expired,upload_purpose_mismatch,upload_missingwhen the file was never sent,upload_already_usedwhen the upload id was already used once). - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl -X POST "https://public-api.dapi.digital/v2/stocks" \
-H "x-api-key: $DAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Clicker 50 pack",
"units_per_batch": 50,
"designs": [
{
"file": {
"upload": "upl_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu"
},
"name": "Clicker",
"materials": {
"mode": "single",
"allowed": [
"mat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu"
]
}
}
],
"extras": [
"xtr_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu"
],
"manufacturing": {
"assembly_required": true,
"farm_instructions": "Bag in tens."
}
}'{
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack",
"description": "Pre-assembled clickers, bagged.",
"review": {
"status": "pending",
"reason": null,
"reviewed_at": null
},
"units_per_batch": 50,
"batch_price": null,
"unit_price": null,
"contents": [
{
"type": "design",
"design": {
"id": "dsg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "design",
"name": "clicker.3mf"
}
},
{
"type": "extra",
"extra": {
"id": "xtr_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "extra",
"name": "M3 screw"
}
}
],
"inventory": {
"available": 0,
"in_production": 0,
"by_region": []
},
"restock": [],
"images": [
{
"url": "https://cdn.example.com/clicker.png",
"primary": true
}
],
"attachments": [
{
"id": "att_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "attachment",
"name": "packing-guide.pdf"
}
],
"created_at": "2026-04-30T12:00:00Z",
"updated_at": "2026-05-02T10:00:00Z"
}Get a stock
GET/
- Credentials
- An API key with the
stocks:readscope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
get_stock
Returns one of your stocks: its price, contents, inventory per region and restock rules. Designers only.
Path parameters
- idstringRequired
Unique identifier of the stock, prefixed with
stk_. Treat it as an opaque string: store it and compare it, never parse it.
Query parameters
- expand[]array of string
Replace references with full objects. Repeat the parameter for several paths, for example
expand[]=contents.design. Unknown paths are rejected withinvalid_expand. An expanded object from another resource needs the read scope of that resource on your API key; without it the reference{ id, object, name }is returned instead, with no error. Herecontents.extraneedsextras:read.Possible valuescontents.designcontents.extraattachments
Returns200 OK
The stock. Returns the stock object.
Responses
- 200
The stock.
- 400
The request is invalid.
details.errorslists each problem (validation_failed), or anexpand[]path is unknown (invalid_expand). - 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 403
The credentials are valid but not allowed to do this: a scope is missing (
missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which casedetails.fix_urllinks to the dashboard page that fixes it. - 404
You have no stock with this id (
stock_not_found). - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl "https://public-api.dapi.digital/v2/stocks/stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu" \
-H "x-api-key: $DAPI_API_KEY"{
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack",
"description": "Pre-assembled clickers, bagged.",
"review": {
"status": "approved",
"reason": null,
"reviewed_at": "2026-05-02T10:00:00Z"
},
"units_per_batch": 50,
"batch_price": {
"amount": 30000,
"currency": "usd"
},
"unit_price": {
"amount": 600,
"currency": "usd"
},
"contents": [
{
"type": "design",
"design": {
"id": "dsg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "design",
"name": "clicker.3mf"
}
},
{
"type": "extra",
"extra": {
"id": "xtr_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "extra",
"name": "M3 screw"
}
}
],
"inventory": {
"available": 32,
"in_production": 18,
"by_region": [
{
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"available": 32,
"in_production": 18
}
]
},
"restock": [
{
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"mode": "auto_buy",
"when_available_below": 10,
"reorder_units": 50
}
],
"images": [
{
"url": "https://cdn.example.com/clicker.png",
"primary": true
}
],
"attachments": [
{
"id": "att_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "attachment",
"name": "packing-guide.pdf"
}
],
"created_at": "2026-04-30T12:00:00Z",
"updated_at": "2026-05-02T10:00:00Z"
}Update a stock
PATCH/
- Credentials
- An API key with the
stocks:writescope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
update_stock
Changes the fields you send. Changing units_per_batch or the farm instructions sends the stock back to review; it cannot be bought until approved again. Designers only.
Path parameters
- idstringRequired
Unique identifier of the stock, prefixed with
stk_. Treat it as an opaque string: store it and compare it, never parse it.
Request body
- namestring
Display name.
- descriptionstring or null
Longer description. Null for none.
- units_per_batchinteger
How many units one batch contains.
- extrasarray of string
Your extras packed into every unit. Each counts once per unit. An extra still pending review is accepted and is reviewed with the stock; a rejected one is refused (
extra_not_approved). - manufacturingobject
How the stock is produced. Applies to every design.
- imagesarray of objects
Stock photos, in display order. On create, every entry is a new
upload. On update the list replaces the current images: entries not sent are deleted, and kept ones use theurlthe stock returns. - attachmentsarray of objects
Production documents for the farm: new (
upload, purposeattachment) or kept (id, update only). On update the list replaces the current attachments.
Returns200 OK
The updated stock. Returns the stock object.
Responses
- 200
The updated stock.
- 400
The request is invalid.
details.errorslists each problem (validation_failed), or anexpand[]path is unknown (invalid_expand). - 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 403
The credentials are valid but not allowed to do this: a scope is missing (
missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which casedetails.fix_urllinks to the dashboard page that fixes it. - 404
You have no stock with this id (
stock_not_found). - 422
An extra id is not one of yours (
extra_not_found) or names an extra 3DAPI rejected (extra_not_approved, its name indetails.extra_name), an imageurlor attachmentidto keep is not one of the stock's (unknown_image,unknown_attachment), more than one image is primary (too_many_primary_images), or an upload id is unknown, expired or for another purpose. - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl -X PATCH "https://public-api.dapi.digital/v2/stocks/stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu" \
-H "x-api-key: $DAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"units_per_batch": 50,
"manufacturing": {
"assembly_required": true,
"farm_instructions": "Pack each unit in its own bag."
}
}'{
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack",
"description": "Pre-assembled clickers, bagged.",
"review": {
"status": "approved",
"reason": null,
"reviewed_at": "2026-05-02T10:00:00Z"
},
"units_per_batch": 50,
"batch_price": {
"amount": 30000,
"currency": "usd"
},
"unit_price": {
"amount": 600,
"currency": "usd"
},
"contents": [
{
"type": "design",
"design": {
"id": "dsg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "design",
"name": "clicker.3mf"
}
},
{
"type": "extra",
"extra": {
"id": "xtr_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "extra",
"name": "M3 screw"
}
}
],
"inventory": {
"available": 32,
"in_production": 18,
"by_region": [
{
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"available": 32,
"in_production": 18
}
]
},
"restock": [
{
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"mode": "auto_buy",
"when_available_below": 10,
"reorder_units": 50
}
],
"images": [
{
"url": "https://cdn.example.com/clicker.png",
"primary": true
}
],
"attachments": [
{
"id": "att_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "attachment",
"name": "packing-guide.pdf"
}
],
"created_at": "2026-04-30T12:00:00Z",
"updated_at": "2026-05-02T10:00:00Z"
}Add a design to a stock
POST/
- Credentials
- An API key with the
stocks:writescope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
add_stock_design
Adds a model file to a stock. Sends the stock back to review. Edit or remove designs with the design operations. Designers only.
Path parameters
- idstringRequired
Unique identifier of the stock, prefixed with
stk_. Treat it as an opaque string: store it and compare it, never parse it.
Headers
- Idempotency-Keystring
Any unique string, for example a UUID. Sending the same request again with the same key within 24 hours returns the first response without doing anything twice. Reusing a key with a different body is refused with
idempotency_key_reused. A refused request (4xx) frees the key so you can correct and resend it; a server error (5xx) is kept and returned again, because the write may already have happened: check the resource before retrying with a new key.
Request body
- fileobjectRequired
The model file, uploaded first with purpose
design_file. - namestring or null
Display name. The file name when omitted.
- materialsobjectRequired
Returns201 Created
The new design, pending review. Returns the design object.
Responses
- 201
The new design, pending review.
- 400
The request is invalid.
details.errorslists each problem (validation_failed), or anexpand[]path is unknown (invalid_expand). - 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 403
The credentials are valid but not allowed to do this: a scope is missing (
missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which casedetails.fix_urllinks to the dashboard page that fixes it. - 404
You have no stock with this id (
stock_not_found). - 422
A material id is not in the catalog (
material_not_found), multicolor combinations have different slot counts (slot_count_mismatch), or the upload id is unknown, expired or for another purpose. - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl -X POST "https://public-api.dapi.digital/v2/stocks/stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu/designs" \
-H "x-api-key: $DAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"file": {
"upload": "upl_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu"
},
"name": "Tracker lid",
"materials": {
"mode": "single",
"allowed": [
"mat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu"
]
}
}'{
"id": "dsg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "design",
"name": "tracker.3mf",
"owner": {
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack"
},
"review": {
"status": "pending",
"reason": null,
"reviewed_at": null
},
"files": [
{
"id": "dfl_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "design_file",
"name": "tracker.3mf",
"format": "3mf",
"size_bytes": 2758723,
"download_url": "https://files.example.com/tracker.3mf?signature=abc",
"uploaded_at": "2026-04-21T07:34:06Z",
"production_version": {
"name": "farm-settings-tracker.3mf",
"format": "3mf",
"size_bytes": 2761090,
"download_url": "https://files.example.com/farm-settings-tracker.3mf?signature=def",
"prepared_at": "2026-04-21T07:36:40Z"
}
}
],
"materials": {
"mode": "single",
"allowed": [
{
"id": "mat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "material",
"name": "PLA Black",
"custom": false
},
{
"id": null,
"object": "material",
"name": "PETG Matte",
"custom": true
}
]
},
"manufacturing": {
"colors": 1,
"requires_ams": false,
"assembly_required": true,
"farm_instructions": null,
"extra_parts_note": "Two M2 screws"
},
"created_at": "2026-04-21T07:34:06Z",
"updated_at": "2026-04-21T09:10:00Z"
}Set a restock rule
PUT/
- Credentials
- An API key with the
stocks:writescope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
set_stock_restock
Sets what happens when one region runs low (see when_available_below for exactly what is counted). Auto-reorder buys from the same wallet: when a region reaches its restock threshold and auto-reorder is on in your wallet settings, batches are bought automatically (origin: auto_reorder), so keep enough balance for both. Returns the stock with its updated restock list. Designers only.
Path parameters
- idstringRequired
Unique identifier of the stock, prefixed with
stk_. Treat it as an opaque string: store it and compare it, never parse it. - region_idstringRequired
Unique identifier of the region, prefixed with
reg_. Treat it as an opaque string: store it and compare it, never parse it.
Request body
- modestringRequired
offdoes nothing,notifyemails you when the region runs low,auto_buybuysreorder_unitsfrom your wallet (when auto-reorder is on in your wallet settings; otherwise it emails).Possible valuesoffnotifyauto_buy - when_available_belowinteger or null
Threshold in units. The rule is checked each time an order draws units from this stock (when the order is assigned for production), not continuously. It counts the units paid for minus the units used in this region, across every batch and including units still in production (so not
available), and triggers when that count is at or below this threshold. Required unlessmodeisoff. - reorder_unitsinteger or null
Units to buy per automatic purchase, returned as set. Purchases round up to whole batches: an automatic purchase buys
reorder_unitsdivided byunits_per_batch, rounded up (at least one batch), atbatch_priceeach, and the batch it creates holds exactly those batches timesunits_per_batchunits. A multiple ofunits_per_batchbuys exactly what you ask for. Required forauto_buy.
Returns200 OK
The stock with the new rule. Returns the stock object.
Responses
- 200
The stock with the new rule.
- 400
The request is invalid, including a field the mode needs that is missing or one that does not apply to it (
validation_failed,details.errors). - 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 403
auto_buybuys stock, so your plan must include prepaid stock (plan_limit_reached);details.fix_urlpoints at upgrading. - 404
You have no stock with this id (
stock_not_found). - 422
The region is not one of the stock regions (
region_not_available). - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl -X PUT "https://public-api.dapi.digital/v2/stocks/stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu/restock/reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu" \
-H "x-api-key: $DAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mode": "auto_buy",
"when_available_below": 10,
"reorder_units": 50
}'{
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack",
"description": "Pre-assembled clickers, bagged.",
"review": {
"status": "approved",
"reason": null,
"reviewed_at": "2026-05-02T10:00:00Z"
},
"units_per_batch": 50,
"batch_price": {
"amount": 30000,
"currency": "usd"
},
"unit_price": {
"amount": 600,
"currency": "usd"
},
"contents": [
{
"type": "design",
"design": {
"id": "dsg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "design",
"name": "clicker.3mf"
}
},
{
"type": "extra",
"extra": {
"id": "xtr_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "extra",
"name": "M3 screw"
}
}
],
"inventory": {
"available": 32,
"in_production": 18,
"by_region": [
{
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"available": 32,
"in_production": 18
}
]
},
"restock": [
{
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"mode": "auto_buy",
"when_available_below": 10,
"reorder_units": 50
}
],
"images": [
{
"url": "https://cdn.example.com/clicker.png",
"primary": true
}
],
"attachments": [
{
"id": "att_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "attachment",
"name": "packing-guide.pdf"
}
],
"created_at": "2026-04-30T12:00:00Z",
"updated_at": "2026-05-02T10:00:00Z"
}The stock batch object
One purchase of a stock in one region: how many units were bought, how many are made and how many orders have used.
Attributes
- idstring
Unique identifier of the stock batch, prefixed with
bat_. Treat it as an opaque string: store it and compare it, never parse it. - objectstring
Names the type of this object. Always
stock_batch. - stockobject
The stock this batch is of.
- regionobject
Production region holding the units. Orders use units from a region that ships to the buyer.
- statusStockBatchStatus
Where the batch is:
queued: paid for; production has not started.in_production: the production partner is making the units. Units already made can be used by orders.completed: every unit has been made.used_up: orders have used every unit.
Possible valuesqueuedin_productioncompletedused_up - batchesinteger
How many batches were bought in this purchase line, at least one. Each holds the stock
units_per_batch. Anauto_reorderpurchase roundsreorder_unitsup to whole batches. - unitsobject
Unit counts for this batch.
- price_paidobject
What you paid for this purchase line, all batches included.
- unit_priceobject
What one unit cost you.
- purchase_referencestring or null
Reference of the checkout this batch was bought in, shared by every batch bought together and shown on the wallet charge.
- originstring
How the batch was bought:
manualby you (dashboard or API),auto_reorderautomatically from your wallet when a region reached its restock threshold.Possible valuesmanualauto_reorder - purchased_attimestamp
When the batch was bought.
- completed_attimestamp or null
When every unit was made. Null until then.
{
"id": "bat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock_batch",
"stock": {
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack"
},
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"status": "in_production",
"batches": 2,
"units": {
"purchased": 100,
"made": 60,
"used": 20,
"available": 40
},
"price_paid": {
"amount": 60000,
"currency": "usd"
},
"unit_price": {
"amount": 600,
"currency": "usd"
},
"purchase_reference": "ST-8KD2X",
"origin": "manual",
"purchased_at": "2026-09-30T10:00:00Z",
"completed_at": null
}List batches across stocks
GET/
- Credentials
- An API key with the
stocks:readscope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
list_all_stock_batches
Lists every batch you bought, of any stock, newest first. Use it to see everything in production at once, or every batch bought in one checkout with purchase_reference. Designers only.
Query parameters
- statusarray of StockBatchStatus
Only batches in these states. Repeat for several, for example
status=queued&status=in_production.Possible valuesqueuedin_productioncompletedused_up - regionstring
Only batches held in this region.
- sortstring
Order of results. A leading
-means newest first.Possible values-purchased_atpurchased_at - limitinteger
How many results per page, from 1 to 100.
- cursorstring
Where to continue from: the
next_cursorof the previous page. Omit for the first page. - stockstring
Only batches of this stock.
- purchased_aftertimestamp
Only batches bought after this time.
- purchased_beforetimestamp
Only batches bought before this time.
- originstring
Only batches you bought (
manual) or auto-reorder bought.Possible valuesmanualauto_reorder - purchase_referencestring
Only batches bought in this checkout, for example
ST-8KD2X.
Returns200 OK
A page of batches.
Responses
- 200
A page of batches.
- 400
The request is invalid.
details.errorslists each problem (validation_failed), or anexpand[]path is unknown (invalid_expand). - 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 403
The credentials are valid but not allowed to do this: a scope is missing (
missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which casedetails.fix_urllinks to the dashboard page that fixes it. - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl "https://public-api.dapi.digital/v2/stock-batches" \
-H "x-api-key: $DAPI_API_KEY"{
"object": "list",
"data": [
{
"id": "bat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock_batch",
"stock": {
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack"
},
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"status": "in_production",
"batches": 2,
"units": {
"purchased": 100,
"made": 60,
"used": 20,
"available": 40
},
"price_paid": {
"amount": 60000,
"currency": "usd"
},
"unit_price": {
"amount": 600,
"currency": "usd"
},
"purchase_reference": "ST-8KD2X",
"origin": "manual",
"purchased_at": "2026-09-30T10:00:00Z",
"completed_at": null
}
],
"has_more": false,
"next_cursor": null
}List what used a batch
GET/
- Credentials
- An API key with the
stocks:readscope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
list_stock_batch_usage
Lists the orders that took units from one batch, newest first. Designers only.
Path parameters
- idstringRequired
Unique identifier of the stock, prefixed with
stk_. Treat it as an opaque string: store it and compare it, never parse it. - batch_idstringRequired
Unique identifier of the stock batch, prefixed with
bat_. Treat it as an opaque string: store it and compare it, never parse it.
Query parameters
- limitinteger
How many results per page, from 1 to 100.
- cursorstring
Where to continue from: the
next_cursorof the previous page. Omit for the first page.
Returns200 OK
A page of usage lines.
Responses
- 200
A page of usage lines.
- 400
The request is invalid.
details.errorslists each problem (validation_failed), or anexpand[]path is unknown (invalid_expand). - 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 403
The credentials are valid but not allowed to do this: a scope is missing (
missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which casedetails.fix_urllinks to the dashboard page that fixes it. - 404
You have no such stock, or the batch is not one of its batches (
stock_not_found,stock_batch_not_found). - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl "https://public-api.dapi.digital/v2/stocks/stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu/batches/bat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu/usage" \
-H "x-api-key: $DAPI_API_KEY"{
"object": "list",
"data": [
{
"order": {
"id": "ord_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "order",
"name": "SSG2M9S9"
},
"variant": {
"id": "var_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "variant",
"name": "Clicker Blue"
},
"units": 2,
"used_at": "2026-10-11T08:00:00Z"
}
],
"has_more": false,
"next_cursor": null
}List the batches of a stock
GET/
- Credentials
- An API key with the
stocks:readscope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
list_stock_batches
Lists every batch you bought of one stock, newest first, with how many units are made, used and still available. Use it to follow production and see where your inventory is. Designers only.
Path parameters
- idstringRequired
Unique identifier of the stock, prefixed with
stk_. Treat it as an opaque string: store it and compare it, never parse it.
Query parameters
- statusarray of StockBatchStatus
Only batches in these states. Repeat for several, for example
status=queued&status=in_production.Possible valuesqueuedin_productioncompletedused_up - regionstring
Only batches held in this region.
- sortstring
Order of results. A leading
-means newest first.Possible values-purchased_atpurchased_at - limitinteger
How many results per page, from 1 to 100.
- cursorstring
Where to continue from: the
next_cursorof the previous page. Omit for the first page.
Returns200 OK
A page of batches.
Responses
- 200
A page of batches.
- 400
The request is invalid.
details.errorslists each problem (validation_failed), or anexpand[]path is unknown (invalid_expand). - 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 403
The credentials are valid but not allowed to do this: a scope is missing (
missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which casedetails.fix_urllinks to the dashboard page that fixes it. - 404
You have no stock with this id (
stock_not_found). - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl "https://public-api.dapi.digital/v2/stocks/stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu/batches" \
-H "x-api-key: $DAPI_API_KEY"{
"object": "list",
"data": [
{
"id": "bat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock_batch",
"stock": {
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack"
},
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"status": "in_production",
"batches": 2,
"units": {
"purchased": 100,
"made": 60,
"used": 20,
"available": 40
},
"price_paid": {
"amount": 60000,
"currency": "usd"
},
"unit_price": {
"amount": 600,
"currency": "usd"
},
"purchase_reference": "ST-8KD2X",
"origin": "manual",
"purchased_at": "2026-09-30T10:00:00Z",
"completed_at": null
}
],
"has_more": false,
"next_cursor": null
}Get a stock batch
GET/
- Credentials
- An API key with the
stocks:readscope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
get_stock_batch
Returns one batch of a stock with its production progress. Designers only.
Path parameters
- idstringRequired
Unique identifier of the stock, prefixed with
stk_. Treat it as an opaque string: store it and compare it, never parse it. - batch_idstringRequired
Unique identifier of the stock batch, prefixed with
bat_. Treat it as an opaque string: store it and compare it, never parse it.
Returns200 OK
The batch. Returns the stock batch object.
Responses
- 200
The batch.
- 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 403
The credentials are valid but not allowed to do this: a scope is missing (
missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which casedetails.fix_urllinks to the dashboard page that fixes it. - 404
You have no such stock, or the batch is not one of its batches (
stock_not_found,stock_batch_not_found). - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl "https://public-api.dapi.digital/v2/stocks/stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu/batches/bat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu" \
-H "x-api-key: $DAPI_API_KEY"{
"id": "bat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock_batch",
"stock": {
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack"
},
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"status": "in_production",
"batches": 2,
"units": {
"purchased": 100,
"made": 60,
"used": 20,
"available": 40
},
"price_paid": {
"amount": 60000,
"currency": "usd"
},
"unit_price": {
"amount": 600,
"currency": "usd"
},
"purchase_reference": "ST-8KD2X",
"origin": "manual",
"purchased_at": "2026-09-30T10:00:00Z",
"completed_at": null
}The stock purchase object
One checkout of stock batches.
Attributes
- objectstring
Names the type of this object. Always
stock_purchase. - purchase_referencestring
Reference shared by every batch bought in this checkout.
- totalobject
What was taken from your wallet.
- batchesarray of StockBatch
The batches bought, one per item.
{
"object": "stock_purchase",
"purchase_reference": "ST-8KD2X",
"total": {
"amount": 60000,
"currency": "usd"
},
"batches": [
{
"id": "bat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock_batch",
"stock": {
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack"
},
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"status": "queued",
"batches": 2,
"units": {
"purchased": 100,
"made": 60,
"used": 20,
"available": 40
},
"price_paid": {
"amount": 60000,
"currency": "usd"
},
"unit_price": {
"amount": 600,
"currency": "usd"
},
"purchase_reference": "ST-8KD2X",
"origin": "manual",
"purchased_at": "2026-09-30T10:00:00Z",
"completed_at": null
}
]
}Buy stock batches
POST/
- Credentials
- An API key with the
stocks:writescope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
create_stock_purchase
Buys batches of one or more approved stocks in one checkout, paid from your wallet. There is no card top-up: if the balance is short, nothing is bought. Each item becomes a batch that the production partner of its region makes. Auto-reorder buys from the same wallet: when a region reaches its restock threshold and auto-reorder is on in your wallet settings, batches are bought automatically (origin: auto_reorder), so keep enough balance for both. Your plan must include prepaid stock. Designers only.
Headers
- Idempotency-Keystring
Any unique string, for example a UUID. Sending the same request again with the same key within 24 hours returns the first response without doing anything twice. Reusing a key with a different body is refused with
idempotency_key_reused. A refused request (4xx) frees the key so you can correct and resend it; a server error (5xx) is kept and returned again, because the write may already have happened: check the resource before retrying with a new key.
Request body
- itemsarray of objectRequired
What to buy. Each stock and region pair at most once.
Returns201 Created
The purchase and the batches bought. Returns the stock purchase object.
Responses
- 201
The purchase and the batches bought.
- 400
The request is invalid.
details.errorslists each problem (validation_failed), or anexpand[]path is unknown (invalid_expand). - 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 402
Your wallet balance does not cover the purchase (
insufficient_balance);details.requiredis the amount needed anddetails.balancewhat the wallet holds. Nothing was bought. - 403
Your plan does not include prepaid stock (
plan_limit_reached);details.fix_urlpoints at upgrading. - 409
A stock is not approved and priced (
stock_not_approved);details.itemslists the positions concerned. - 422
A stock is not one of yours (
stock_not_found), a region is not one of the stock regions (region_not_available), or a stock and region pair appears twice (duplicate_item);details.itemslists the positions concerned. - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user), plus 60 per minute per API key (or signed-in user) for quote, upload, order and payment operations. Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl -X POST "https://public-api.dapi.digital/v2/stock-purchases" \
-H "x-api-key: $DAPI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"stock": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"region": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"batches": 2
}
]
}'{
"object": "stock_purchase",
"purchase_reference": "ST-8KD2X",
"total": {
"amount": 60000,
"currency": "usd"
},
"batches": [
{
"id": "bat_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock_batch",
"stock": {
"id": "stk_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "stock",
"name": "Clicker 50 pack"
},
"region": {
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe"
},
"status": "queued",
"batches": 2,
"units": {
"purchased": 100,
"made": 60,
"used": 20,
"available": 40
},
"price_paid": {
"amount": 60000,
"currency": "usd"
},
"unit_price": {
"amount": 600,
"currency": "usd"
},
"purchase_reference": "ST-8KD2X",
"origin": "manual",
"purchased_at": "2026-09-30T10:00:00Z",
"completed_at": null
}
]
}The region object
A production region your stock is held in, and the countries it ships to. Orders use stock from a region that ships to the buyer.
Attributes
- idstring
Unique identifier of the region, prefixed with
reg_. Treat it as an opaque string: store it and compare it, never parse it. - objectstring
Names the type of this object. Always
region. - namestring
Display name, as set by the production partner.
- countriesarray of string
Countries orders can ship to from this region.
{
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe",
"countries": [
"DE",
"FR",
"NL"
]
}Get a production region
GET/
- Credentials
- An API key with the
stocks:readscope (full access includes every scope). A signed-in dashboard session works too. - For
- Designers
- Operation id
get_region
Returns a region one of your stocks is produced in, with the countries it ships to. Only regions of your own stocks are available. Designers only.
Path parameters
- idstringRequired
Unique identifier of the region, prefixed with
reg_. Treat it as an opaque string: store it and compare it, never parse it.
Returns200 OK
The region. Returns the region object.
Responses
- 200
The region.
- 401
Credentials are missing (
missing_credentials), the API key is unknown or inactive (invalid_api_key), the session expired (invalid_session), or both a key and a session were sent (ambiguous_credentials). - 403
The credentials are valid but not allowed to do this: a scope is missing (
missing_scope), the endpoint is for another kind of account (actor_not_allowed) or another kind of credential (credential_not_allowed), the account may no longer use the API (account_blacklisted), or the account must change something first, in which casedetails.fix_urllinks to the dashboard page that fixes it. - 404
None of your stocks is produced in this region (
region_not_found). - 429
Too many requests (
rate_limited): the limit is 500 per minute per API key (or signed-in user). Wait for the number of seconds in theRetry-Afterheader, then retry;detailshaslimit,window_seconds,reset_atandretry_after_seconds.
Errors use the error object.
curl "https://public-api.dapi.digital/v2/regions/reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu" \
-H "x-api-key: $DAPI_API_KEY"{
"id": "reg_bfP0GSqKoZFrD72H5Os0rc7HV9XP6eQJu",
"object": "region",
"name": "Western Europe",
"countries": [
"DE",
"FR",
"NL"
]
}