# Verify Responses Server-Side

<details>

<summary>What is this?</summary>

After a user completes your CAPTCHA on the frontend, you need to verify that it's legitimate on your server. Think of it like checking an ID card - the user shows you the card (CAPTCHA token), but you need to call the issuing authority (our GotCHA API) to confirm it's real.

</details>

<details>

<summary>Why do I need this?</summary>

**This step is critical for security.** Without server-side verification, malicious users could bypass your CAPTCHA entirely. The frontend CAPTCHA is just for show - the real protection happens on your server.

</details>

### How it works

{% stepper %}
{% step %}

### Get the token from your frontend

When a user completes the CAPTCHA, your frontend receives a token (a long string of characters). Your form should send this token to your server along with the rest of the form data.
{% endstep %}

{% step %}

### Verify the token with our API

Your server needs to make a request to our verification endpoint to check if the token is valid.

**API Details:**

* **URL:** `http://api.gotcha.land/api/siteverify`
* **Method:** POST
* **Content-Type:** `application/x-www-form-urlencoded`

**Required Parameters:**

* `secret`: Your private secret key (found in your GotCHA dashboard)
* `response`: The token you received from the frontend
* `remoteip`: (optional) The client that solved the captcha
  {% endstep %}

{% step %}

### Check the response

Our API will return a JSON response like this:

```json
{
  "success": true|false,
  "challenge_ts": timestamp,   // timestamp of the challenge load (ISO8601 format)
  "hostname": string,          // the hostname of the site where the captcha was solved
  "error-codes": [string]      // optional
}
```

If `success` is `true`, the CAPTCHA is valid. If it's `false`, reject the form submission.

Error codes can be one or more of the following:

* `missing-input-secret`: The secret parameter is missing.
* `invalid-input-secret`: The secret parameter is invalid or malformed.
* `missing-input-response`: The response parameter is missing.
* `invalid-input-response`: The response parameter is invalid or malformed.
* `bad-request`: The request is invalid or malformed.
* `timeout-or-duplicate`: The response is no longer valid: either is too old or has been used previously.
  {% endstep %}
  {% endstepper %}

## Code Examples

### **Javascript/Node.js**

```javascript
async function verifyCaptcha(token) {
    const response = await fetch('http://api.gotcha.land/api/siteverify', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: new URLSearchParams({
            secret: 'YOUR_SECRET_KEY',    // ** Replace with your actual secret key ** 
            response: token
        })
    });
    
    const result = await response.json();
    return result.success;
}

// Usage in an Express.js route
app.post('/submit-form', async (req, res) => {
    const captchaToken = req.body['gotcha-response'];
    
    const isValid = await verifyCaptcha(captchaToken);
    if (isValid) {
        // Process the form submission
        res.json({ message: 'Form submitted successfully!' });
    } else {
        // Reject the submission
        res.status(400).json({ error: 'Invalid CAPTCHA' });
    }
});
```

### Rust

```rust
#[derive(Debug, Serialize, Deserialize)]
pub struct VerificationResponse {
    pub success: bool,
    #[serde(with = "time::serde::iso8601")]
    pub challenge_ts: OffsetDateTime,
    pub hostname: String,
    #[serde(rename = "error-codes", skip_serializing_if = "Option::is_none")]
    pub error_codes: Option<Vec<ErrorCodes>>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum ErrorCodes {
    MissingInputSecret,
    InvalidInputSecret,
    MissingInputResponse,
    InvalidInputResponse,
    BadRequest,
    TimeoutOrDuplicate,
}

// Example verification endpoint
async fn verify_captcha(token: &str) -> Result<bool, Error> {
    let client = reqwest::Client::new();
    let response = client
        .post("http://api.gotcha.land/api/siteverify")
        .form(&[
            ("secret", "YOUR_SECRET_KEY"),
            ("response", token),
        ])
        .send()
        .await?;

    let result: VerificationResponse = response.json().await?;
    Ok(result.success)
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gotcha.gitbook.io/docs/website-integration/verify-responses-server-side.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
