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

# Reveal manual connection credentials

GET https://api.modulards.com/api/public/v1/sites/{site_id}/connection/manual/reveal

Delivers the OAuth client secret for a website's manual connection - the only response on this surface that reveals it. Never build this URL by hand: always follow `meta.reveal_url` exactly as returned by "Manual connection credentials", which mints it as a short-lived Laravel signed URL (`signed:relative`) carrying `user`, `nonce`, `expires` and `signature`.

This route opts out of personal-access-token authentication entirely (`AuthenticatePublicApi` is skipped): the signed URL itself is the credential, so `Authorization` is ignored here.

The link is single-use: reading it once spends the `nonce`, independently of its time-to-live. Route name `public.v1.sites.connection.manual.reveal`.

Answers **200** with `meta.client_id` and `meta.client_secret` - the plaintext OAuth client secret used to finish the manual WordPress connection.

Errors: **403** with a JSON:API `errors` document when the signature is invalid, tampered or expired (Laravel's own "Invalid signature." message), and the same status when the nonce was already spent ("This link has already been used or has expired.", the message the API returns when the link is followed a second time).

Reference: https://api.docs.modulards.com/modular-ds-public-api/websites/reveal-manual-connection-credentials

## Request

### Path parameters

- `site_id` (string, required)

### Query parameters

- `user` (string, optional) — Global user id of the member who requested the reveal; part of the signature, never edit by hand
- `nonce` (string, optional) — Single-use token bound to that membership; spent on first successful read
- `expires` (string, optional) — Unix timestamp the signature is valid until (Laravel signed-route parameter)
- `signature` (string, optional) — HMAC over the relative path and the parameters above (Laravel signed-route parameter)

## Response

### 200

200 - Client secret revealed

- `jsonapi` (object, optional)
  - `version` (string, optional)
- `meta` (object, optional)
  - `client_id` (string, optional)
  - `client_secret` (string, optional)

## Errors

### 403 Forbidden Error

403 - Link already used or expired

- `errors` (list of object, optional)
  - `detail` (string, optional)
  - `status` (string, optional)
  - `title` (string, optional)
- `jsonapi` (object, optional)
  - `version` (string, optional)

## Examples

**Response**

```json
{
  "jsonapi": {
    "version": "1.1"
  },
  "meta": {
    "client_id": "a1b2c3d4-e5f6-4789-a012-b3c4d5e6f789",
    "client_secret": "8f14e45fceea167a5a36dedd4bea2543a2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e"
  }
}
```

**SDK Code**

```python 200 - Client secret revealed
import requests

url = "https://api.modulards.com/api/public/v1/sites/site_id/connection/manual/reveal"

response = requests.get(url)

print(response.json())
```

```javascript 200 - Client secret revealed
const url = 'https://api.modulards.com/api/public/v1/sites/site_id/connection/manual/reveal';
const options = {method: 'GET'};

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

```go 200 - Client secret revealed
package main

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

func main() {

	url := "https://api.modulards.com/api/public/v1/sites/site_id/connection/manual/reveal"

	req, _ := http.NewRequest("GET", url, nil)

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

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

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

}
```

```ruby 200 - Client secret revealed
require 'uri'
require 'net/http'

url = URI("https://api.modulards.com/api/public/v1/sites/site_id/connection/manual/reveal")

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

request = Net::HTTP::Get.new(url)

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

```java 200 - Client secret revealed
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://api.modulards.com/api/public/v1/sites/site_id/connection/manual/reveal")
  .asString();
```

```php 200 - Client secret revealed
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://api.modulards.com/api/public/v1/sites/site_id/connection/manual/reveal');

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

```csharp 200 - Client secret revealed
using RestSharp;

var client = new RestClient("https://api.modulards.com/api/public/v1/sites/site_id/connection/manual/reveal");
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);
```

```swift 200 - Client secret revealed
import Foundation

let request = NSMutableURLRequest(url: NSURL(string: "https://api.modulards.com/api/public/v1/sites/site_id/connection/manual/reveal")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"

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()
```