Skip to content
WaitScope Sign in Request access (by email) Menu

Upload traces through the API

Upload a trace through API v1 with the app token: sign in, open the upload, send chunks of up to 8 MiB, complete it and follow the analysis until the report.

Applies to: Console 1.6.0 API v1

API v1 was built for the Android app: the app uses it to sign in, upload traces and read reports. There is no separate API key: a script signs in as the app, with username, password and the second-step code, and uses the token that the sign-in returns. This page shows the upload path with curl; the full contract, with every field and error code, is in API v1.

Before you start

  • An account with two-step verification through the authenticator app and the terms accepted in the browser. Before acceptance, calls respond 403 termos_pendentes.
  • Signing in through the API counts toward the account limit of concurrent sessions, together with the browser and the app. With a limit of one session, signing in from the script ends the oldest session, such as the browser one.
  • curl, jq and bash on Linux. The examples use GNU stat and dd.

Do not store the password in the script, and keep the token like a password: with it, anyone can open your analyses until the session ends. When you are done, end the session.

Sign in and get the token

  1. Send username and password to receive the second-step challenge:
    BASE=https://app.waitscope.com/api/v1
    DESAFIO=$(curl -sS "$BASE/sessao" \
      -H 'Content-Type: application/json' \
      -d '{"username": "zz-exemplo", "password": "<password>", "method": "app", "device_name": "script"}' |
      jq -r .desafio)
  2. Exchange the challenge and the 6-digit code from the authenticator app for the token:
    TOKEN=$(curl -sS "$BASE/sessao/codigo" \
      -H 'Content-Type: application/json' \
      -d "{\"desafio\": \"$DESAFIO\", \"codigo\": \"123456\"}" |
      jq -r .token)

Result: TOKEN has 43 characters. It is valid for up to 90 days, expires after 30 days without use and appears in My account as App Android · script. The challenge is valid for 10 minutes.

To end the session when you are done:

curl -sS -X DELETE "$BASE/sessao" -H "Authorization: Bearer $TOKEN"

Upload the file

  1. Open the upload with the name and size of each file. With "juntar": true, the files become a single analysis (analyze together):
    ARQ=exemplo-10046.trc
    TAM=$(stat -c %s "$ARQ")
    ENVIO=$(curl -sS "$BASE/envios" \
      -H "Authorization: Bearer $TOKEN" \
      -H 'Content-Type: application/json' \
      -d "{\"juntar\": false, \"arquivos\": [{\"nome\": \"$ARQ\", \"tamanho\": $TAM}]}" |
      jq -r .id)

    Result: the 201 response has the upload id, each file with its position n and what has already arrived in recebido, and pedaco_max, 8388608 bytes (8 MiB).

  2. Send the file in chunks of up to 8 MiB, in order, each with the Content-Range of its range and the total size:
    PEDACO=8388608
    INI=0
    while [ "$INI" -lt "$TAM" ]; do
      FIM=$(( INI + PEDACO - 1 ))
      [ "$FIM" -ge "$TAM" ] && FIM=$(( TAM - 1 ))
      dd if="$ARQ" bs="$PEDACO" skip=$(( INI / PEDACO )) count=1 status=none |
        curl -fsS -X PUT "$BASE/envios/$ENVIO/arquivos/0" \
          -H "Authorization: Bearer $TOKEN" \
          -H 'Content-Type: application/octet-stream' \
          -H "Content-Range: bytes $INI-$FIM/$TAM" \
          --data-binary @- || break
      INI=$(( FIM + 1 ))
    done

    Result: each accepted chunk responds 200 with the new total in recebido.

  3. Complete the upload and keep the analysis id:
    ANALISE=$(curl -sS -X POST "$BASE/envios/$ENVIO/concluir" \
      -H "Authorization: Bearer $TOKEN" |
      jq -r '.analises[0].id // .repetidas[0]')

    Result: the 201 response has the new analyses in analises and, in repetidas, the ids of the ones that already existed with the same content (repeated upload).

If a chunk fails, the loop stops. Ask the server how much has arrived and run only the while again, which continues from that point:

INI=$(curl -sS "$BASE/envios/$ENVIO" -H "Authorization: Bearer $TOKEN" | jq '.arquivos[0].recebido')

Follow the analysis

  1. Ask for the status every few seconds:
    curl -sS "$BASE/analises/$ANALISE" -H "Authorization: Bearer $TOKEN" | jq '{status, progress, error}'

    Result: status goes from queued to running, with the progress in progress, and ends as done or error, with the reason in error.

  2. With done, download the report:
    curl -sS -o relatorio.html "$BASE/analises/$ANALISE/relatorio.html" -H "Authorization: Bearer $TOKEN"

relatorio.html is the same file as Download HTML in the console. The /relatorio route, with no extension, returns the report in JSON, section by section. Before the analysis finishes, or if it ended with an error, both respond 409 conflito.

Cancel and resume

  • DELETE $BASE/envios/$ENVIO cancels the upload and deletes what has arrived.
  • The upload belongs to the token that created it and disappears after 24 hours without a new chunk, or when the token session ends.
  • Repeating concluir returns the same result, without creating the analysis again: you can repeat it after losing the response.

Common problems

Common error responses when uploading through the API
ResponseCauseWhat to do
401 sessao_invalidaToken missing, expired or endedSign in again and use the new token.
403 termos_pendentesTerms not accepted in the current versionOpen the console in the browser and accept them.
409 conflito with recebidoThe chunk does not start where the file stoppedContinue from the byte in recebido.
413 grande_demaisThe total exceeds the per-upload limit, or the chunk exceeds 8 MiBCompress the file or use smaller chunks.
429 limiteQueue full, stored analyses at the limit or another upload from the account in progressWait or delete analyses. With envio in the body, the half-finished upload belongs to this token: resume or cancel it.
503 sem_espacoServer out of disk spaceTry again later and let the administrator know.

Next steps

Updated on 2026-10-29. Report an error on this page