> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.walletstech.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.walletstech.com/_mcp/server.

# Refresh a token

POST https://your-endpoint.example.com/refresh
Content-Type: application/json

Trade a valid refresh token for a **new access + refresh token pair**, without re-sending your api key.

This and `/auth` are the only endpoints that do not require a bearer token — the refresh token *is* the credential here, so it is sent in the body rather than the `Authorization` header.

## Refresh tokens rotate

Each call **consumes** the token you present and issues a new one. A refresh token is single-use: once spent, it is dead. Always store the `refreshToken` from the response and discard the one you just sent.

## Replay revokes the whole chain

Presenting an **already-consumed** token is the signature of a stolen one, so the service revokes the entire rotation family — the token you sent, the one that replaced it, and every descendant. Both you and the attacker are forced back to `/auth` with your api key.

In practice this means a refresh token must be **stored durably and refreshed by exactly one process**. Two workers sharing a refresh token will race, one will replay, and both get logged out.

Reference: https://docs.walletstech.com/api-reference/auth/refresh-token

## OpenAPI Specification

```yaml
openapi: 3.1.0
info:
  title: Blockchain Wallet Service
  version: 1.0.0
paths:
  /refresh:
    post:
      operationId: refreshToken
      summary: Refresh a token
      description: >-
        Trade a valid refresh token for a **new access + refresh token pair**,
        without re-sending your api key.


        This and `/auth` are the only endpoints that do not require a bearer
        token — the refresh token *is* the credential here, so it is sent in the
        body rather than the `Authorization` header.


        ## Refresh tokens rotate


        Each call **consumes** the token you present and issues a new one. A
        refresh token is single-use: once spent, it is dead. Always store the
        `refreshToken` from the response and discard the one you just sent.


        ## Replay revokes the whole chain


        Presenting an **already-consumed** token is the signature of a stolen
        one, so the service revokes the entire rotation family — the token you
        sent, the one that replaced it, and every descendant. Both you and the
        attacker are forced back to `/auth` with your api key.


        In practice this means a refresh token must be **stored durably and
        refreshed by exactly one process**. Two workers sharing a refresh token
        will race, one will replay, and both get logged out.
      tags:
        - auth
      parameters:
        - name: X-Request-Id
          in: header
          description: >-
            Correlation id. Generated if omitted, echoed on every response, and
            written to the audit log. **`/send` is the exception — there it is
            required, and it doubles as the idempotency key.**
          required: false
          schema:
            type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TokenPairResponse'
        '401':
          description: >-
            Unauthorized — the refresh token is missing, malformed, expired,
            already consumed, revoked, or its api client has been deactivated.


            Every case is terminal for this token: **call `/auth` with your api
            key**. Retrying the refresh will never succeed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                refreshToken:
                  $ref: '#/components/schemas/RefreshToken'
              required:
                - refreshToken
servers:
  - url: https://your-endpoint.example.com
    description: >-
      Placeholder. Each client is issued its own base URL — there is no shared
      public host. Replace this with the endpoint you were given.
components:
  schemas:
    RefreshToken:
      type: string
      description: >-
        Opaque 64-character hex token. **Single-use** — every `/refresh`
        consumes the token presented and returns a new one.


        It is not a JWT and carries no readable claims. Only a hash of it is
        stored, so it cannot be recovered if lost — a lost refresh token just
        means calling `/auth` again.
      title: RefreshToken
    TokenPairResponseResult:
      type: object
      properties:
        token:
          type: string
          description: >-
            HS256 JWT access token. Present it as `Authorization: Bearer
            <token>` on every endpoint except `/auth` and `/refresh`.
        expiresAt:
          type: string
          format: date-time
          description: Access-token expiry — **15 minutes** after issue.
        refreshToken:
          $ref: '#/components/schemas/RefreshToken'
        refreshExpiresAt:
          type: string
          format: date-time
          description: >-
            Refresh-token expiry — **7 days** after issue. Rotating does not
            extend the window past this.
      required:
        - token
        - expiresAt
        - refreshToken
        - refreshExpiresAt
      title: TokenPairResponseResult
    RequestId:
      type: string
      description: Echo of the inbound `X-Request-Id`, or a generated one.
      title: RequestId
    TokenPairResponse:
      type: object
      properties:
        result:
          $ref: '#/components/schemas/TokenPairResponseResult'
        requestId:
          $ref: '#/components/schemas/RequestId'
      required:
        - result
        - requestId
      description: >-
        An access token for the next 15 minutes, plus the refresh token that
        mints the one after it.
      title: TokenPairResponse
    ErrorResponse:
      type: object
      properties:
        message:
          type: string
          description: Safe, client-facing message. Internal detail never leaks here.
        error:
          type: string
          description: The HTTP status code, as a string.
        requestId:
          $ref: '#/components/schemas/RequestId'
      required:
        - message
        - error
        - requestId
      title: ErrorResponse

```

## Examples



**Request**

```json
{
  "refreshToken": "5d41402abc4b2a76b9719d911017c592a1b2c3d4e5f60718293a4b5c6d7e8f90"
}
```

**Response**

```json
{
  "result": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJjbGllbnRfOWYzYTIiLCJpYXQiOjE3ODQ5NjA5MDAsImV4cCI6MTc4NDk2MTgwMH0.9tR2n1ZR1ZRn1Z4oRc2tL3nW0eS9yUg7vAr1bXd2tQl",
    "expiresAt": "2026-07-13T10:30:00.000Z",
    "refreshToken": "8f14e45fceea167a5a36dedd4bea2543a2b1f7e9c3d0a4b6e8f0c2d4a6b8e0f2",
    "refreshExpiresAt": "2026-07-20T10:15:00.000Z"
  },
  "requestId": "b7a1f0c2-3d4e-4a5b-9c6d-7e8f90a1b2c3"
}
```

**SDK Code**

```python Token pair rotated
import requests

url = "https://your-endpoint.example.com/refresh"

payload = { "refreshToken": "5d41402abc4b2a76b9719d911017c592a1b2c3d4e5f60718293a4b5c6d7e8f90" }
headers = {"Content-Type": "application/json"}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Token pair rotated
const url = 'https://your-endpoint.example.com/refresh';
const options = {
  method: 'POST',
  headers: {'Content-Type': 'application/json'},
  body: '{"refreshToken":"5d41402abc4b2a76b9719d911017c592a1b2c3d4e5f60718293a4b5c6d7e8f90"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Token pair rotated
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://your-endpoint.example.com/refresh"

	payload := strings.NewReader("{\n  \"refreshToken\": \"5d41402abc4b2a76b9719d911017c592a1b2c3d4e5f60718293a4b5c6d7e8f90\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Token pair rotated
require 'uri'
require 'net/http'

url = URI("https://your-endpoint.example.com/refresh")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n  \"refreshToken\": \"5d41402abc4b2a76b9719d911017c592a1b2c3d4e5f60718293a4b5c6d7e8f90\"\n}"

response = http.request(request)
puts response.read_body
```

```java Token pair rotated
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://your-endpoint.example.com/refresh")
  .header("Content-Type", "application/json")
  .body("{\n  \"refreshToken\": \"5d41402abc4b2a76b9719d911017c592a1b2c3d4e5f60718293a4b5c6d7e8f90\"\n}")
  .asString();
```

```php Token pair rotated
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://your-endpoint.example.com/refresh', [
  'body' => '{
  "refreshToken": "5d41402abc4b2a76b9719d911017c592a1b2c3d4e5f60718293a4b5c6d7e8f90"
}',
  'headers' => [
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Token pair rotated
using RestSharp;

var client = new RestClient("https://your-endpoint.example.com/refresh");
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"refreshToken\": \"5d41402abc4b2a76b9719d911017c592a1b2c3d4e5f60718293a4b5c6d7e8f90\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Token pair rotated
import Foundation

let headers = ["Content-Type": "application/json"]
let parameters = ["refreshToken": "5d41402abc4b2a76b9719d911017c592a1b2c3d4e5f60718293a4b5c6d7e8f90"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://your-endpoint.example.com/refresh")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```