curl --request POST \
--url https://api.ionworks.com/protocols/convert \
--header 'Content-Type: application/json' \
--data '
{
"protocol": {},
"drive_cycles": {},
"filename_stem": "protocol",
"nominal_capacity_ah": 1,
"verify": false
}
'import requests
url = "https://api.ionworks.com/protocols/convert"
payload = {
"protocol": {},
"drive_cycles": {},
"filename_stem": "protocol",
"nominal_capacity_ah": 1,
"verify": False
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
protocol: {},
drive_cycles: {},
filename_stem: 'protocol',
nominal_capacity_ah: 1,
verify: false
})
};
fetch('https://api.ionworks.com/protocols/convert', 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.ionworks.com/protocols/convert",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'protocol' => [
],
'drive_cycles' => [
],
'filename_stem' => 'protocol',
'nominal_capacity_ah' => 1,
'verify' => false
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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.ionworks.com/protocols/convert"
payload := strings.NewReader("{\n \"protocol\": {},\n \"drive_cycles\": {},\n \"filename_stem\": \"protocol\",\n \"nominal_capacity_ah\": 1,\n \"verify\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.ionworks.com/protocols/convert")
.header("Content-Type", "application/json")
.body("{\n \"protocol\": {},\n \"drive_cycles\": {},\n \"filename_stem\": \"protocol\",\n \"nominal_capacity_ah\": 1,\n \"verify\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ionworks.com/protocols/convert")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"protocol\": {},\n \"drive_cycles\": {},\n \"filename_stem\": \"protocol\",\n \"nominal_capacity_ah\": 1,\n \"verify\": false\n}"
response = http.request(request)
puts response.read_body{
"target": "<string>",
"primary": {
"filename": "<string>",
"content_base64": "<string>",
"media_type": "<string>"
},
"assets": [
{
"filename": "<string>",
"content_base64": "<string>",
"media_type": "<string>"
}
],
"warnings": [
"<string>"
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Convert Protocol Endpoint
Convert a UCP to a vendor-native protocol file.
The primary artifact is returned as base64-encoded bytes alongside a
suggested filename and media type. Some targets (currently Maccor with
drive cycles) emit additional asset files in assets.
curl --request POST \
--url https://api.ionworks.com/protocols/convert \
--header 'Content-Type: application/json' \
--data '
{
"protocol": {},
"drive_cycles": {},
"filename_stem": "protocol",
"nominal_capacity_ah": 1,
"verify": false
}
'import requests
url = "https://api.ionworks.com/protocols/convert"
payload = {
"protocol": {},
"drive_cycles": {},
"filename_stem": "protocol",
"nominal_capacity_ah": 1,
"verify": False
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
protocol: {},
drive_cycles: {},
filename_stem: 'protocol',
nominal_capacity_ah: 1,
verify: false
})
};
fetch('https://api.ionworks.com/protocols/convert', 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.ionworks.com/protocols/convert",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'protocol' => [
],
'drive_cycles' => [
],
'filename_stem' => 'protocol',
'nominal_capacity_ah' => 1,
'verify' => false
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$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.ionworks.com/protocols/convert"
payload := strings.NewReader("{\n \"protocol\": {},\n \"drive_cycles\": {},\n \"filename_stem\": \"protocol\",\n \"nominal_capacity_ah\": 1,\n \"verify\": false\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.ionworks.com/protocols/convert")
.header("Content-Type", "application/json")
.body("{\n \"protocol\": {},\n \"drive_cycles\": {},\n \"filename_stem\": \"protocol\",\n \"nominal_capacity_ah\": 1,\n \"verify\": false\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ionworks.com/protocols/convert")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"protocol\": {},\n \"drive_cycles\": {},\n \"filename_stem\": \"protocol\",\n \"nominal_capacity_ah\": 1,\n \"verify\": false\n}"
response = http.request(request)
puts response.read_body{
"target": "<string>",
"primary": {
"filename": "<string>",
"content_base64": "<string>",
"media_type": "<string>"
},
"assets": [
{
"filename": "<string>",
"content_base64": "<string>",
"media_type": "<string>"
}
],
"warnings": [
"<string>"
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Body
Request body for converting a UCP to a vendor-native protocol file.
UCP as a dict or YAML string.
Vendor target: 'maccor', 'arbin', 'neware', 'biologic_bttest', or 'novonix'.
maccor, arbin, arbin_sdx, neware, biologic_bttest, novonix Optional mapping of drive cycle name → samples. Required when the protocol references DriveCycle steps.
Stem for the returned primary filename (no extension).
Rated cell capacity in A.h, from the cell specification. Required for 'neware' when the protocol uses C-rate steps or cutoffs: Neware sets current in absolute mA and has no C-rate mode, so the rate cannot be resolved without it. Ignored by other targets, which express C-rate natively.
x > 0Round-trip the emitted file back through its parser and refuse the conversion (400) if the protocol no longer means the same thing. A writer that drops a loop count, a goto, or a safety bound emits a valid file that simulates identically, so the loss would otherwise only show up on hardware. A re-encoding the target format forces — a C-rate resolved to absolute amps on a format with no C-rate type — is allowed. Off by default: the checker still reports two benign round-trip artifacts of Maccor/Arbin/Neware (explicit fall-through gotos and an appended terminal step) as differences, so enabling it by default would refuse most valid conversions to those targets.
Was this page helpful?