Complete reference for integrating Yaan bot protection into your application.
Include the Yaan script in your HTML:
<script
src="https://cdn.yaan.com/apricot.js"
data-sitekey="YOUR_SITEKEY"
async
></script>
window.Apricot.requestToken()Requests a verification token from Yaan after analyzing user behavior.
Returns: Promise<string>
Usage:
const token = await window.Apricot.requestToken();
Behavior:
Error Handling:
try {
const token = await window.Apricot.requestToken();
// Use token for form submission
} catch (error) {
console.error("Yaan verification failed:", error);
// Handle error (show message to user, etc.)
}
Common Errors:
| Error | Cause | Solution |
|---|---|---|
"Apricot not initialized" | Script not loaded | Wait for script load or check sitekey |
"Request failed: 401" | Invalid sitekey | Verify sitekey in dashboard |
"Request failed: 418" | Session error | Session expired, reload page |
"no global window" | Not in browser context | Only call in browser environment |
/sus - Token Verification EndpointVerifies a Yaan token and determines if the request should be blocked.
Endpoint: POST https://api.yaan.com/sus
Content-Type: application/json
{
diamond: string; // The token from window.Apricot.requestToken()
clientsecret: string; // Your client secret (from dashboard)
ip_addr: string; // User's IP address
email_domain?: string; // Optional: email domain for additional filtering
}
Example Request:
{
"diamond": "abc123def456...",
"clientsecret": "cs_live_1234567890abcdef",
"ip_addr": "192.168.1.100",
"email_domain": "gmail.com"
}
{
block: boolean; // true = block user (bot), false = allow (human)
}
Example Response (Human):
{
"block": false
}
Example Response (Bot):
{
"block": true
}
| Code | Meaning |
|---|---|
200 OK | Token verified successfully (check block field) |
500 Internal Server Error | Server error (retry with exponential backoff) |
Important: The /sus endpoint returns 200 OK even for invalid/expired tokens. Always check the block field in the response. If block: true, deny the request.
async function verifyYaanToken(
token,
clientSecret,
ipAddress,
emailDomain = null,
) {
try {
const response = await fetch("https://api.yaan.com/sus", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
diamond: token,
clientsecret: clientSecret,
ip_addr: ipAddress,
email_domain: emailDomain,
}),
});
if (!response.ok) {
throw new Error(`Yaan API error: ${response.status}`);
}
const result = await response.json();
return !result.block;
} catch (error) {
console.error("Yaan verification error:", error);
// Fail closed: if verification fails, block the request
return false;
}
}
import requests
def verify_yaan_token(token, client_secret, ip_address, email_domain=None):
try:
response = requests.post('https://api.yaan.com/sus', json={
'diamond': token,
'clientsecret': client_secret,
'ip_addr': ip_address,
'email_domain': email_domain
}, timeout=5)
response.raise_for_status()
result = response.json()
return not result['block']
except Exception as e:
print(f'Yaan verification error: {e}')
# Fail closed: if verification fails, block the request
return False
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"time"
)
type YaanRequest struct {
Diamond string `json:"diamond"`
ClientSecret string `json:"clientsecret"`
IPAddr string `json:"ip_addr"`
EmailDomain *string `json:"email_domain,omitempty"`
}
type YaanResponse struct {
Block bool `json:"block"`
}
func verifyYaanToken(token, clientSecret, ipAddr string, emailDomain *string) (bool, error) {
reqBody := YaanRequest{
Diamond: token,
ClientSecret: clientSecret,
IPAddr: ipAddr,
EmailDomain: emailDomain,
}
jsonData, err := json.Marshal(reqBody)
if err != nil {
return false, err
}
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Post(
"https://api.yaan.com/sus",
"application/json",
bytes.NewBuffer(jsonData),
)
if err != nil {
return false, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return false, fmt.Errorf("API returned status %d", resp.StatusCode)
}
var result YaanResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return false, err
}
return !result.Block, nil
}
require 'net/http'
require 'json'
def verify_yaan_token(token, client_secret, ip_address, email_domain = nil)
uri = URI('https://api.yaan.com/sus')
request_body = {
diamond: token,
clientsecret: client_secret,
ip_addr: ip_address,
email_domain: email_domain
}.compact
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request.body = request_body.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
if response.code.to_i == 200
result = JSON.parse(response.body)
return !result['block']
else
# Fail closed
return false
end
rescue => e
puts "Yaan verification error: #{e.message}"
# Fail closed
false
end
Yaan automatically collects behavioral telemetry every 10 seconds while the user is on your page. This happens transparently without any additional code.
Browser Fingerprinting:
User Interactions:
Document State:
All data is used exclusively for bot detection and is not shared with third parties. See our Privacy Policy for details.
/sus endpointExample Rate Limiting (Node.js with express-rate-limit):
const rateLimit = require("express-rate-limit");
const yaanLimiter = rateLimit({
windowMs: 1000, // 1 second
max: 10, // 10 requests per second
message: "Too many verification requests",
});
app.post("/api/submit", yaanLimiter, async (req, res) => {
// Your verification logic...
});
Example:
async function verifyWithFallback(token, clientSecret, ipAddress) {
try {
const isHuman = await verifyYaanToken(token, clientSecret, ipAddress);
return isHuman;
} catch (error) {
console.error("Yaan verification failed:", error);
// Log to your monitoring service
logError("yaan-verification-failed", error);
// Fail closed
return false;
}
}
Use these special sitekeys for testing:
| Sitekey | Behavior |
|---|---|
test_always_pass | Always returns block: false |
test_always_block | Always returns block: true |
test_random | Randomly blocks 50% of requests |
Test sitekeys only work in development/staging environments, not production.
describe("Yaan Integration", () => {
it("should block bots", async () => {
const token = "test-bot-token";
const result = await verifyYaanToken(
token,
"test_always_block",
"127.0.0.1",
);
expect(result).toBe(false);
});
it("should allow humans", async () => {
const token = "test-human-token";
const result = await verifyYaanToken(
token,
"test_always_pass",
"127.0.0.1",
);
expect(result).toBe(true);
});
});