Get started

Server-side quickstart

Connect and run from a backend that holds a client secret.

This guide connects a user's Gmail account and reads invoice emails from a backend. A confidential application keeps a client secret on your server and uses it to authenticate the code exchange. It can also tag each connection with your own user id. The public-client quickstart uses PKCE instead of a client secret.

1. Create a confidential application

In the console, create an application with the client type set to confidential. The console shows clientSecret once; store it with your other secrets. You can rotate it later from the application's overview. The previous secret stops working immediately, so update your backend with the new one.

Register the callback URL your backend will handle. The examples use https://app.example/callback; replace it with your registered URL in both the auth link and the code exchange.

Your backend builds the link per request. Generate a fresh state, a random string you'll check when the user returns, store it against the signed-in user, and add external_user_id, your own id for that user. Replace APPLICATION_ID, STATE, and USER_42 with your values. This link asks the user to connect Gmail:

https://connect.trywool.com/v1/oauth/authorize
  ?client_id=APPLICATION_ID
  &redirect_uri=https://app.example/callback
  &response_type=code
  &state=STATE
  &website=mail.google.com
  &external_user_id=USER_42

Send the user to this link. After they approve and sign in, WOOL redirects to your callback with code and state. Check state against the value you stored before accepting the code. If the callback carries error, handle the declined or failed authorization before attempting an exchange.

PKCE (Proof Key for Code Exchange) is optional for confidential applications. If you include its challenge on the link, you must send the matching verifier when exchanging the code; see the PKCE guide.

3. Exchange the code

Use the code from the callback as CODE. Authenticate with HTTP Basic, using the application id as the username and the client secret as the password:

curl -X POST https://api.trywool.com/v1/oauth/token \
  -u "APPLICATION_ID:CLIENT_SECRET" \
  -d grant_type=authorization_code \
  -d code=CODE \
  -d redirect_uri=https://app.example/callback

The response carries access_token for execution requests, connection_id for the connected Gmail account, and user_id for the user within your WOOL application. Store these values against your own user record. The token is long-lived and doesn't refresh.

4. Run and poll

Use the token from the exchange as ACCESS_TOKEN. This run looks for unpaid invoice emails in the connected Gmail inbox. The output_schema asks for invoice numbers and totals as structured data:

curl -X POST https://api.trywool.com/v1/applications/APPLICATION_ID/executions \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "prompt": "List the unpaid invoices in my inbox with their invoice numbers and totals.", "output_schema": { "type": "object", "properties": { "invoices": { "type": "array", "items": { "type": "object", "properties": { "number": { "type": "string" }, "total": { "type": "number" } } } } } } }'

The create response contains execution.id. Use it in GET /v1/applications/{id}/executions/{executionId}, with the same bearer token, and poll every 3 to 5 seconds until status is COMPLETED or FAILED. With an output_schema, result.extracted holds the data in the shape you asked for, and the run completes only when the result matches that shape. On failure, read terminal.status and terminal.reason.

The command generates a new Idempotency-Key each time you run it. If you retry a request after a timeout, reuse its original key and body to avoid creating a second run; see Idempotency.

Next steps

Confidential flow on a server covers several connections per user and the secret. Structured results has the rules for output_schema.