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 /sessaoends 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_namefrom the sign-in. - The console cookie does not work in the API, and the token does not work in the console.
methodisapp, the default, oremail, the latter only when the account has a confirmed email and the server sends email. The refusal lists the accepted methods inmetodos_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, exceptGET /euandDELETE /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.
| HTTP | codigo | When |
|---|---|---|
| 400 | requisicao_invalida | Invalid JSON, unknown field or value out of range |
| 401 | sessao_invalida | No token, or a token that expired, was ended or is of another type |
| 401 | credenciais_invalidas | Wrong username or password; the response is the same for a user that does not exist |
| 401 | codigo_incorreto | Wrong second-step code; carries tentativas_restantes |
| 403 | cadastro_pendente | Enrollment token trying another route |
| 403 | troca_de_senha | Expired or temporary password: only /eu, /conta/senha and DELETE /sessao work |
| 403 | acesso_vencido | The account's access period has ended |
| 403 | admin_cadastro_local | Administrator without a second step signing in over the internet |
| 403 | admin_so_local | Administrator over the internet, when the server only accepts the administrator on the machine itself |
| 403 | termos_pendentes | The current version of the terms has not been accepted in the console yet |
| 404 | nao_encontrado | Resource that does not exist or belongs to another account |
| 409 | conflito | The state does not allow it, such as the report of an analysis that has not finished or an upload already completed |
| 410 | desafio_expirado | Second-step challenge expired, already used or replaced by another sign-in |
| 413 | grande_demais | Over the upload limit |
| 429 | muitas_tentativas | Sign-in or code lockout; carries bloqueado_ate |
| 429 | limite | Queue full, stored analyses at the limit or another upload in progress |
| 503 | indisponivel | Service unavailable for a moment, such as the database being down or a failure to write the file |
| 503 | sem_espaco | The 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
| Method and path | What it does |
|---|---|
GET /versao | No 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/apk | Downloads 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
| Method and path | What it does |
|---|---|
POST /sessao | First step of the sign-in: username, password, method and device_name, optional, up to 80 characters. |
POST /sessao/codigo | Second step: desafio and codigo. Returns the token. |
POST /sessao/codigo/reenviar | Resends the code by email, at most 3 sends, 60 s apart. |
DELETE /sessao | Ends the token used in the call. |
GET /eu | The account data: user, language, deadlines, second step, limits (limits) and pending terms (terms_pending). |
GET and POST /duas-etapas/app | With 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/confirmar | Enrollment of the code by email, when the server sends email. |
Account
| Method and path | What it does |
|---|---|
PUT /conta/idioma | Changes the account language: pt, en or es. |
GET and PUT /conta/privacidade | The literal mask: ocultar_textos and ocultar_numeros, on by default. The rule for each one is in Hidden literals in the SQL. |
POST /conta/senha | Changes the password (senha_atual, nova, repetir) and ends the other sessions. |
GET /conta/aparelhos | The open sessions, from the console and from the app. |
DELETE /conta/aparelhos/{id} | Ends a session. |
POST /conta/aparelhos/encerrar-outros | Ends all the other sessions. |
POST /conta/recuperacao | Generates new recovery codes. |
POST /conta/app and /conta/app/confirmar | Changes the authenticator app; the current one works until the confirmation. |
POST /conta/email and /conta/email/confirmar | Sets 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
| Method and path | What 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/excluir | Deletes 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
| Method and path | What it does |
|---|---|
GET /analises/{id}/relatorio | The report in JSON, with the sections of the console page, the translated texts and the raw numbers. |
GET /analises/{id}/relatorio.html | The 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.
| Method and path | What it does |
|---|---|
POST /envios | Opens 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}/concluir | Closes 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 thelimitsfield. Over the size: 413grande_demais. Queue or stored analyses at the limit: 429limite. - 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
- Upload traces through the API: the step-by-step upload from a script.
- Upload traces with the Android app: the app that uses this API.
- Limits and repeated upload: the size limits and what happens to a file uploaded again.
- Data retention, deletion and privacy: what is stored and who sees it.