curl --request POST \
--url https://api.vane.xyz/api/auth/refresh \
--cookie refresh_token=const options = {method: 'POST', headers: {cookie: 'refresh_token='}};
fetch('https://api.vane.xyz/api/auth/refresh', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.vane.xyz/api/auth/refresh"
headers = {"cookie": "refresh_token="}
response = requests.post(url, headers=headers)
print(response.text){
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3YzllNjY3OSJ9.example-new-access-token",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3YzllNjY3OSJ9.example-new-refresh-token",
"message": "Token refreshed successfully"
}Refresh tokens
Exchanges a valid refresh token for a new access and refresh token pair once the access token expires (after 15 minutes). Refresh tokens stay valid for 30 days.
The only transport the API recognizes is the HttpOnly refresh_token cookie exactly as set at sign-in. The cookie value is server signed, so it cannot be rebuilt from the JSON refreshToken. A raw JWT in the cookie, an Authorization: Bearer header, or a JSON body all return 401 “Refresh token not found.”; no header or body transport exists. Browsers send the cookie automatically, while non-browser clients must replay the Set-Cookie value verbatim through a cookie jar.
curl --request POST \
--url https://api.vane.xyz/api/auth/refresh \
--cookie refresh_token=const options = {method: 'POST', headers: {cookie: 'refresh_token='}};
fetch('https://api.vane.xyz/api/auth/refresh', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.vane.xyz/api/auth/refresh"
headers = {"cookie": "refresh_token="}
response = requests.post(url, headers=headers)
print(response.text){
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3YzllNjY3OSJ9.example-new-access-token",
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI3YzllNjY3OSJ9.example-new-refresh-token",
"message": "Token refreshed successfully"
}refresh_token cookie replayed exactly as set at sign-in returns 401 “Invalid or expired refresh token.” even seconds after the 201, while the matching access_token still works on GET /auth/me. Until this is fixed, re-run the sign-in flow (GET /auth/siwx/challenge, then POST /auth/siwx/verify) when the 15-minute access token lapses.Authorizations
HttpOnly refresh-token cookie set by POST /auth/siwx/verify (Path=/api/auth, 30 days). The value is a server-signed string rather than the raw refreshToken JWT, so a raw JWT in this cookie, a Bearer header, or a JSON body all return 401 "Refresh token not found.". Browsers attach it on their own; outside a browser, replay the Set-Cookie value verbatim from a cookie jar. Used only by POST /auth/refresh.

