# 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)
}
```
