curl --request PUT \
--url https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket} \
--header 'Content-Type: application/pdf' \
--data '<string>'import requests
url = "https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}"
payload = "<string>"
headers = {"Content-Type": "application/pdf"}
response = requests.put(url, data=payload, headers=headers)
print(response.text)const options = {method: 'PUT', headers: {'Content-Type': 'application/pdf'}, body: '<string>'};
fetch('https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => "<string>",
CURLOPT_HTTPHEADER => [
"Content-Type: application/pdf"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}"
payload := strings.NewReader("<string>")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Content-Type", "application/pdf")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}")
.header("Content-Type", "application/pdf")
.body("<string>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Content-Type"] = 'application/pdf'
request.body = "<string>"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {}
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": true,
"message": "Example message",
"code": "NOT_FOUND",
"details": {},
"correlationId": "Example correlationId",
"error": {}
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}Send the file a visitor chose through the upload adapter of a published widget
The second of the two calls the upload adapter’s module makes from the visitor’s browser (the first, the begin-upload operation of callPublicCompositionAdapter, answers with the ticket this route takes). The module sends the file itself, as the body, with its media type as the Content-Type. It is not meant to be called by hand, and it takes no API key.
Address. https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}: the root of the API host, NOT under /v1. A client generated from this description for https://api.widgetic.com/v1 must be given the base address https://api.widgetic.com for the calls of the Public Embed tag.
The ticket. Single-use and valid for ten minutes, given for one file: its name, its media type and its exact size are what the visitor said when the ticket was asked for, after the widget’s owner’s settings (the kinds of file they take, the largest size) were applied. The Content-Type and the Content-Length of this request must be those, and the body must be exactly that many bytes (400 UPLOAD_FILE_CHANGED otherwise). The gateway never believes the type it was told: the first bytes of the file must be a file of that type and one the owner accepts (422 otherwise). A ticket whose file was stored and is sent again is answered with the same file, so a visitor whose connection dropped after the file landed does not store it twice; a ticket whose attempt failed is spent, and the module asks for a new one.
The virus check. Before anything is stored, the file is checked for viruses, wherever it would be kept (Widgetic’s storage or a partner’s own bucket). A file that fails the check is refused with 422 UPLOAD_FILE_UNSAFE and nothing is stored. When the check cannot be done, nothing is stored either, and the answer is the same neutral 503 UPLOAD_UNAVAILABLE as for any other cause the visitor is not told. The ticket of a refused file is spent.
What it stores. The file goes to the widget owner’s storage: Widgetic’s, or the partner’s own bucket for a widget of a customer a partner manages. It counts against the owner’s storage allowance and is filed in the folder the owner chose, as a file sent by a visitor, which the owner’s own file list leaves out. A full allowance, a partner’s storage that cannot be used and a stopped feature are all the same 503 UPLOAD_UNAVAILABLE to a visitor, and the owner is told through a notice.
Who may call. The same rule as the entry route: a permitted Origin header, which is the artifact origin the widget runs from or any website when the owner has not restricted the allowed websites (when the owner has, one of the websites the owner listed, Widgetic’s own sites, the visitor’s own machine or the owner’s own platform). A request without a permitted Origin is 403 ORIGIN_NOT_ALLOWED. A composition that is not served (unpublished, or its owner’s plan does not serve it) is 404, with the codes of the other public embed routes.
Limits. 30 requests a minute for each visitor address and composition and 240 a minute for a composition (429 RATE_LIMITED, with a Retry-After header); at most 10 MB for a file, and only so many files held in memory at once on each gateway process (503 UPLOAD_BUSY, with a Retry-After). A file that does not arrive within two minutes is 408 UPLOAD_TIMEOUT. Every answer but a success closes the connection, so a client that is refused before it has sent the file reads the answer and stops.
curl --request PUT \
--url https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket} \
--header 'Content-Type: application/pdf' \
--data '<string>'import requests
url = "https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}"
payload = "<string>"
headers = {"Content-Type": "application/pdf"}
response = requests.put(url, data=payload, headers=headers)
print(response.text)const options = {method: 'PUT', headers: {'Content-Type': 'application/pdf'}, body: '<string>'};
fetch('https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => "<string>",
CURLOPT_HTTPHEADER => [
"Content-Type: application/pdf"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}"
payload := strings.NewReader("<string>")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Content-Type", "application/pdf")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}")
.header("Content-Type", "application/pdf")
.body("<string>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.widgetic.com/embed/compositions/{compositionId}/adapters/upload/files/{ticket}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Content-Type"] = 'application/pdf'
request.body = "<string>"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {}
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": true,
"message": "Example message",
"code": "NOT_FOUND",
"details": {},
"correlationId": "Example correlationId",
"error": {}
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}{
"success": false,
"error": "Example error",
"code": "Example code",
"correlationId": "Example correlationId"
}Path Parameters
The ticket the begin-upload operation answered with.
20 - 128^[A-Za-z0-9_-]{20,128}$Body
The bytes of the file as they are: no encoding and no form around them.