curl --request POST \
--url https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete \
--header 'Authorization: Bearer <token>'import requests
url = "https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete', 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://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "open",
"expires_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"run": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"test_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "<string>",
"analysis": "pending",
"analysis_error": "<string>"
}
},
"meta": {
"timestamp": "2023-11-07T05:31:56Z",
"projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}Complete an Agent Picks self-run upload
Complete an open upload once every artifact its manifest declares is stored at its declared bytes. The run is recorded as a self-run, completed and awaiting analysis, in its series’ self-run test for the month it started, and its analysis is requested; run.analysis reads analysed once it has an outcome. A retry returns the completed upload without recording the run again. Refusals carry a reason: 404 not_found (no upload, a deleted one or another project’s); 409 artifact_missing (details name the artifact and its declared bytes; upload it, then complete) or artifact_size_mismatch (details name the artifact, its declared bytes and the stored bytes; the bundle changed or was damaged after its manifest was written, and since a stored artifact can’t be replaced the upload expires: create it again once a cleanup sweep, which runs every 15 minutes, has removed its artifacts, no sooner than 2 hours 15 minutes after it was last created or retried, once its artifacts are removed, and upload every artifact), upload_expired (not completed within 24 hours of being created or last retried, or an artifact was stored at the wrong size; create it again once a cleanup sweep, which runs every 15 minutes, has removed its artifacts, no sooner than 2 hours 15 minutes after it was last created or retried, once its artifacts are removed), series_busy (retry); 403 plan_excludes_uploads, project_uploads_off (as for create), analysis_cap_reached (as for create; the upload stays open until its 24 hours end, so complete it again after resets_at or once the plan allows more), forbidden or paused; 400 unknown_category, unknown_request or unknown_stack. The member who created the API key needs project management permission and edit rights on the project; otherwise 403. Not available over MCP. Requires Agent Picks. Takes no body. Requires the agent_picks.run scope.
curl --request POST \
--url https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete \
--header 'Authorization: Bearer <token>'import requests
url = "https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete"
headers = {"Authorization": "Bearer <token>"}
response = requests.post(url, headers=headers)
print(response.text)const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
fetch('https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete', 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://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete"
req, _ := http.NewRequest("POST", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://devtune.ai/api/v2/projects/{projectId}/agent-picks/uploads/{runId}/complete")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "open",
"expires_at": "2023-11-07T05:31:56Z",
"completed_at": "2023-11-07T05:31:56Z",
"run": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"test_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "<string>",
"analysis": "pending",
"analysis_error": "<string>"
}
},
"meta": {
"timestamp": "2023-11-07T05:31:56Z",
"projectId": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}{
"error": "<string>",
"message": "<string>",
"status": 123,
"reason": "<string>",
"details": {}
}Authorizations
API key with dtk_live_ prefix. Obtain it from API Keys in the account sidebar. New keys start with all supported scopes selected for the chosen project, and you can narrow them to specific read/write scopes as needed.
Path Parameters
The project the credential is bound to. Read it from GET /connection.
The run id in the bundle manifest.