Brivio Documentation
Developers

API

The public REST interface for your own integrations.

Base URL

All requests go to https://api.brivio.ro. Responses are JSON, and errors follow one contract: a code, a message and, where relevant, the list of invalid fields.

What is covered

The endpoints cover sales documents, partners, the catalogue and stock. Spaces (/spaces) group the domains, sites and apps of a project and can be managed with an API key; space transfers (/space-transfers) are read-only, because moving a space to another organisation needs a person in the app with a second factor. Accounting operations are not exposed for writing: entries are generated from documents, and a direct write path could produce entries with no source document.

Newsletter subscribers (double opt-in)

POST /v1/marketing/subscribers lets the backend of a public form (a site footer, a landing page) add someone to your organisation's newsletter. Brivio sends the confirmation email, hosts the confirmation page and keeps the consent evidence; the person only becomes a subscriber after they confirm.

The key needs the scope marketing_subscribers:write. It stands alone and is not implied by marketing:write, so a key that lives on a public form's server can add subscribers but cannot send campaigns. The optional Idempotency-Key header is honoured (24 h replay).

Request body:

  • email — required, up to 320 characters, lowercased by the server.
  • name — optional, up to 200 characters.
  • locale — ro or en, default ro; the language of the confirmation email and pages.
  • source — optional, up to 120 characters; where the form lives, for your own reporting.
  • redirect_url — optional https URL; after a successful confirmation the person is sent there (303) with ?status=confirmed.
  • consent — required, the evidence GDPR art. 7(1) asks the controller to be able to show:
    • text_version — required, 1–64 characters, the version of the consent wording the person saw;
    • text — optional, up to 2000 characters, stored only as a SHA-256 hash;
    • ip — optional, the end user's IP (not your server's), stored only as a salted hash;
    • user_agent — optional, truncated to 300 characters.

Brivio keeps hashes rather than the raw IP and wording: enough to prove later which text a given request agreed to, without storing more personal data than the proof needs.

Responses use the usual { data, error } envelope with a MarketingSubscriber object:

  • 201 — a new subscriber was created with status pending and a confirmation email was sent.
  • 200 — the address is already known for your organisation. The call is idempotent per address: the current state is returned unchanged, or the confirmation is re-sent if the subscriber is still pending and the cooldown has passed, or a previously unsubscribed address goes back to pending. confirmation_sent tells you whether this call sent an email.
  • 422 VALIDATION_ERROR, 401, 403 SCOPE_REQUIRED, 429 RATE_LIMITED.

The status moves pending → subscribed → unsubscribed. The confirmation link opens a page with a button: opening the link (GET) never changes anything, because mail security scanners follow every link; pressing the button (POST) confirms. The link is signed, single-use and valid for 24 hours. Every subscriber also gets unsubscribe_url, an RFC 8058 one-click unsubscribe link that works both from the mail client's unsubscribe button and from a browser.

Limits: 600 requests per hour per organisation, and at most one confirmation email per address every 10 minutes.

curl https://api.brivio.ro/v1/marketing/subscribers \
	-H "Authorization: Bearer $BRIVIO_API_KEY" \
	-H "Content-Type: application/json" \
	-H "Idempotency-Key: 6f1c2e4a-newsletter-footer" \
	-d '{
		"email": "ana@example.ro",
		"name": "Ana",
		"locale": "ro",
		"source": "example.ro/footer",
		"redirect_url": "https://example.ro/newsletter/confirmed",
		"consent": { "text_version": "2026-10-05", "text": "I agree to receive the monthly newsletter.", "ip": "203.0.113.7" }
	}'
const subscriber = await brivio.marketing.createSubscriber({
	email: "ana@example.ro",
	name: "Ana",
	locale: "ro",
	source: "example.ro/footer",
	consent: { text_version: "2026-10-05", text: consentText, ip: request.ip },
});
// subscriber.status === "pending" until Ana confirms
$subscriber = $brivio->createMarketingSubscriber([
		'email' => 'ana@example.ro',
		'locale' => 'ro',
		'source' => 'example.ro/footer',
		'consent' => ['text_version' => '2026-10-05', 'ip' => $_SERVER['REMOTE_ADDR']],
]);

Full reference

Every operation, with its request shape, responses and code samples, is generated from the OpenAPI document at /reference. The same document drives the TypeScript, PHP, Python, Go, Java and .NET SDKs, so what you read there is what the SDK calls.

On this page