Requests
Overview¶
A request is everything Posting needs to make an HTTP call: the method and URL, headers, query and path parameters, a body, authentication and a few options. You edit a request in the Request panel, send it with Ctrl+J, and save it into your collection with Ctrl+S.
Creating a request¶
Press Ctrl+N to open a new, empty request in a tab of its own. Choose a method with Ctrl+T
(or press a method's letter while the method selector has focus: G GET, P POST,
U PUT, A PATCH, D DELETE, H HEAD, O OPTIONS), and type a URL.
You don't need to type https:// or http://: a URL without a scheme is sent over http://.
A new request isn't written to disk until you save it.
Editing a request¶
The Request panel has seven tabs. Jump to any of them with Ctrl+O followed by Q W E R T Y U, or move along the tabs with Left and Right and press Down to move into one.
Type $ in the URL bar, a header, query or form value, the auth fields, the proxy URL or the body
to see the variables you can use.
See Environments for how variables work.
Headers¶
Headers are edited in a table. Type into the empty row at the bottom to add a header, and another empty row appears beneath it. As you type a header's name, Posting suggests common header names.
| Key | Action |
|---|---|
| Up / Down | Move between rows |
| Ctrl+R | Enable or disable the row |
| Ctrl+X | Delete the row |
You can also click the checkbox at the start of a row to enable or disable it, or the ✕ at its
end to delete it. A disabled row stays in the request, and is saved with it, but isn't sent.
The Query and form tables work the same way. The Path table only has values to fill in: its rows
come from the URL (see Path).
Body¶
Choose the kind of body with the selector at the top of the tab (Left and Right change it):
- None sends no body.
- Raw sends the text you type. Choose its content type beside it: JSON, Text, XML or
HTML. The text is syntax highlighted, and Posting sends the matching
Content-Typeheader, unless you've set aContent-Typeheader yourself. - Form sends URL-encoded form fields (
application/x-www-form-urlencoded), edited in a table. - Multipart sends an ordered mixture of text and file parts (
multipart/form-data). - File sends a file's bytes as the entire body, without multipart framing, for example for a PUT upload.
Press F4 in the body to edit it in your own editor, or F3 to view it in your pager. See External Tools.
Multipart and file uploads¶
In Multipart, select a part in the list to edit its details beside it. On a narrow pane,
Enter opens the details full-width and Esc returns to the list. Choose + Add part
or press Ins to add one. Use Ctrl+R to enable or disable the selected part,
Ctrl+X to delete it, and Alt+Up / Alt+Down to reorder it. Disabled parts are saved but
not sent. Repeated names are kept: to send several files as attachments, add a part for each
file with that name.
A Text part has a multiline value and an optional content type, for example
application/json for metadata. F4 and F3 work in its value. A File part has a path,
an optional filename override, and an optional content type. With no overrides, Posting sends
the basename as the filename and infers the content type from the extension, falling back to
application/octet-stream. Switching part types or body modes keeps drafts in the open tab;
only the selected body mode and part type are written to YAML.
Paths are relative to the collection root, including for unsaved requests, or absolute. They refer to files on the machine running Posting: over SSH, these are files on the remote host. Type a path to see directory and file completions, then press Enter to accept one. Suggestions use up to 512 entries in each directory; you can always type an exact path. F5 in the path refreshes its metadata. Posting supports regular files, including empty files, not directories, devices, stdin or glob patterns.
Substitute body variables applies to part names, text values, paths, filenames and content types. It never changes file contents. Importing and saving store references, not file bytes. Each send reads the current files, so re-sending a history entry is not a replay of historical file contents. Keep shared fixtures in the collection, or use variables for machine-specific paths.
Posting checks every enabled file before connecting. It streams uploads, shows byte progress, then waits for the response. Esc cancels the request. Redirects and Digest authentication can resend the body; if a file's identity, size or modification time changed, Posting stops and asks you to send again. The request timeout includes uploading, so increase it for large files.
Posting generates the multipart boundary and its Content-Type. Leave that header unset, or
use bare multipart/form-data; a different type or a manually supplied boundary is an error.
For example:
body:
multipart:
- name: title
value: ${TITLE}
- name: document
file: fixtures/report.pdf
- name: metadata
value: '{"team":"finance"}'
content_type: application/json
For a whole-file body, use body: {file: fixtures/report.pdf} with an optional content_type.
Each multipart part has exactly one of value or file, plus optional filename, content_type
and enabled: false. Multipart and file bodies require Posting 3; older versions cannot preserve them.
Path¶
Path parameters are placeholders in the URL's path, written as :name:
https://api.example.com/users/:id/comments/:commentId
Each placeholder you type in the URL gets a row in the Path tab, where you fill in its value. The rows come from the URL, so you add or remove them by editing the URL. Values are inserted into the URL when the request is sent. A placeholder with an empty value is sent as it is.
Values can contain variables, such as $USER_ID.
To send a literal :name in a path, double the colon: ::name is sent as :name.
Query¶
The Query tab lists the query string's parameters, and it's kept in step with the URL.
Type ?page=2&per_page=50 at the end of the URL and two rows appear in the Query tab; add, change
or remove rows and the URL updates to match.
A disabled row is kept in the Query tab but removed from the URL, so it isn't sent.
Auth¶
Choose how the request authenticates:
- None sends no credentials.
- Basic sends a username and password with HTTP Basic authentication.
- Digest answers the server's Digest challenge with a username and password.
- Bearer token sends
Authorization: Bearer <token>. - OAuth 2.0 obtains and refreshes a bearer token using authorization code with PKCE or client credentials.
The Authorization header is created when the request is sent, and replaces any Authorization
header you've added yourself (for Digest auth, once the server has sent its challenge). Credentials can use variables, for example ${API_TOKEN}, so you can
keep secrets out of your request files.
OAuth 2.0¶
Choose OAuth 2.0 in Auth, then choose a grant:
- Code + PKCE signs in through your browser. Enter the provider's Auth URL, Token URL,
Client ID, and space-separated Scopes. Public clients leave Client secret empty.
Register
http://127.0.0.1:8765/oauth/callbackas a redirect URI with the provider, or enter another HTTP loopback IP, port and path in Redirect URI. Posting uses S256 PKCE and checks the callback's state. Request the provider's offline-access scope, oftenoffline_access, if needed to receive a refresh token. - Client credentials authenticates an application without a browser. Enter the Token URL, Client ID, Client secret and any Scopes the provider requires.
Client auth chooses how Posting sends client credentials to the token endpoint: Body
(client_secret_post, the default) or Basic header (client_secret_basic). Public PKCE
clients use Body with no secret. Follow your provider's client registration settings.
Press Ctrl+J to authorize and send. A code grant opens the browser and waits up to three
minutes; Esc cancels it. The browser must be able to reach the callback on the machine
running Posting. When using SSH or a container, forward the callback port if the browser is on
another machine. Port 0 selects an available port, for providers that permit variable loopback
ports. The API request's timeout starts after authorization finishes.
Posting reuses tokens and refreshes them shortly before expiry, on the next send. It keeps a
rotated refresh token when the provider returns one. Client credentials grants obtain a new token
instead. A revoked or expired refresh token needs a new login: choose Forget OAuth token in
the command palette, then send again. Forgetting removes the token for the current configuration
from memory and the credential store; it doesn't revoke consent at the provider. Posting doesn't
automatically replay API requests that return 401.
Tokens are saved in the OS credential store: macOS Keychain, Windows Credential Manager, or a Linux Secret Service such as GNOME Keyring. On Linux this requires an available, unlocked store on the session D-Bus. If the store is unavailable, Posting warns in Auth and keeps the token in memory for this session only; it never falls back to a plaintext token file. Tokens are scoped to the collection, API origin and resolved OAuth configuration, so changing credentials or scopes doesn't reuse another configuration's token.
Use variables such as ${CLIENT_SECRET} for secrets. Literal client credentials are saved in
request YAML, just like Basic auth credentials. Generated access and refresh tokens aren't
written to request files, request history configurations, or YAML exports. API responses are
still recorded normally, so don't use an endpoint that echoes credentials if you want them kept
out of response history. OAuth requests can't be exported as curl or grpcurl commands.
OAuth endpoints and HTTP API requests require HTTPS, except HTTP on loopback for local testing. Token requests use the request's proxy and SSL verification settings and the configured CA/client certificates. Token endpoint redirects aren't followed, and API redirects to a different origin don't receive the OAuth token. OAuth also works with GraphQL and TLS gRPC calls. gRPC reflection can reuse or refresh credentials but doesn't open a browser; send once to sign in first.
A saved OAuth request looks like this:
url: https://api.example.com/me
auth:
type: oauth2
oauth2:
grant_type: authorization_code
authorization_url: https://identity.example.com/authorize
token_url: https://identity.example.com/token
client_id: ${CLIENT_ID}
scope: openid profile offline_access
redirect_uri: http://127.0.0.1:8765/oauth/callback
client_auth: client_secret_post
For client credentials, use grant_type: client_credentials, add client_secret: ${CLIENT_SECRET},
and omit authorization_url and redirect_uri. Edit OAuth requests only in Posting 3; Posting 2
doesn't understand this auth type.
Info¶
The request's Name and Description, and the File it's saved in.
The name is shown in the request tabs and the collection browser. The description is shown when you
hover over the request in the collection browser, and supports code in backticks.
Options¶
| Option | Default | Description |
|---|---|---|
| Follow redirects | On | Follow 3xx responses to their destination, stopping with an error after 10 requests in a chain. When it's off, you see the redirect response itself. |
| Verify SSL certificates | On | Reject servers whose certificates can't be verified. Turn it off for servers with self-signed certificates. See also Configuring SSL. |
| Attach cookies | On | Send cookies set by earlier responses, and remember cookies from this one. Cookies are kept until you quit Posting, and are shared by all tabs. |
| Substitute body variables | On | Replace variables in the body. Turn this off to send a body that contains literal $ signs, such as a JSON schema or a GraphQL query. Variables in the URL, headers and auth are still replaced. |
| Proxy URL | Empty | Send the request through this proxy, e.g. http://proxy.example.com:8080. When it's empty, the standard HTTP_PROXY, HTTPS_PROXY and NO_PROXY environment variables apply. |
| Timeout | 5 | How many seconds to wait for the whole request, including redirects and reading the response. |
GraphQL requests¶
To make a GraphQL request, open the method selector with Ctrl+T and choose GraphQL, or press
Q while the method selector has focus. The selector shows GraphQL, and the collection browser,
request tabs and history show a GQL badge where an HTTP request shows its method. Choose a method
to turn it back into an HTTP request. The URL, headers, auth and options stay as they are when you
switch, and so does the query, so you can switch back and forth without losing anything.
A GraphQL request has two tabs of its own, before the usual ones:
- Query holds the GraphQL document, with syntax highlighting. If the document defines more than one operation, type the name of the one to run in Operation, above the document.
- Variables holds the operation's variables as a JSON object, such as
{"id": "${USER_ID}"}.
The other tabs work as they do for an HTTP request. There's no Body tab, and the URL's query parameters are in the Params tab, because Query is the document. Press F4 in the document or the variables to edit them in your own editor.
Posting sends a GraphQL request as a POST with Content-Type: application/json and a JSON body
of query, variables and operationName. Empty variables and an empty operation name are left
out. Unless you've set an Accept header, Posting also sends
Accept: application/graphql-response+json, application/json.
Variables in GraphQL requests¶
In the Variables tab, Posting variables work as they do in a raw body: $NAME and ${NAME} are
both replaced, and typing $ suggests the variables you can use.
In the query, only ${NAME} is replaced. A bare $name there is a GraphQL variable, so
query User($id: ID!) is sent as written, even if your environment defines id.
Turn off Substitute body variables in the Options tab to send the query and the variables exactly as written.
GraphQL responses¶
GraphQL servers often answer 200 OK when an operation fails, and put the failure in an errors
list in the response body. When a 2xx response has errors, Posting shows its status in the
warning colour, in the URL bar, the response panel and the history, and the response panel counts
the errors, for example 200 1 error.
GraphQL request files¶
A saved GraphQL request has kind: graphql and a graphql section instead of a method and a body:
name: Get user
kind: graphql
url: ${BASE_URL}/graphql
graphql:
query: |
query User($id: ID!) {
user(id: $id) {
name
email
}
}
variables: |
{"id": "${USER_ID}"}
operation_name: User
auth:
type: bearer_token
bearer_token:
token: ${API_TOKEN}
Posting 2 doesn't know about GraphQL requests. It opens them as a GET of the URL with no body, and
saving one in Posting 2 removes kind and the graphql section, which loses the query. Edit
GraphQL requests only in Posting 3.
WebSocket requests¶
Choose WebSocket in the method selector (Ctrl+T, then W). Enter a ws:// or wss://
URL and press Connect or Ctrl+J. Connecting does not send the draft in the Message
tab. Once connected, Send or Ctrl+J sends that draft as one message. Edit it and send again
as often as needed, including empty messages. Enable Binary (base64) to send base64-decoded
bytes instead of UTF-8 text.
The Messages response tab shows sent and received messages with timestamps. JSON messages use the existing text and JSON tree inspectors; binary messages are shown as base64. New messages appear without keyboard or mouse activity. Select an older message to pause following while new messages accumulate; F resumes following. Enter opens the full inspector and Esc returns to the log without disconnecting.
Press Alt+J or choose Disconnect WebSocket to disconnect. Esc from the log also disconnects. The log, handshake headers, close code and reason remain available in history. Unsent queued messages are discarded on disconnect. Reconnection is explicit and never replays messages. The request timeout bounds connecting and each write; it does not end an established interactive connection. A caller's deadline still applies.
Headers, query/path parameters, Basic/Bearer/OAuth authentication, cookies, proxy and TLS settings
apply to the upgrade handshake. To offer subprotocols, add a Sec-WebSocket-Protocol header.
OAuth requires wss:// except on loopback. Ping frames receive automatic pong replies. Redirects,
Digest authentication, per-message compression and automatic reconnect are not supported.
Messages are limited to 1 MiB; the connection stops when the retained log reaches 10,000 entries
or 64 MiB of payloads, preserving the log and explaining the limit.
Saved requests use kind: websocket:
name: Deployment updates
kind: websocket
url: wss://api.example.com/events
websocket:
message: '{"subscribe":"deployments"}'
binary: false
Edit these files only in Posting 3. Export as YAML is supported; command export is not.
See headless WebSocket runs for the different send/timeout behavior
of posting run.
gRPC requests¶
To make a gRPC request, open the method selector with Ctrl+T and choose gRPC, or press
R while the method selector has focus. The selector shows gRPC, and the collection browser,
request tabs and history show an RPC badge where an HTTP request shows its method. Choose a
method to turn it back into an HTTP request. The address, metadata, auth and options stay as they
are when you switch, and so do the gRPC method and message.
The server's address¶
Type the server's address in the URL bar, for example localhost:50051. The address is a host and
a port, with no path. The method goes in the Method field. The address's scheme decides whether
Posting connects with TLS:
| Address | Connection |
|---|---|
grpc://host:port or http://host:port |
Plaintext |
grpcs://host:port or https://host:port |
TLS |
localhost:50051, 127.0.0.1:50051 or [::1]:50051 |
Plaintext, because the host is a loopback address |
0.0.0.0:50051 or [::]:50051 |
Plaintext, because a server that prints this address is listening on this machine |
Any other address without a scheme, such as api.example.com:8443 |
TLS |
unix:///run/app.sock or unix:app.sock |
Plaintext, over the Unix socket at that path. A relative path is relative to the directory you started Posting in |
Without a port, TLS uses port 443 and plaintext uses port 80. If a TLS connection fails because the
server only speaks plaintext, the error suggests grpc://. If a plaintext connection fails because
the server wants TLS, the error suggests grpcs://.
Verify SSL certificates in the Options tab, and the SSL settings in your configuration, apply as they do to HTTP requests.
The call names the address's host in its :authority header, and over TLS, checks that the
server's certificate has that name. A call to a Unix socket names localhost. To use another name,
type it in Authority on the Options tab. Use it when you connect through an IP address, a
port forward or a load balancer, and the server or its certificate expects its own name.
Authority takes variables.
The Message and Proto tabs¶
A gRPC request has two tabs of its own, before the usual ones:
- Message has the Method field, and the message to send below it.
- Proto lists the
.protofiles that describe the server, for servers that don't offer reflection. Leave it empty to ask the server.
The other tabs work as they do for an HTTP request, with these differences:
- There's no Body, Path or Query tab.
- The Headers tab is called Metadata. Each enabled row is sent as gRPC metadata, with its
name in lower case. A name that ends in
-bintakes a base64 value, which Posting decodes before sending. Names that gRPC sets itself (content-type,te, and names that start withgrpc-or:) are errors, and so are HTTP/1 headers that HTTP/2 forbids (connection,keep-alive,proxy-connection,transfer-encoding,upgradeandhost). Auser-agentrow replaces Posting's own user agent, and gRPC adds its version after it. - Basic and bearer auth are sent as
authorizationmetadata. Digest auth needs an HTTP challenge, so the Auth tab doesn't offer it, and a request file withtype: digestdoesn't load. - The Options tab has Verify SSL certificates, Substitute body variables, Authority and Timeout. The timeout is the deadline for the whole call, including connecting. An open stream uses it only for connecting.
Finding methods¶
Posting contacts a server only when you ask it to. Opening a gRPC request, or showing its tabs, never contacts the server.
When the Proto tab is empty, Posting asks the server's reflection service for its methods. It asks when:
- The Method field takes focus. Posting asks again only if the address, the metadata or the auth has changed since it last asked, or if that attempt failed.
- You press Ctrl+R in the Method field, or choose Refresh gRPC methods in the command palette.
- A send of the request gets a response.
When the server has no reflection service, add its .proto files on the Proto tab instead:
- Files lists the files, one per line, relative to the collection directory. A file ending in
.protoset,.binpbor.pbis a compiled descriptor set, such asprotoc --descriptor_set_outorbuf build -owrites. Any other file is.protosource, which Posting compiles itself, so you don't needprotoc. - Import paths lists the directories that
importstatements are relative to. With none, the collection directory is the only one. Each.protofile must be inside one of them.
With proto files, Posting lists the methods without connecting to the server, so it lists them as soon as the request opens. It reads the files again each time the Method field takes focus, and on Ctrl+R or Refresh gRPC methods, so an edited file is picked up.
The line under the Method field shows how many methods Posting found, and where, for example
4 methods via reflection · plaintext. Once you choose a method, it shows the method's kind and its
message types, such as server stream · ListBooksRequest → Book. If Posting couldn't find the
methods, the line says why. Before Posting has asked the server, the line says so.
The Method field lists the methods while it has focus, and opens the list when they arrive.
Type to filter them, and press Enter to choose one. You can also type a method yourself as
package.Service/Method or package.Service.Method.
Messages and streams¶
Write the message as JSON, in protobuf's JSON format: field names in lowerCamelCase or as they're
written in the .proto file, enum values by name, and well-known types such as Timestamp in their
JSON form. When you choose a method and the message is empty, or still holds the previous method's
template, Posting fills it in with a template that has every field of the method's input. Choose
Insert gRPC message template in the command palette to replace the message with a template at
any time.
What you write depends on the method:
- A unary or server-streaming method takes one JSON object.
- A client-streaming or bidirectional method takes a JSON array of objects, and Posting sends each one as a message, in order. A single object is sent as a stream of one message.
- An empty message is sent as one empty message, for any method.
Variables work as they do in a raw body: $NAME and ${NAME} are both replaced, and typing $
suggests the variables you can use. Turn off Substitute body variables to send the message
exactly as written. Press F4 in the message to edit it in your own editor.
When you press Ctrl+J, Posting sends every message and closes its side of the call while it
reads the server's replies, so a server that answers each message as it arrives works too. The
response shows each reply as it arrives, with RECEIVING in the response panel's title, until the
call ends.
Open streams¶
To send messages one at a time while a call runs, open a stream instead. Press Alt+J, or choose
Open gRPC stream in the command palette. Posting calls the method, sends the message, and keeps
its side of the call open. The response panel's title shows Streaming. While the stream is open:
- Press Ctrl+J to send the message in the editor. Edit the message between sends to send a different one. For a client-streaming or bidirectional method, a JSON array sends each object as a message. A message that isn't valid for the method shows an error and sends nothing, and the stream stays open.
- Press Alt+J again, or choose End gRPC stream, to close your side of the call. The server then ends the call when it's ready, as a client-streaming server does when it replies.
- Press Esc to stop the call at once.
An open stream has no timeout once it has connected. It runs until you end it, you stop it, or the server ends the call. For a unary or server-streaming method, an open stream sends only its first message, and is useful to watch a server stream for longer than the timeout.
gRPC responses¶
The response panel shows the call's status by name, such as OK or NOT_FOUND, with the server's
status message beside it. Only OK is shown in the success colour.
The Body tab shows the server's messages as JSON, with fields at their default values included:
- An object for a unary or client-streaming method.
- An array for a server-streaming or bidirectional method, even when the server sent one message or none.
- When the call fails and the server sent no messages, an object with the status's
code,messageanddetails. Posting decodes the details whose types it knows, such as thegoogle.rpcerror details. It shows the others as their type URL and base64 value.
The Headers tab shows the response metadata. A gRPC response has a Trailers tab instead of
Cookies. Trailers arrive when the server ends the call, and they start with grpc-status and,
when the server sent one, grpc-message. A call that ends without the server's trailers, such as
one that times out, has none.
When a call runs past its timeout, the response shows the messages that arrived before the deadline,
with the status DEADLINE_EXCEEDED. When you press Esc after the server has answered, the
response keeps the messages that arrived, with the status CANCELLED. When Posting can't reach the server, or the server sends
nothing before the deadline, the response panel shows an error, as it does for an HTTP request.
Posting keeps up to 64 MB of messages from a call, the same limit as an HTTP response body. When a
stream sends more, Posting cancels the call. The response shows the messages that arrived before
the limit, with the status CANCELLED and the message response truncated at 64.00 MB.
Each send opens a new connection to the server. Without proto files, it also asks the server for the method's schema again, so a changed server is picked up straight away.
Exporting as grpcurl¶
For a gRPC request, the command palette offers Export as grpcurl in place of Export as curl.
The command uses -plaintext or -insecure to match the connection, -unix for a Unix socket,
-authority for Authority, -cacert, -cert and -key
for the files in your SSL settings when the connection uses
TLS, -H for metadata and auth, -d for the message, -max-time for the timeout, and
-import-path, -proto and -protoset for the proto files, with absolute paths so the command
runs from any directory. Basic and bearer auth replace an authorization metadata row, as they do
when Posting sends the request. If the address still has a variable in it, the command keeps the
address as written. Only a grpc:// or http:// scheme then makes the command -plaintext, so
without a scheme grpcurl uses TLS. grpcurl reads a stream as JSON objects one after another, so an
array message is written that way.
gRPC request files¶
A saved gRPC request has kind: grpc and a grpc section instead of a method and a body:
name: Get user
kind: grpc
url: localhost:50051
grpc:
method: acme.users.v1.UserService/GetUser
message: |
{"id": "${USER_ID}"}
proto:
files:
- protos/acme/users/v1/users.proto
import_paths:
- protos
auth:
type: bearer_token
bearer_token:
token: ${API_TOKEN}
headers:
- name: x-tenant
value: core
options:
timeout: 10
Leave out the proto section to use reflection. A gRPC request file can't have method, body,
params or path_params, and its options can't have follow_redirects, attach_cookies or
proxy_url. Any other key in the grpc or proto sections is an error.
Posting 2 doesn't know about gRPC requests. Edit them only in Posting 3.
What gRPC requests don't do yet¶
- gRPC-Web and Connect.
- Compressed messages.
- Proxies.
- Client certificates for a single request. The client certificate in your SSL settings applies to every request.
- Importing gRPC requests from Postman or grpcurl. Bruno gRPC requests can be imported.
- Completing proto file paths.
- Reusing a connection from one send to the next.
Sending a request¶
Press Ctrl+J (or Alt+Enter) from anywhere to send the request in the current tab, or press Enter in the URL bar. Press Esc to cancel it while it's in flight.
Posting sends a User-Agent header identifying itself unless you've set your own.
If the URL's address or path, or an OAuth field, uses a variable that isn't defined, Posting tells you which one
instead of sending the request. An undefined variable anywhere else, including the query string,
is sent as written.
See Responses for what you can do with the response.
Saving a request¶
Press Ctrl+S to save the request in the current tab.
The first time you save a request, Posting asks where to save it:
| Field | Description |
|---|---|
| Name | The request's name. Required. |
| File name | The name of the file, without .posting.yaml. Leave it empty to use one made from the name. |
| Folder | The folder in the collection to save it in, such as users/admin. Leave it empty to save at the top of the collection. Missing folders are created. |
| Description | An optional description. |
Press Enter to save. After that, Ctrl+S saves changes to the same file.
Renaming a request¶
Change the Name in the Info tab and save. The request keeps its file name; to rename or move the file itself, rename or move it on disk and Posting will notice the change.
Duplicating a request¶
Press D with the cursor on a request in the collection browser, or choose Duplicate request
in the command palette, to make a copy. The copy is saved beside the original, with (copy) added
to its name, and opened in a new tab.
To duplicate several requests at once, select them first. Their copies aren't opened. They become the selection instead.
Deleting a request¶
Press Backspace with the cursor on a request in the collection browser, or choose Delete request in the command palette to delete the request in the current tab. Posting asks you to confirm, then deletes the file. With several requests selected, Posting asks once and deletes them all.
If the request is open in a tab, the tab stays open with its contents intact, as an unsaved request, so you can save it again if you change your mind.
Importing curl commands¶
Paste a curl command into the URL bar and Posting turns it into a request, filling in the method,
URL, headers, query parameters, body, authentication and options.
If your terminal doesn't paste the command in one go, type or paste it and press Enter.
A command split over several lines with \ at the end of each line is supported.
You can also:
- choose Import curl command… in the command palette, and paste the command into the dialog; press Ctrl+J to import it
- choose Import curl from clipboard to import the command on your clipboard directly (over SSH, this needs a terminal that lets applications read the clipboard)
Importing replaces everything in the current tab's request except its name and description. The request keeps its file too, so importing into a saved request updates it once you save.
Posting understands the options people most often copy from browsers and API docs, including
-X, -H, -d and its variants, --json, -F, -u, --digest, -b, -A, -e, -k, -L,
-x, -m, -G, -I and --oauth2-bearer. Options that don't affect the request, such as -s,
-v and -o, are ignored. A few things to be aware of:
-Fimports multipart fields, including@path,;filename=and;type=. Use separate-Ffields for multiple files.--form-stringalways imports literal text.--data-binary @pathand--json @pathimport a whole-file body. Files are read when sending, so each send uses the current contents. Relative paths resolve against the collection, not the shell directory the command originally ran in.--jsonsupplies JSON Content-Type and Accept headers unless you set them explicitly. A whole-file body cannot be combined with other data fragments or files. Stdin, nested multipart,<fileparts and custom per-part headers aren't supported.$NAMEin a pasted command isn't expanded: it becomes a Posting variable.
Exporting as curl¶
Choose Export as curl in the command palette to copy the request as a curl command.
The command is copied to your clipboard straight away, and shown in a dialog where you can check it.
The Values / Variables switch at the top of the dialog chooses between a command with variables replaced by their values (the default), ready to run, or one with the variables left in, ready to share. Press Y to copy the command again.
Uploads export as -F / --form-string, or --data-binary @path for a whole file. Resolved file
paths are absolute so the command can run from another directory. Paths with unresolved variables
are kept as written. Curl generates the boundary for multipart uploads; empty multipart bodies
export with explicit framing instead.
To add your own options to every exported command, set curl_export_extra_args in your
configuration:
curl_export_extra_args: "--silent --show-error"
This is inserted straight after curl.
Exporting as YAML¶
Choose Export as YAML in the command palette to copy the request in Posting's file format, a quick way to share a request with another Posting user.
The request file format¶
Requests are saved as YAML files ending in .posting.yaml. They're designed to be easy to read,
review and edit by hand. Here's an example:
name: Create user
description: Adds a new user to the system.
method: POST
url: https://${API_HOST}/users/:team
body:
content: |-
{
"firstName": "John",
"email": "john.doe@example.com"
}
content_type: application/json
auth:
type: bearer_token
bearer_token:
token: ${API_TOKEN}
headers:
- name: X-Request-ID
value: docs-example
- name: X-Debug
value: 'true'
enabled: false
params:
- name: sendWelcomeEmail
value: 'true'
path_params:
- name: team
value: engineering
options:
timeout: 30
Only settings that differ from the defaults are written, so most files are short:
| Key | Description |
|---|---|
name, description |
Shown in the collection browser and the Info tab. |
kind |
graphql for a GraphQL request, grpc for a gRPC request. Left out for an HTTP request. |
method |
The HTTP method. Left out for GET. |
url |
The URL, without its query string. |
headers, params |
Lists of name and value. enabled: false marks a disabled row. |
path_params |
The values of the URL's :name placeholders. |
body |
One of content for a raw body, form_data for a URL-encoded form, multipart for ordered parts, or file for a whole-file body. Raw and file bodies can also specify content_type. |
graphql |
A GraphQL request's query, variables and operation_name. Any other key in it is an error. |
grpc |
A gRPC request's method, message and proto (files and import_paths). Any other key in it is an error. |
auth |
type is basic, digest, bearer_token or oauth2, with configuration under a key of the same name (basic: {username, password}, bearer_token: {token}). See OAuth 2.0 for oauth2 fields. |
options |
Any of follow_redirects, verify_ssl, attach_cookies, substitute_body_variables, proxy_url and timeout. |
captures |
Maps session variable names to JSON response paths, e.g. {SESSION_ID: data.id}. See Response captures. |
scripts |
Posting 2 scripts. Posting 3 keeps them but doesn't run them; see Scripting. |
HTTP requests without OAuth and with none, raw or URL-encoded form bodies use Posting 2's format. OAuth, multipart and file bodies, generated values and response captures require Posting 3.