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

API v1 reference

Summary of the API v1 the Android app uses: address, token, language, error codes, session, account, analysis, report and upload routes, and the limits.

Applies to: Console 1.6.0 API v1

API v1 is the interface the Android app uses to talk to the console: sign-in, account, analyses, reports and trace upload. It was built for the app and follows the same rules as the console in the browser. This page summarizes the contract; to send a trace from a script, follow Upload traces through the API.

Address and format

  • Base: https://app.waitscope.com/api/v1, over HTTPS only. The previous address, https://waitscope.io/api/v1, still responds, for apps configured with it.
  • JSON in UTF-8 in both directions, except downloads and the file chunks of an upload. An unknown field in the body is refused with 400.
  • The paths follow the console's, in Portuguese: /analises, /envios, /conta.
  • Instants in RFC 3339 with a time zone, such as 2026-10-17T13:50:48-03:00. Trace times in whole microseconds, in the fields ending in _us, and sizes in bytes. Formatting numbers and dates for display is up to the client.
  • No CORS: the API does not serve a page from another site opened in the browser.

Authentication

Sign-in has the same two steps as the console: the password and then the code from the authenticator app. At the end, the API returns a 43-character token, which goes in every call in the Authorization: Bearer <token> header.

curl -s https://app.waitscope.com/api/v1/sessao \
  -H 'Content-Type: application/json' \
  -d '{"username": "zz-exemplo", "password": "...", "method": "app", "device_name": "zz-script"}'

The response carries "etapa": "codigo" and a desafio (challenge), valid for 10 minutes. Send the challenge with the 6-digit code from the app, or with a recovery code:

curl -s https://app.waitscope.com/api/v1/sessao/codigo \
  -H 'Content-Type: application/json' \
  -d '{"desafio": "...", "codigo": "123456"}'

The response carries the token, its expiry in expira_em and the account data, the same as GET /eu.

  • The token is valid for up to 90 days and expires after 30 days without use. DELETE /sessao ends the token right away.
  • It counts toward the account's limit of simultaneous sessions, together with the browser ones, and appears in My account as “App Android · device”, with the device_name from the sign-in.
  • The console cookie does not work in the API, and the token does not work in the console.
  • method is app, the default, or email, the latter only when the account has a confirmed email and the server sends email. The refusal lists the accepted methods in metodos_disponiveis.
  • An account without two-step verification yet receives "etapa": "cadastro" and a token that only opens the enrollment, for 30 minutes.
  • Until you accept, in the console, the current version of the Terms of Service and the Privacy Policy, every route responds 403 termos_pendentes, except GET /eu and DELETE /sessao.

Language

The messages, the diagnosis, the report cards and the Oracle error catalog come translated by the server. With a token, in the account language, which PUT /conta/idioma changes. Without a token, by the Accept-Language header: pt, en or es, and anything else becomes pt.

Errors

An error comes with the HTTP status and a body like this:

{"erro": {"codigo": "nao_encontrado", "mensagem": "The requested address does not exist."}}

The codigo is stable and lets the program decide what to do; the mensagem comes already translated, to show to the user. Some errors carry fields next to erro: bloqueado_ate, with the Retry-After header, tentativas_restantes and metodos_disponiveis.

Common API v1 error codes
HTTPcodigoWhen
400requisicao_invalidaInvalid JSON, unknown field or value out of range
401sessao_invalidaNo token, or a token that expired, was ended or is of another type
401credenciais_invalidasWrong username or password; the response is the same for a user that does not exist
401codigo_incorretoWrong second-step code; carries tentativas_restantes
403cadastro_pendenteEnrollment token trying another route
403troca_de_senhaExpired or temporary password: only /eu, /conta/senha and DELETE /sessao work
403acesso_vencidoThe account's access period has ended
403admin_cadastro_localAdministrator without a second step signing in over the internet
403admin_so_localAdministrator over the internet, when the server only accepts the administrator on the machine itself
403termos_pendentesThe current version of the terms has not been accepted in the console yet
404nao_encontradoResource that does not exist or belongs to another account
409conflitoThe state does not allow it, such as the report of an analysis that has not finished or an upload already completed
410desafio_expiradoSecond-step challenge expired, already used or replaced by another sign-in
413grande_demaisOver the upload limit
429muitas_tentativasSign-in or code lockout; carries bloqueado_ate
429limiteQueue full, stored analyses at the limit or another upload in progress
503indisponivelService unavailable for a moment, such as the database being down or a failure to write the file
503sem_espacoThe upload would leave the server without its disk space reserve

The account and enrollment routes also use senha_atual_incorreta (401), senha_invalida, metodo_indisponivel, email_indisponivel, email_invalido and codigo_expirado (400).

Routes

All routes require the token, except GET /versao and the sign-in ones. A route with the id of a resource from another account responds 404 nao_encontrado, without confirming that it exists: not even the administrator sees another account's analyses.

Version

Version routes
Method and pathWhat it does
GET /versaoNo token. The server and API versions and, when an app is published, the app's: versao, codigo, minima, sha256, bytes, the download address and the app page address. When the installed codigo is lower than minima, the app asks for the update.
GET /app/apkDownloads the published APK.
curl -s https://app.waitscope.com/api/v1/versao

With the app published, the response carries its version; with no APK published, app comes as null:

{"api":1,"app":{"bytes":...,"codigo":7,"download":"/api/v1/app/apk","minima":...,"pagina":"/app","sha256":"...","versao":"1.2.1"},"servidor":"1.6.0"}

Session

Session routes and second-step enrollment routes
Method and pathWhat it does
POST /sessaoFirst step of the sign-in: username, password, method and device_name, optional, up to 80 characters.
POST /sessao/codigoSecond step: desafio and codigo. Returns the token.
POST /sessao/codigo/reenviarResends the code by email, at most 3 sends, 60 s apart.
DELETE /sessaoEnds the token used in the call.
GET /euThe account data: user, language, deadlines, second step, limits (limits) and pending terms (terms_pending).
GET and POST /duas-etapas/appWith the enrollment token: the key and the QR code for the authenticator app and, afterward, the confirmation with the code, which returns the 10 recovery codes.
POST /duas-etapas/email and /duas-etapas/email/confirmarEnrollment of the code by email, when the server sends email.

Account

Account routes
Method and pathWhat it does
PUT /conta/idiomaChanges the account language: pt, en or es.
GET and PUT /conta/privacidadeThe literal mask: ocultar_textos and ocultar_numeros, on by default. The rule for each one is in Hidden literals in the SQL.
POST /conta/senhaChanges the password (senha_atual, nova, repetir) and ends the other sessions.
GET /conta/aparelhosThe open sessions, from the console and from the app.
DELETE /conta/aparelhos/{id}Ends a session.
POST /conta/aparelhos/encerrar-outrosEnds all the other sessions.
POST /conta/recuperacaoGenerates new recovery codes.
POST /conta/app and /conta/app/confirmarChanges the authenticator app; the current one works until the confirmation.
POST /conta/email and /conta/email/confirmarSets up or changes the second-step email.

Sensitive actions (password, app, email and recovery codes) require senha_atual, with the same lockout as the console for wrong attempts.

Analyses

Analysis routes
Method and pathWhat it does
GET /analises?limite=50&antes=<cursor>Lists the analyses, newest first, 1 to 200 per page (default 50). The proximo field leads to the next page, in antes.
GET /analises/{id}One analysis.
DELETE /analises/{id}Deletes the analysis.
POST /analises/excluirDeletes several, with {"ids": [...]}, up to 200.
GET /analises/mudancas?desde=<instant>The analyses that finished after the instant, up to 500 per query. The agora field is the desde of the next query.

Each analysis carries id, name, status (queued, running, done or error), progress, size_bytes, the dates, response_time_us, the trace type and the error message, already translated. There is no trace download and no reprocessing: the trace does not stay on the server.

curl -s "https://app.waitscope.com/api/v1/analises?limite=20" -H "Authorization: Bearer $TOKEN"

Report

Report routes
Method and pathWhat it does
GET /analises/{id}/relatorioThe report in JSON, with the sections of the console page, the translated texts and the raw numbers.
GET /analises/{id}/relatorio.htmlThe exported HTML, the same as Download HTML.
GET /analises/{id}/comandos/{rank}The detail of a statement, with the plan.
GET /analises/{id}/objetos/{obj}The object page: ready-to-run queries for the database.
GET /analises/{id}/plsql?dono=&nome=&tipo=&linha=Ready-to-run queries for the PL/SQL in the stack of a deadlock.

relatorio and relatorio.html accept ?top=N, from 1 to 300, or ?todos=1, like Statements per list; without them, 10. While the analysis has not finished, or if it finished with an error, the report routes respond 409 conflito. The SQL comes out with the account's literal mask. With either mask option on, the sql_id of the variants (top_variants) comes empty and the sql_ids of the shareable texts comes as []: the sql_id is computed from the text with the values.

Upload

The upload is resumable: the file goes in chunks of up to 8 MiB, one at a time, and after a network drop it continues from where it stopped.

Upload routes
Method and pathWhat it does
POST /enviosOpens the upload, with juntar and the list of arquivos (nome and tamanho). Returns the id, the list that counts and pedaco_max; .trm and empty files are left out.
PUT /envios/{id}/arquivos/{n}Sends a chunk of file n, with Content-Range: bytes ini-fim/total; ini is what has already been received.
GET /envios/{id}How much of each file has arrived, to resume.
POST /envios/{id}/concluirCloses the upload and creates the analyses. Repeating it returns the same result, without creating the analyses again.
DELETE /envios/{id}Cancels the upload and deletes what has arrived.
curl -s https://app.waitscope.com/api/v1/envios \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"juntar": false, "arquivos": [{"nome": "exemplo-10046.trc", "tamanho": 1845}]}'

curl -s -X PUT "https://app.waitscope.com/api/v1/envios/$ENVIO/arquivos/0" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Range: bytes 0-1844/1845" \
  --data-binary @exemplo-10046.trc

The example sends the synthetic trace, of 1,845 bytes, in a single chunk; $ENVIO is the id returned by POST /envios. With "juntar": true, the files become a collection, analyzed as a single trace. The upload belongs to the token that opened it and disappears after 24 hours without a new chunk or when the token's session ends.

Limits

  • Request limit per IP address and progressive sign-in lockout after 5 wrong passwords or codes. Whoever goes over the limit receives 429.
  • The account limits (size per upload, queued analyses and stored analyses) come in GET /eu, in the limits field. Over the size: 413 grande_demais. Queue or stored analyses at the limit: 429 limite.
  • One upload in progress per user, in chunks of up to 8 MiB. A stalled upload disappears in 24 hours.
  • Up to 200 analyses per page in the list, up to 200 ids in a batch delete and up to 500 items per changes query.
  • Token for up to 90 days, or 30 days without use; enrollment token for 30 minutes; second-step challenge for 10 minutes.

Where to go next

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