https://api.decisionnode.com /v1/uploadsAn upload takes two calls: this one, which answers with a storage URL per image, and a PUT of the bytes to that URL. Then any key of the workspace can name the image by its upload_id for one hour. For a one-off decision an https url is simpler; uploads are for an image you ask about several times, for large images, and for the images of a fine-tuning dataset. An uploaded image does not count toward a request's 25 MB body limit; the same image inline as base64 does.
MD5=$(openssl md5 -binary receipt.jpg | base64)
SIZE=$(wc -c < receipt.jpg | tr -d ' ')
curl https://api.decisionnode.com/v1/uploads \
-H "Authorization: Bearer $DECISIONNODE_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"files\": [{\"content_type\": \"image/jpeg\", \"byte_size\": $SIZE, \"checksum\": \"$MD5\"}]}"
# then PUT the bytes to the returned url with exactly the returned headers:
curl -X PUT "$URL" --data-binary @receipt.jpg \
-H "Content-Type: image/jpeg" -H "Content-MD5: $MD5" -H "If-None-Match: *"Headers#
AuthorizationstringrequiredBearer dn_live_....Content-Typestringrequiredapplication/json; the body is at most 64 KiB.
Request body#
filesarrayrequired- 1 to 16 images. All are checked before anything is stored: one bad file refuses the call.
content_typestringrequiredimage/jpeg,image/pngorimage/webp, exactly, lower case.byte_sizeintegerrequired- The file's size in bytes, 1 to 10,485,760 (10 MB).
checksumstringrequired- The file's MD5, base64 encoded: 24 characters. The storage refuses bytes that do not match it.
sha256string- The file's SHA-256, base64 encoded: 44 characters. When given, the storage checks it too, and a repeated request naming this upload can be answered from the cache of repeated requests; without it, such a request is never cached. The official SDKs always send it.
Response body#
uploadsarray- One entry per file, in request order.
upload_idstringupl_and 32 hex digits. Name the image by it.urlstring- Where to
PUTthe bytes. Send it as given; never build or edit one. methodstring- Always
PUT. headersobject- The headers the
PUTmust carry, exactly:Content-Type,Content-MD5,If-None-Match: *, and the SHA-256 header when you sentsha256. expires_atstring- When the
upload_idstops working: one hour from now, UTC.
expires_ininteger- Seconds the URLs accept the
PUT: 300.
{ "files": [ { "content_type": "image/jpeg", "byte_size": 482113, "checksum": "rL0Y20zC+Fzt72VPzMSk2A==" } ]}The PUT#
- Within 5 minutes, send the file's bytes to
urlwith exactly theheadersgiven. Your API key never goes to that URL. - The bytes are checked: a size or an MD5 that differs from what you declared is refused, and the object is written once: a second
PUTto the same URL is refused. A retry that is refused because the first attempt landed is a success. - After the 5 minutes, call
/v1/uploadsagain for a new URL.
Naming an upload#
{
"images": [
{ "id": "receipt", "upload_id": "upl_3f6c1a9e0b2d4c7f8a1e5d9b2c4f6a80" }
]
}- One of
data,urlandupload_idper image;media_typeis optional and must match the upload when given. - Anywhere an image goes:
/v1/decide, batch lines, a session frame'simage, and fine-tuning records. The image counts toward the 16 images of a request like any other and is billed as the same image sent asdata. - Any key of the workspace, for one hour from this call, as many times as you like. A batch holds its uploads until it ends, and a validated fine-tuning dataset holds its uploads for the dataset's life.
- Zero retention: in a workspace with zero retention an upload is deleted right after the first decision that used it.
Errors#
| Status | Type | When |
|---|---|---|
400 | api_usage_error | A body that is not a JSON object, or a file outside the rules above; the message names the file and the field |
401 | authentication_error | The key is missing, unknown or revoked |
402 | insufficient_credit | The balance is empty: a workspace that may not decide may not upload |
403 | workspace_suspended | The workspace is paused |
413 | request_too_large_error | A body over 64 KiB |
429 | rate_limit_error | Over your key's request rate: each call counts as one request of zero tokens |
529 | overloaded_error | Storage is busy; wait Retry-After |
| Type | When |
|---|---|
upload_not_found | The id is unknown, malformed or another workspace's |
upload_expired | More than an hour has passed: upload the image again |
upload_consumed | Zero retention: a decision already used it |
upload_incomplete | The bytes were never PUT, or not yet |
upload_mismatch | The stored size differs from what was declared |
upload_media_type_mismatch | A media_type beside the id that differs from the upload's, or bytes that are not of the declared type |
Presigning is free and bills nothing; the image's tokens are billed in the decision that reads it.