Загружаем 1ОПД
Подготавливаем страницу…
Подготавливаем страницу…
Для одностраничных приложений: интеграция вешается на onSubmit вашего компонента-формы. Никаких глобальных слушателей.
pk_ (publishable — можно публиковать в браузере)forms_scope=[id1, id2, …] — и в каждом запросе передаёте form_id в body.Создать ключ для своего сайта → ваш ЛК 1ОПД · Все endpoints → API Reference
import { useState } from "react";
const OPD_API = "https://v2.1opd.ru/api/v2/create-agreement";
const OPD_KEY = process.env.NEXT_PUBLIC_OPD_KEY!; // pk_xxxxxxxxxxxxxxxxxxxx
export function LeadForm() {
const [email, setEmail] = useState("");
const [name, setName] = useState("");
const [submitting, setSubmitting] = useState(false);
async function recordConsent(payload: Record<string, string>) {
try {
const res = await fetch(OPD_API, {
method: "POST",
headers: { "API-KEY": OPD_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
form_id: 1,
hash_field: payload.email,
fields: Object.entries(payload).map(([k, v]) => ({ field: k, value: v })),
}),
});
const data = await res.json();
return data.hash as string | undefined;
} catch {
// не блокируем основную отправку
return undefined;
}
}
async function handleSubmit(e: React.FormEvent) {
e.preventDefault();
setSubmitting(true);
await recordConsent({ email, name });
// ваша основная отправка — например, POST на /api/leads
setSubmitting(false);
}
return (
<form onSubmit={handleSubmit}>
<input value={email} onChange={(e) => setEmail(e.target.value)} placeholder="Email" />
<input value={name} onChange={(e) => setName(e.target.value)} placeholder="Имя" />
<button disabled={submitting}>Отправить</button>
</form>
);
}<script setup lang="ts">
import { ref } from "vue";
const OPD_API = "https://v2.1opd.ru/api/v2/create-agreement";
const OPD_KEY = import.meta.env.VITE_OPD_KEY; // pk_xxxxxxxxxxxxxxxxxxxx
const email = ref("");
const name = ref("");
async function submit() {
await fetch(OPD_API, {
method: "POST",
headers: { "API-KEY": OPD_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
form_id: 1,
hash_field: email.value,
fields: [
{ field: "email", value: email.value },
{ field: "name", value: name.value },
],
}),
});
// ... ваша основная логика
}
</script>
<template>
<form @submit.prevent="submit">
<input v-model="email" placeholder="Email" />
<input v-model="name" placeholder="Имя" />
<button>Отправить</button>
</form>
</template>Если форм много — один хук, один ключ с forms_scope, разные form_id на вызовы:
// hooks/use1OPD.ts — переиспользуемый хук для multi-form
export function use1OPD() {
async function record(formId: number, fields: Record<string, string>, hashField = "email") {
return fetch("https://v2.1opd.ru/api/v2/create-agreement", {
method: "POST",
headers: {
"API-KEY": process.env.NEXT_PUBLIC_OPD_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
form_id: formId, // multi-form: один ключ, разные form_id
hash_field: fields[hashField],
fields: Object.entries(fields).map(([k, v]) => ({ field: k, value: v })),
}),
}).then((r) => r.json());
}
return { record };
}pk_, не sk_. В скомпилированный bundle попадает всё, что есть в коде.NEXT_PUBLIC_, в Vite — VITE_: ключ попадёт в client bundle сознательно.allowed_origins укажите прод + stage + dev-хосты. Без правильного Origin запрос вернёт 403.Откройте ЛК → раздел «Интеграция». Там персональные snippet'ы с уже подставленным API-ключом и form_id.
Открыть ЛК →Запросите тестовый доступ — выдаём ключ под ваш домен и помогаем подключиться.
Связаться →Все endpoints, коды ошибок, форматы HMAC/Origin/IP. Таблица «какую защиту выбрать».
Открыть →