# Authoring requests Everything here is a field on the HTTP request model. Run `yaak request schema http --pretty` to see the full, current schema, including the authentication variants contributed by installed plugins. ## Two ways to create Name, method, and URL have flags. Everything else needs JSON: ```bash yaak request create wk_abc123 --name "List Pets" --method GET --url "https://api.example.com/pets" ``` ```bash yaak request create wk_abc123 --json '{ "name": "Create Pet", "method": "POST", "url": "https://api.example.com/pets", "bodyType": "application/json", "body": {"text": "{\"name\":\"Rex\",\"species\":\"dog\"}"}, "headers": [{"name": "Content-Type", "value": "application/json", "enabled": true}] }' ``` Flags and JSON cannot be mixed on the same command. The workspace ID may be omitted when only one workspace exists, and may also be carried inside the payload as `workspaceId`. ## Bodies `bodyType` decides how `body` is encoded onto the wire, and `body` is a free-form object whose shape depends on that type. For text-ish types the content lives in `body.text` as a **string**, so a JSON payload is double-encoded: a JSON string containing JSON. | `bodyType` | `body` | |---|---| | `application/json` | `{"text": "{\"key\":\"value\"}"}` | | `text/xml` | `{"text": ""}` | | `other` | `{"text": "…"}` | | `graphql` | `{"query": "{ pets { id } }", "variables": "{\"n\":1}", "operationName": ""}` | | `application/x-www-form-urlencoded` | `{"form": [{"name":"a","value":"1","enabled":true}]}` | | `multipart/form-data` | `{"form": [{"name":"file","file":"/abs/path","enabled":true}]}` | | `binary` | `{"filePath": "/abs/path"}` | | `null` (omitted) | no body | For `graphql`, note that `variables` is a **string** of JSON, not an object, and that a GraphQL request sent with method `GET` moves query/variables/operationName into the query string and sends no body at all. For `multipart/form-data`, each entry is either a text field (`value`) or a file (`file`, an absolute path), and may carry its own `contentType`. **Add the `Content-Type` header yourself.** In the desktop app, choosing a body type also writes a matching `Content-Type` into the request's headers, so it is stored on the request rather than inferred at send time. Creating a request from the CLI skips that step: `bodyType` alone controls how the body is *encoded*, and nothing adds the header. A JSON body with no `Content-Type` goes out as untyped bytes, which many APIs answer with 400 or 415. ```json "bodyType": "application/json", "body": {"text": "{\"name\":\"Rex\"}"}, "headers": [{"name": "Content-Type", "value": "application/json", "enabled": true}] ``` Use the same value as `bodyType`, with two exceptions the app also makes: `other` pairs with `text/plain`, and `graphql` pairs with `application/json`. Multipart is the one case to leave alone — the sender replaces that header with one carrying the generated boundary. Requests created this way end up identical to app-created ones, which matters because the user will open them in the app afterwards. ## Headers ```json "headers": [ {"name": "Accept", "value": "application/json", "enabled": true}, {"name": "X-Debug", "value": "1", "enabled": false} ] ``` `enabled: false` keeps a header in the app for the user to toggle without sending it. Values accept template variables. ## URL parameters One array covers both query string entries and path placeholders. A parameter fills a path placeholder only when its **name starts with a colon** and matches the placeholder in the URL. Everything else becomes a query string entry: ```json "url": "https://api.example.com/pets/:petId/visits", "urlParameters": [ {"name": ":petId", "value": "42", "enabled": true}, {"name": "limit", "value": "10", "enabled": true} ] ``` That sends `https://api.example.com/pets/42/visits?limit=10` — `:petId` is substituted into the path and dropped from the query string, `limit` is not. This is the single easiest thing to get wrong here, and it fails **silently**. Naming the parameter `petId` instead of `:petId` leaves `/pets/:petId/visits` in the path as literal text and appends `?petId=42`, which most servers answer with a 404. Always include the colon, and confirm with `yaak -v request send ` that the `> GET …` line shows a substituted path. ## Authentication `authenticationType` names a strategy and `authentication` holds its values. The strategy names are not always what you would guess — the built-ins are `basic`, `bearer`, `apikey`, `jwt`, `oauth1`, `oauth2`, `awsv4` (not "aws"), and `windows` (not "ntlm"). Installed plugins can add more. ```json "authenticationType": "bearer", "authentication": {"token": "${[ api_token ]}"} ``` ```json "authenticationType": "basic", "authentication": {"username": "admin", "password": "${[ admin_password ]}"} ``` ```json "authenticationType": "apikey", "authentication": {"location": "header", "key": "X-Api-Key", "value": "${[ api_key ]}"} ``` The exact fields for each strategy, and which are required, are in the `authentication` property of `yaak request schema http --pretty`, which enumerates every installed strategy as a named variant. Read it rather than guessing — `oauth2` has fifteen fields and `jwt` requires four. Set `authenticationType` to `null` to send no auth and stop inheriting from the parent folder. ## Folders and inheritance Folders are containers *and* a place to put shared configuration. Headers and authentication set on a folder apply to every request inside it, so the common pattern is one folder per API surface holding the auth: ```bash yaak folder create wk_abc123 --name "Admin API" yaak folder update --json '{ "id": "fl_abc123", "authenticationType": "bearer", "authentication": {"token": "${[ admin_token ]}"}, "headers": [{"name": "X-Api-Version", "value": "2024-01-01", "enabled": true}] }' yaak request create wk_abc123 --json '{"name":"List Users","method":"GET","url":"${[ base_url ]}/users","folderId":"fl_abc123"}' ``` The request above sends both the folder's bearer token and its version header without repeating either. A request that sets its own `authenticationType` overrides the folder's. Nest folders by setting a folder's `folderId`. `yaak send ` sends every request in the folder recursively. ## Per-request settings Each `setting*` field is an inherited toggle shaped `{"enabled": bool, "value": …}`, where `enabled` means "override the inherited value" rather than "turn the feature on": ```json "settingFollowRedirects": {"enabled": true, "value": false}, "settingRequestTimeout": {"enabled": true, "value": 5000} ``` Available: `settingFollowRedirects`, `settingRequestTimeout` (ms, `0` for none), `settingValidateCertificates`, `settingSendCookies`, `settingStoreCookies`. ## Updating Updates are JSON merge patches keyed by `id`. Send only what changes: ```bash yaak request update --json '{"id":"rq_abc123","method":"PATCH"}' ``` Arrays are replaced wholesale, not merged — to add one header, read the current list with `yaak request show rq_abc123` and write the full new array back. Setting a key to `null` removes it. ## Ordering `sortPriority` (a float) controls display order in the app sidebar. Leave it at `0` unless the user cares; requests created with the same priority fall back to creation order.