API de URL cortas de Vivoldi para desarrolladores

Guía de la API REST para crear URL cortas

Vivoldi proporciona una API REST dedicada que se puede integrar perfectamente en su sitio web, aplicación móvil o sistema interno.
Con esta API, puede generar y gestionar URL cortas directamente desde su servidor o aplicación sin acceder al panel de Vivoldi.

La API REST está diseñada para funcionar con una amplia gama de lenguajes de programación y plataformas, incluyendo JavaScript, PHP, Java, Android e iOS.
Antes de utilizar la API, debe generar una clave de API y mantenerla almacenada de forma segura sin exponerla a terceros.

Las claves API pueden actualizarse una vez al mes, y las URL cortas existentes no se verán afectadas.
Todos los usuarios, incluidos los del plan gratuito, pueden acceder a la API, pero la frecuencia de las solicitudes y la velocidad de respuesta pueden variar en función de su plan.

Si se encuentra con un error HTTP 403 al llamar a la API, especifique un valor único de User-Agent en el encabezado de la solicitud.
Vivoldi bloquea activamente rastreadores y bots maliciosos y mantiene una lista negra interna de direcciones IP.
Para garantizar una comunicación API estable, utilice el nombre de su empresa o marca (en inglés) como cadena User-Agent.

Vivoldi puede reiniciar los servidores durante el despliegue de funciones, parches de seguridad o mantenimiento del sistema.
Para evitar interrupciones, recomendamos encarecidamente implementar una lógica de reintento para todas las solicitudes de API.

API de URL cortas de Vivoldi para desarrolladores

Cómo llamar a la API

Request:
Host: https://vivoldi.com/api HTTP/1.1
Authorization: APIKey {Your API Key}
Content-type: application/json
Simplemente añada Authorisation, Content-type a su cabecera Http y llame a la API.
Response:
{
    "code": 0,
    "message": "",
    "result": Object
}
code - El código de respuesta, donde 0 es éxito y cualquier otro valor es un código de fallo.
message - El mensaje de respuesta, se devuelve un mensaje de error si el código de respuesta es distinto de cero.
result - El valor de la respuesta, devuelto como un carácter u objeto JSON dependiendo del tipo de API.
Póngase en contacto con Vivoldi si necesita mejoras o modificaciones de la API REST.

Crear enlace

Si desea crear un único enlace corto, puede generarlo fácilmente utilizando esta API.
Para crear varios enlaces a la vez, pruebe a utilizar la API de creación de enlaces masivos.
También puede generar enlaces rápidamente a través del menú "Generador de enlaces masivos" del panel de control.

Para los usuarios del plan gratuito, las llamadas a la API están limitadas a 10 solicitudes por minuto.
Si necesita un mayor volumen, considere la posibilidad de actualizar a un plan de pago para obtener un acceso ampliado.

Cada enlace corto incluye automáticamente un código QR, al que se puede acceder mediante el formato de URL `vvd.bz/[linkId]/qr`.
Para ajustar el tamaño del código QR, basta con añadir el parámetro `size` a la URL.
Por ejemplo, utilice `vvd.bz/[linkId]/qr?size=200` para generar un código QR con un tamaño de 200 píxeles.

Request:
Post /api/link/v2/create HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request:
CamposDescripción de los camposDescripciónRequeridoTipo
urlURL larga La URL larga a la que se redirigirá cuando se haga clic en el enlace corto generado.
Puede tener hasta 3,000 bytes.
string
domainDominio Si el valor está vacío, se establecerá automáticamente como el dominio vvd.bz.
Debes ingresar el valor incluyendo “https://” y, si la opción “brandLinkId” es “Y”, utiliza el dominio “https://vvd.im”.
Si has vinculado tu propio dominio a Vivoldi, puedes configurarlo aquí.
Ejemplo: https://vvd.bz
string
redirectTypeTipo de redirección Establece cómo se navega desde la URL corta a la URL larga.
Puedes elegir entre 200, 301 o 302 como el código de respuesta HTTP. Valor predeterminado: 302
Para más información sobre los métodos de redirección, consulta la página de “Glosario”.
int
grpIdxID de grupo Asignar un ID de grupo vinculará el enlace a ese grupo.
Para obtener el GroupID, debes usar la API de "Lista de grupos".
int
brandLinkIdID de enlace de marca Si especificas un valor, el enlace se creará con ese ID.
(Si se establece un enlace de marca, el dominio será vvd.im en vez de vvd.bz)
Si el valor está vacío, el linkID se genera automáticamente.
string
ttlTítulo del enlace Si el valor está vacío, se almacenará como el título de la página web de la URL larga.
Si está vacío, se accede a la URL larga y se realiza un análisis HTML, por lo que si la respuesta es lenta tras llamar a la API, asigna el título.
string
descriptionMeta descripción Puedes definir la meta description de la página cuando “redirectType” sea “200”.
Este valor se ignora si “redirectType” es “301”, “302”, etc.
string
memoNotas Puedes añadir información adicional para gestión interna que no será visible para los usuarios. string
notfSubscYnEnlace push Si el valor es Y, al hacer clic en el enlace generado, aparecerá una ventana emergente de notificación push antes de acceder al enlace largo, y podrás enviar mensajes push a todos los usuarios que hayan dado permiso.
Si el usuario rechaza o cierra la ventana, será dirigido inmediatamente a la URL larga.
Si no se ingresa valor, el predeterminado es N.
Para más información, consulta la página de introducción de Web Push.
Y o N
clksIpFilteringYnFiltrado IP para clics Si el valor es Y, los clics desde la misma IP solo contarán una vez en un periodo de 3 días.
A partir del cuarto día, los clics volverán a contarse.
Esta opción solo puede configurarse al crear el enlace y no puede modificarse después.
Disponible a partir del plan Personal.
Y o N
pushNotifyYnNotificaciones push Si el valor es Y, recibirás notificaciones push en dispositivos móviles con la app de Vivoldi instalada, cada vez que se alcance el número de clics configurado en las preferencias del enlace.
Disponible a partir del plan Personal.
Y o N
mailNotifyYnNotificaciones por correo Si el valor es Y, recibirás información por correo cada vez que el enlace alcance el número de clics definido en las preferencias.
Disponible a partir del plan Personal.
Y o N
delYmdFecha de eliminación Tras la fecha configurada, el enlace se elimina automáticamente.
Ciclo de eliminación: cada hora
Ejemplo: 2025-12-31
Date
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnCreateLink" type="button">Create Link</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnCreateLink").on('click', function(evt){
		evt.preventDefault();

		$.ajax({
			type: 'POST',
			url: 'https://vivoldi.com/api/link/v2/create',
			data: JSON.stringify({'url':'https://google.com','domain':'https://vvd.bz'}),
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			contentType: 'application/json; charset=utf-8',
			dataType: 'json',
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				alert('short url: ' + res.result);
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$url = "https://vivoldi.com/api/link/v2/create";
$params = array (
	"url" => "https://www.facebook.com/vivoldi365",
	"domain" => "https://vvd.bz",
);
$body = json_encode($params);

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX",
	"Content-Type: application/json"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class CreateLink {
    public static void main(String[] args) {
        try (HttpClient client = HttpClient.newBuilder().build()) {
            JSONObject params = new JSONObject();
            params.put("url", "https://www.facebook.com/vivoldi365");
            params.put("domain", "https://vvd.bz");

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/link/v2/create"))
                .header("Content-Type", "application/json")
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .POST(HttpRequest.BodyPublishers.ofString(params.toString()))
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println("Short URL: " + json.getString("result"));
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
    }
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":"",
    "result":"https://vvd.bz/jH3d"
}
Response:
CamposDescripciónTipo
codeCódigo de respuesta (0:Éxito)int
messageEl mensaje de respuesta, o un mensaje relacionado si el código de respuesta es distinto de cero.string
resultValor de la respuesta (enlace acortado)string

Creación masiva de enlaces

Crear varios enlaces acortados a la vez.
Si desea crear un gran número de enlaces a la vez, utilice el menú "Crear enlaces masivos" del panel de control.

Sólo puedes crear un número limitado de enlaces a la vez, y los límites por plan son los siguientes
Si desea generar 3.000 enlaces, tendrá que llamar a esta API varias veces.

Plan personal: Hasta 200
Plan Premium: hasta 500
Plan Business: hasta 1.000

Esta API está disponible a partir del plan Personal.

Request:
Post /api/link/v1/createBulk HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request:
CamposTipo
links
CamposDescripción de los camposDescripciónRequeridoTipo
urlURL larga La URL larga a la que se redirigirá cuando se haga clic en el enlace corto generado.
Puede tener hasta 3,000 bytes.
string
domainDominio Si el valor está vacío, se establecerá automáticamente como el dominio vvd.bz.
Debes ingresar el valor incluyendo “https://” y, si la opción “brandLinkId” es “Y”, utiliza el dominio “https://vvd.im”.
Si has vinculado tu propio dominio a Vivoldi, puedes configurarlo aquí.
Ejemplo: https://vvd.bz
string
redirectTypeTipo de redirección Establece cómo se navega desde la URL corta a la URL larga.
Puedes elegir entre 200, 301 o 302 como el código de respuesta HTTP. Valor predeterminado: 302
Para más información sobre los métodos de redirección, consulta la página de “Glosario”.
int
grpIdxID de grupo Asignar un ID de grupo vinculará el enlace a ese grupo.
Para obtener el GroupID, debes usar la API de "Lista de grupos".
int
brandLinkIdID de enlace de marca Si especificas un valor, el enlace se creará con ese ID.
(Si se establece un enlace de marca, el dominio será vvd.im en vez de vvd.bz)
Si el valor está vacío, el linkID se genera automáticamente.
string
ttlTítulo del enlace Si el valor está vacío, se almacenará como el título de la página web de la URL larga.
Si está vacío, se accede a la URL larga y se realiza un análisis HTML, por lo que si la respuesta es lenta tras llamar a la API, asigna el título.
string
descriptionMeta descripción Puedes definir la meta description de la página cuando “redirectType” sea “200”.
Este valor se ignora si “redirectType” es “301”, “302”, etc.
string
memoNotas Puedes añadir información adicional para gestión interna que no será visible para los usuarios. string
notfSubscYnEnlace push Si el valor es Y, al hacer clic en el enlace generado, aparecerá una ventana emergente de notificación push antes de acceder al enlace largo, y podrás enviar mensajes push a todos los usuarios que hayan dado permiso.
Si el usuario rechaza o cierra la ventana, será dirigido inmediatamente a la URL larga.
Si no se ingresa valor, el predeterminado es N.
Para más información, consulta la página de introducción de Web Push.
Y o N
clksIpFilteringYnFiltrado IP para clics Si el valor es Y, los clics desde la misma IP solo contarán una vez en un periodo de 3 días.
A partir del cuarto día, los clics volverán a contarse.
Esta opción solo puede configurarse al crear el enlace y no puede modificarse después.
Disponible a partir del plan Personal.
Y o N
pushNotifyYnNotificaciones push Si el valor es Y, recibirás notificaciones push en dispositivos móviles con la app de Vivoldi instalada, cada vez que se alcance el número de clics configurado en las preferencias del enlace.
Disponible a partir del plan Personal.
Y o N
mailNotifyYnNotificaciones por correo Si el valor es Y, recibirás información por correo cada vez que el enlace alcance el número de clics definido en las preferencias.
Disponible a partir del plan Personal.
Y o N
delYmdFecha de eliminación Tras la fecha configurada, el enlace se elimina automáticamente.
Ciclo de eliminación: cada hora
Ejemplo: 2025-12-31
Date
array
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnCreateBulkLinks" type="button">Create bulk links</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnCreateBulkLinks").on('click', function(evt){
		evt.preventDefault();
		const params = {
			'links': [
				{'url':'https://google.com','domain':'https://vvd.bz'},
				{'url':'https://facebook.com','domain':'https://vvd.bz'},
				{'url':'https://twitter.com','domain':'https://vvd.bz'}
			]
		};
		$.ajax({
			type: 'POST',
			url: 'https://vivoldi.com/api/link/v1/createBulk',
			data: JSON.stringify(params),
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			contentType: 'application/json; charset=utf-8',
			dataType: 'json',
			timeout: 10000
		}).done(function(res){
			if (res.code === 0) {
				console.log(res.result);
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$url = "https://vivoldi.com/api/link/v1/createBulk";
$params = array (
	"links" => array(
		array(
			"url" => "https://google.com",
			"domain" => "https://vvd.bz"
		),
		array(
			"url" => "https://facebook.com",
			"domain" => "https://vvd.bz"
		),
		array(
			"url" => "https://twitter.com",
			"domain" => "https://vvd.bz"
		)
	)
);
$body = json_encode($params);

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX",
	"Content-Type: application/json"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.json.JSONArray;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class CreateLink {
    public static void main(String[] args) {
        try (HttpClient client = HttpClient.newBuilder().build()) {
			JSONObject link1 = new JSONObject();
			link1.put("url", "https://google.com").put("domain", "https://vvd.bz");

			JSONObject link2 = new JSONObject();
			link2.put("url", "https://facebook.com").put("domain", "https://vvd.bz");

			JSONObject link3 = new JSONObject();
			link3.put("url", "https://twitter.com").put("domain", "https://vvd.bz");

			JSONArray links = new JSONArray();
			links.put(link1);
			links.put(link2);
			links.put(link3);

            JSONObject params = new JSONObject();
            params.put("links", links);

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/link/v2/create"))
                .header("Content-Type", "application/json")
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .POST(HttpRequest.BodyPublishers.ofString(params.toString()))
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println("Short URL: " + json.getString("result"));
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
    }
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":"",
    "result":[
        {shortUrl: "https://vvd.bz/bbuR", url: "https://google.com"},
        {shortUrl: "https://vvd.bz/bbuS", url: "https://facebook.com"},
        {shortUrl: "https://vvd.bz/bbuT", url: "https://twitter.com"}
    ]
}
Response:
CamposDescripciónTipo
codeCódigo de respuesta (0:Éxito)int
messageEl mensaje de respuesta, o un mensaje relacionado si el código de respuesta es distinto de cero.string
resultValor de la respuesta (enlace acortado)string

Editar un enlace

Edite el enlace corto que ha creado.
Sólo puede modificar el tipo de enlace si es una URL; los demás tipos no se modifican aunque la llamada a la API tenga éxito.

Request:
Put /api/link/v2/edit HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request:
CamposDescripción de los camposDescripciónRequeridoTipo
linkIdID de enlace ID del enlace corto generado.
Ejemplo:
Si la dirección del enlace corto es "https://vvd.bz/fML", el ID de enlace es fML.
string
domainDominio El dominio de la dirección del enlace corto.
Ejemplo:
Si la dirección del enlace corto es "https://vvd.bz/fML", el dominio es https://vvd.bz.
Importante: Debes ingresar https:// o http://.
Si configuras un dominio diferente al del enlace generado, se producirá un error.
string
redirectTypeTipo de redirección Define cómo se navega del enlace corto a la URL larga.
Puedes elegir entre 200, 301 o 302 como código de estado HTTP. Valor predeterminado: 302.
Para más información sobre métodos de redirección, consulta la página de “Glosario”.
int
grpIdxID de grupo Cambia el grupo del enlace generado.
Para obtener el ID de grupo, debes llamar a la API "Lista de grupos".
int
urlURL larga Cambia la URL larga.
Solo puedes cambiar URLs largas a partir del plan Premium.
string
ttlTítulo del enlace Si este campo está vacío, el título del enlace no se modifica. string
descriptionMeta descripción Puedes definir la meta description de la página cuando “redirectType” tenga valor “200”.
Este valor se ignora cuando “redirectType” es “301”, “302”, etc.
string
memoNotas Puedes añadir información administrativa adicional que no será visible para los usuarios.
Si este campo está vacío, la nota no se modificará.
string
notfSubscYnEnlace Push Si el valor es Y, al hacer clic en el enlace se mostrará un pop-up de notificación push antes de ir a la URL larga. Si el usuario ha aceptado las notificaciones push, puedes enviar mensajes push a todos los usuarios permitidos.
Si rechazan o cierran el pop-up, irán directamente a la URL larga.
Si no ingresas un valor, el valor predeterminado es N.
Para saber más sobre enlaces de suscripción push, haz clic aquí.
Y o N
pushNotifyYnNotificaciones push Si el valor es Y, recibirás notificaciones push en dispositivos móviles con la app Vivoldi instalada cada vez que un enlace alcance el número de clics configurado en "Configuración -> Preferencias".
Esta función está disponible a partir del plan Personal.
Y o N
mailNotifyYnNotificaciones por correo Si el valor es Y, recibirás información por correo sobre el número de clics cada vez que se alcance el objetivo configurado en "Configuración -> Preferencias".
Esta función está disponible a partir del plan Personal.
Y o N
delYmdFecha de eliminación Después de la fecha indicada, el enlace se eliminará automáticamente.
Ciclo de eliminación: cada hora.
Ejemplo: 2025-12-31
Date
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnUpdateLink" type="button">Update Link</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnUpdateLink").on('click', function(evt){
		evt.preventDefault();

		$.ajax({
			type: 'PUT',
			url: 'https://vivoldi.com/api/link/v2/edit',
			data: JSON.stringify({'linkId':'jH3d','domain':'https://vvd.bz','ttl':'new title','memo':'new my memo'}),
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			contentType: 'application/json; charset=utf-8',
			dataType: 'json',
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				alert('Success!');
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$url = "https://vivoldi.com/api/link/v2/edit";
$params = array (
	"linkId" => "4Rt3",
	"domain" => "https://vvd.bz",
	"ttl" => "new title",
	"memo" => "new my memo"
);
$body = json_encode($params);

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX",
	"Content-Type: application/json"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class UpdateLink {
	public static void main(String[] args) {
		try (HttpClient client = HttpClient.newBuilder().build()) {
            JSONObject params = new JSONObject();
            params.put("linkId", "jH3d");
            params.put("domain", "https://vvd.bz");
			params.put("ttl", "new title");
			params.put("memo", "new my memo");

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/link/v2/edit"))
                .header("Content-Type", "application/json")
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .PUT(HttpRequest.BodyPublishers.ofString(params.toString()))
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println("success!");
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
	}
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":""
}
Response:
CamposDescripciónTipo
codeCódigo de respuesta (0:Éxito)int
messageEl mensaje de respuesta, o un mensaje relacionado si el código de respuesta es distinto de cero.string

Borrar un enlace

Borra el enlace corto que has creado.

Request:
Delete /api/link/v1/remove HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: -
Request:
CamposDescripción de los camposDescripciónRequeridoTipo
linkIdID de enlace ID del enlace corto generado.
Ejemplo:
Si la dirección del enlace corto es "https://vvd.bz/fML", el linkID es fML.
Se requiere URLEncode si se establece un LinkID de marca (cuando defines tú mismo el LinkID) y contiene caracteres especiales.
string
domainDominio El dominio de la dirección del enlace corto.
Ejemplo:
Si la dirección del enlace corto es "https://vvd.bz/fML", el dominio es https://vvd.bz.
Importante: Debes ingresar https:// o http://.
Si indicas un dominio diferente al del enlace generado, se producirá un error.
Para un LinkID de marca (cuando defines tú mismo el LinkID), el dominio es https://vvd.im.
string
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnDeleteLink" type="button">Delete Link</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnDeleteLink").on('click', function(evt){
		evt.preventDefault();

		$.ajax({
			type: 'DELETE',
			url: 'https://vivoldi.com/api/link/v1/remove?linkId=강남스타벅스점&domain=https://vvd.im',
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				alert('Success!');
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$linkId = urlencode("강남스타벅스점");
$url = "https://vivoldi.com/api/link/v1/remove?linkId=$linkId&domain=https://vvd.im";

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class DeleteLink {
	public static void main(String[] args) {
		try (HttpClient client = HttpClient.newBuilder().build()) {
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/link/v1/remove?linkId=강남스타벅스점&domain=https://vvd.im"))
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .DELETE()
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println("success!");
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
	}
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":""
}
Response:
CamposDescripciónTipo
codeCódigo de respuesta (0:Éxito)int
messageEl mensaje de respuesta, o un mensaje relacionado si el código de respuesta es distinto de cero.string

Estadísticas de clics por hora del día

Vea los clics y las pulsaciones a lo largo del tiempo para un solo enlace.

Esta API está disponible a partir del plan Business.

Request:
Get /api/statistics/v1/clicks-by-time HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: -
Request:
필드필드 설명설명필수유형
linkId링크 ID 링크 ID로 통계를 조회합니다.
브랜드 링크(링크ID를 직접 설정)로 설정된 링크 중 특수문자가 포함되어 있으면 URLEncode가 필요합니다.
string
domain도메인 링크 도메인으로 목록을 조회합니다.
도메인 앞에 반드시 http:// 또는 https:// 값을 붙여야 합니다.
브랜드 링크(링크ID를 직접 설정)가 설정되어 있는 경우 도메인은 https://vvd.bz이 아닌 https://vvd.im 입니다.
string
ymd날짜 해당 날짜의 시간대별 클릭 수와 클릭 사람 수 목록을 조회합니다.
오늘로 부터 최대 7일 전 날짜만 입력할 수 있습니다.
예: 2024-06-14
string
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnClickList" type="button">Get click list</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnClickList").on('click', function(evt){
		evt.preventDefault();

		const linkId = 'y6Tg';
		const domain = 'https://vvd.bz';
		const ymd = '2024-06-14';

		$.ajax({
			type: 'GET',
			url: 'https://vivoldi.com/api/statistics/v1/clicks-by-time?linkId='+linkId+'&domain='+domain+'&ymd='+ymd,
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				console.log(res);
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$linkId = "y6Tg";
$domain = "https://vvd.bz";
$ymd = "2024-06-14";
$url = "https://vivoldi.com/api/statistics/v1/clicks-by-time?linkId=$linkId&domain=$domain&ymd=$ymd";

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class ClickList {
	public static void main(String[] args) {
		try (HttpClient client = HttpClient.newBuilder().build()) {
            String nm = URLEncoder.encode("my test group", StandardCharsets.UTF_8);
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/statistics/v1/clicks-by-time?linkId=y6Tg&domain=https://vvd.bz&ymd=2024-06-14"))
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .GET()
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println(json.getString("result"));
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
	}
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":"",
    "result":[
        {
            "ymd":"2024-06-14",
            "hour":"00",
            "linkId":"y6Tg",
            "domain":"https://vvd.bz",
            "acesCnt":24,
            "pernCnt":17,
        },
        {
            "ymd":"2024-06-14",
            "hour":"08",
            "linkId":"y6Tg",
            "domain":"https://vvd.bz",
            "acesCnt":121,
            "pernCnt":198,
        }
        {
            "ymd":"2024-06-14",
            "hour":"14",
            "linkId":"y6Tg",
            "domain":"https://vvd.bz",
            "acesCnt":84,
            "pernCnt":68,
        }
    ]
}
Response:
필드설명유형
code응답 코드 (0:성공)int
message응답 메시지, 응답 코드가 0이 아닐 경우 관련 메시지가 리턴됨.string
result 통계 목록:
필드필드 설명설명유형
ymd날짜-string
hour시간00시 ~ 23시string
linkId링크 ID-string
domain도메인-string
acesCnt클릭 수링크 클릭 수int
pernCnt클릭 사람 수링크를 클릭한 사람 수int
array

Estadísticas de clics por fecha

Puede ver el número de clics en un solo enlace por fecha y el número de personas que hicieron clic en él.
Al buscar, el intervalo de fechas de inicio y fin no puede ser superior a un mes.

Esta API está disponible a partir del plan Business.

Request:
Get /api/statistics/v1/clicks-by-date HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: -
Request:
필드필드 설명설명필수유형
linkId링크 ID 링크 ID로 통계를 조회합니다.
브랜드 링크(링크ID를 직접 설정)로 설정된 링크 중 특수문자가 포함되어 있으면 URLEncode가 필요합니다.
string
domain도메인 링크 도메인으로 목록을 조회합니다.
도메인 앞에 반드시 http:// 또는 https:// 값을 붙여야 합니다.
브랜드 링크(링크ID를 직접 설정)가 설정되어 있는 경우 도메인은 https://vvd.bz이 아닌 https://vvd.im 입니다.
string
startYmd시작 날짜 링크를 클릭한 시작 날짜로 클릭 날짜가 시작 날짜와 종료 날짜 사이 포함되어야 합니다.
예: 2024-05-01
string
endYmd종료 날짜 링크를 클릭한 종료 날짜로 클릭 날짜가 시작 날짜와 종료 날짜 사이 포함되어야 합니다.
시작 날짜와 종료 날짜 범위는 최대 1달입니다.
예: 2024-05-31
string
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnClickList" type="button">Get click list</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnClickList").on('click', function(evt){
		evt.preventDefault();

		const linkId = 'y6Tg';
		const domain = 'https://vvd.bz';
		const startYmd = '2024-05-01';
		const endYmd = '2024-05-31';

		$.ajax({
			type: 'GET',
			url: 'https://vivoldi.com/api/statistics/v1/clicks-by-date?linkId='+linkId+'&domain='+domain+'&startYmd='+startYmd+'&endYmd='+endYmd,
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				console.log(res);
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$linkId = "y6Tg";
$domain = "https://vvd.bz";
$startYmd = "2024-05-01";
$endYmd = "2024-05-31";
$url = "https://vivoldi.com/api/statistics/v1/clicks-by-date?linkId=$linkId&domain=$domain&startYmd=$startYmd&endYmd=$endYmd";

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class ClickList {
	public static void main(String[] args) {
		try (HttpClient client = HttpClient.newBuilder().build()) {
            String nm = URLEncoder.encode("my test group", StandardCharsets.UTF_8);
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/statistics/v1/clicks-by-date?linkId=y6Tg&domain=https://vvd.bz&startYmd=2024-05-01&endYmd=2024-05-31"))
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .GET()
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println(json.getString("result"));
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
	}
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":"",
    "result":[
        {
            "ymd":"2024-05-01",
            "linkId":"y6Tg",
            "domain":"https://vvd.bz",
            "acesCnt":384,
            "pernCnt":295,
        },
        {
            "ymd":"2024-05-02",
            "linkId":"y6Tg",
            "domain":"https://vvd.bz",
            "acesCnt":18543,
            "pernCnt":15691,
        }
        {
            "ymd":"2024-05-03",
            "linkId":"y6Tg",
            "domain":"https://vvd.bz",
            "acesCnt":5408,
            "pernCnt":5006,
        }
    ]
}
Response:
필드설명유형
code응답 코드 (0:성공)int
message응답 메시지, 응답 코드가 0이 아닐 경우 관련 메시지가 리턴됨.string
result 통계 목록:
필드필드 설명설명유형
ymd날짜-string
linkId링크 ID-string
domain도메인-string
acesCnt클릭 수링크 클릭 수int
pernCnt클릭 사람 수링크를 클릭한 사람 수int
array

Lista de grupos

Obtiene una lista de los grupos de enlaces creados.

Request:
Get /api/group/v1/list HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: -
Request:
필드필드 설명설명필수유형
grpIdx그룹 ID 그룹 ID로 목록을 조회합니다. int
nm그룹 이름 그룹 이름을 설정하면 그룹 목록을 조회할 때 그룹 이름을 검색하여 조회합니다.
그룹 이름 검색은 equals 조회가 아닌 like 조회입니다.
string
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnGroupList" type="button">Get group list</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnGroupList").on('click', function(evt){
		evt.preventDefault();

		const nm = encodeURI('my test group');

		$.ajax({
			type: 'GET',
			url: 'https://vivoldi.com/api/group/v1/list?nm='+nm,
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				console.log(res);
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$nm = urlencode("my test group");
$url = "https://vivoldi.com/api/group/v1/list?nm=$nm";

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class GroupList {
	public static void main(String[] args) {
		try (HttpClient client = HttpClient.newBuilder().build()) {
            String nm = URLEncoder.encode("my test group", StandardCharsets.UTF_8);
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/group/v1/list?nm="+nm))
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .GET()
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println(json.getString("result"));
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
	}
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":"",
    "result":[
        {
            "idx":1,
            "nm":"쿠팡 전자제품",
            "memo":"10만원 ~ 50만원 제품",
            "linkCnt":112,
            "blockOverseasSticsYn":"N",
            "notfSubscYn":"N",
            "kakaoNotifyYn":"N",
            "pushNotifyYn":"N",
            "mailNotifyYn":"N",
            "clksIpFilteringYn":"N",
            "regYmdt":"2019-10-20 02:30:00",
            "modYmdt":"2019-10-20 02:30:00"
        },
        {
            "idx":2,
            "nm":"쿠팡 전자제품 (100만원 이상)",
            "memo":"100만원 이상 제품",
            "linkCnt":68,
            "blockOverseasSticsYn":"N",
            "notfSubscYn":"Y",
            "kakaoNotifyYn":"N",
            "pushNotifyYn":"Y",
            "mailNotifyYn":"N",
            "clksIpFilteringYn":"Y",
            "regYmdt":"2019-10-21 15:30:20",
            "modYmdt":"2019-10-22 11:20:50"
        }
    ]
}
Response:
필드설명유형
code응답 코드 (0:성공)int
message응답 메시지, 응답 코드가 0이 아닐 경우 관련 메시지가 리턴됨.string
result 그룹 목록:
필드필드 설명설명유형
idx그룹ID-int
nm이름-string
memo메모-string
linkCnt링크 수그룹에 연결된 링크 수int
blockOverseasSticsYn해외통계 차단Y:사용함, N:사용 안함Y or N
notfSubscYn푸시구독Y:사용함, N:사용 안함Y or N
kakaoNotifyYn클릭 수 카톡 알림Y:사용함, N:사용 안함Y or N
pushNotifyYn클릭 수 푸시 알림Y:사용함, N:사용 안함Y or N
mailNotifyYn클릭 수 메일 알림Y:사용함, N:사용 안함Y or N
clksIpFilteringYn클릭 수 IP 필터링Y:사용함, N:사용 안함Y or N
regYmdt생성 날짜그룹이 생성된 날짜Date
modYmdt수정 날짜그룹이 수정된 날짜Date
array

Validar enlaces con fechas de caducidad, contraseñas y clics máximos permitidos

Esta API está disponible en el plan Premium.

Cuando restringes el acceso a un enlace, estableces una fecha de caducidad, una contraseña y un número máximo de clics permitidos.
Si los usuarios hacen clic en un enlace generado por Vivoldi, está bien, pero si van directamente a una URL larga en su navegador, no hay manera de validarlo.
Vivoldi proporciona un SDK de JavaScript independiente para resolver este problema.

Cuando añades el SDK a una página con un enlace largo, el SDK recupera la información del enlace y comprueba la fecha de caducidad, la contraseña y el número máximo de clics permitidos.
Redirige de nuevo al enlace corto de Vivoldi o bloquea el acceso.

Añada el script proporcionado por Vivoldi a la página de su evento o promoción entre ... y valídelo fácilmente con una sola línea de código.

Añada el script de Vivoldi a su página como se muestra a continuación:

<html>
<head>
<title>샘플 페이지</title>
<script src="https://opencdn.vivoldi.com/js/v1/link.validate.min.js?v=202401191" type="text/javascript"></script>
<script>
const linkId = 'xY5h';   // 생성한 링크ID
const domain = 'https://vvd.bz';   // 링크 도메인 (vvd.bz 또는 vvd.im)
const apiKey = 'oc3w9m4ytso9mv5e8yse9XXXXXXXXXX';   // 귀하의 API Key
vvdLinkValidate(linkId, domain, apiKey);   // 비볼디에서 제공하는 SDK의 함수 호출
</script>
</head>

<body>
.
.
.
</body>
</html>
Request:
Get /api/validate/v1/link HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/x-www-form-urlencoded
Request 항목 설명:
필드필드 설명설명필수유형
linkId링크 ID 유효기간, 비밀번호, 최대 클릭 허용 수가 설정된 링크의 ID string
domain도메인 생성된 링크의 도메인 string
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnValidate" type="button">Get validate</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnValidate").on('click', function(evt){
		evt.preventDefault();

		$.ajax({
			type: 'GET',
			url: 'https://vivoldi.com/api/validate/v1/link?linkId=4Rug&domain=https://vvd.bz',
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				console.log(res.result);
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$linkId = "4Rug";
$domain = "https://vvd.bz";
$url = "https://vivoldi.com/api/validate/v1/link?linkId=$linkId&domain=$domain";

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class LinkValidate {
	public static void main(String[] args) {
		try (HttpClient client = HttpClient.newBuilder().build()) {
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/validate/v1/link?linkId=4Rug&domain=https://vvd.bz"))
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .GET()
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println(json.getString("result"));
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
	}
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":"",
    "result": {
        "linkId": "xY5h",
        "domain": "https://vvd.bz",
        "expireUseYn": "N",
        "expireYn": "N",
        "expireUrl": "https://",
        "acesMaxUseYn": "Y",
        "acesMaxYn": "Y",
        "acesMaxCnt": 1000,
        "acesCnt": 1,
        "pernCnt": 1,
        "agentKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "url": "https://vvd.bz/xY5h",
        "pwdUseYn": "Y",
        "pwdConfirmYn: "Y"
    }
}
Response 항목 설명:
필드설명유형
code응답 코드 (0:성공)int
message응답 메시지, 응답 코드가 0이 아닐 경우 관련 메시지가 리턴됨.string
result
필드필드 설명설명유형
linkId링크ID-string
domain도메인-string
expireUseYn유효기간 설정여부 Y:유효기간 설정됨, N:유효기간이 설정되지 않음.
링크 그룹에 유효기간이 설정되어 있을 경우 링크의 유효기간은 무시됩니다.
Y or N
expireYn유효기간 만료여부Y:유효기간 만료됨, N:유효기간이 만료되지 않음Y or N
expireUrl유효기간 만료URL 유효기간이 만료될 경우 이동될 URL
링크 그룹에 유효기간 만료URL이 설정된 경우 링크의 만료URL은 무시됩니다.
string
acesMaxUseYn최대 클릭 허용 수 설정 여부 Y:최대 클릭 허용 수가 설정됨, N:최대 클릭 허용 수가 설정되지 않음.
링크 그룹에 최대 클릭 허용 수가 설정된 경우 링크의 허용 수 설정는 무시됩니다.
Y or N
acesMaxYn최대 클릭 허용 수 초과여부Y:최대 클릭 허용 수 초과됨, N:최대 클릭 허용 수 초과안됨Y or N
acesMaxCnt최대 클릭 허용 수설정된 최대 클릭 허용 수int
acesCnt링크 클릭 수현재까지 클릭된 수int
pernCnt링크 사람 수클릭한 사람 수int
agentKey사용자 키 값이 존재할 경우 비볼디의 짧은 링크를 클릭한 상태입니다.
값이 없을 경우 브라우저에서 긴 URL로 바로 접속한 경우입니다.
값이 존재할 경우 3시간 후 자동으로 값이 초기화됩니다.
string
url단축URL비볼디의 짧은 링크string
pwdUseYn비밀번호 설정여부 Y: 비밀번호가 설정됨, N:비밀번호가 설정되지 않음
링크 그룹에 비밀번호가 설정된 경우 링크의 비밀번호는 무시됩니다.
Y or N
pwdConfirmYn비밀번호 인증 완료여부 Y: 사용자가 단축URL에 접속한 후 비밀번호를 입력하고 인증에 성공함.
N:브라우저에서 긴 URL로 접속하였거나 비밀번호 인증이 완료되지 않은 상태.
비밀번호 인증이 완료된 후 3시간이 경과하면 값이 N으로 처리되므로 다시 인증을 해야 합니다.
Y or N
object

Crear cupón

Esta API está disponible a partir del plan Personal.

Crear un cupón de descuento. Si desea crear varios cupones a la vez, créelos en el panel de control.
No puede cargar imágenes de cupones utilizando la API.
En este caso, puede cargar imágenes de cupones cuando cree un grupo de cupones en el panel de control y especifique el grupo cuando cree el cupón.
Si especifica un grupo de cupones al crear un cupón, se ignorarán algunos ajustes y se aplicarán los ajustes del grupo de cupones.

Request:
Post /api/coupon/v1/create HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request:
CamposDescripción de los camposDescripciónRequeridoTipo
cpnNoNúmero de cupón Un número de cupón de 8 a 16 dígitos compuesto por letras mayúsculas y números. No se permiten caracteres especiales.
Si el valor está vacío, el número de cupón se genera automáticamente por el sistema.
string
grpIdxGrupo de cupón Los grupos de cupones permiten categorizar y administrar los cupones. Si hay un ajuste de grupo y de cupón al mismo tiempo, prevalece el ajuste del cupón.
Puedes ver el IDX de grupo en la página de grupos de cupones de tu panel.
Valor por defecto: 0
int
tmplIdxPlantilla de cupón Las plantillas de cupón describen para qué sirve el cupón, cómo usarlo y cualquier condición.
Puedes ver el IDX de la plantilla en la página de plantillas de cupones del panel.
Valor por defecto: 0
int
nmNombre del cupón El nombre del cupón aparece en la página del cupón. string
discTypeIdxTipo de descuento Establece el tipo de descuento (porcentaje o cantidad).
457: Descuento por porcentaje (%), 458: Descuento por cantidad
Descuento por porcentaje: Aplica un descuento en porcentaje al cupón.
Descuento por cantidad: Aplica un descuento por monto fijo.
int
discValor del descuento Introduce un valor entre 1% y 100% si el descuento es por porcentaje (457).
Introduce el monto si el descuento es por cantidad (458).
double
discCurrencyMoneda del descuento Puedes definir la moneda si el descuento es por cantidad (458).
KRW: won coreano, USD: dólar estadounidense, JPY: yen japonés, EUR: euro.
Valor por defecto: KRW
string
strtYmdFecha de inicio de validez Indica la fecha desde la cual el cupón es válido.
Valor de 10 dígitos en formato aaaa-mm-dd.
Ejemplo: 2024-10-01
date
endYmdFecha de vencimiento Indica la fecha hasta la cual el cupón es válido.
Valor de 10 dígitos en formato aaaa-mm-dd.
Ejemplo: 2024-12-31
date
onsiteYnCupón presencial Si el valor es Y, la página del cupón muestra un botón para canjearlo presencialmente.
El usuario debe mostrar el cupón al personal de tienda para canjearlo.
Útil para tiendas físicas.
Valor por defecto: N
Y o N
onsitePwdContraseña de canje presencial Si defines una contraseña, el personal deberá ingresarla para canjear el cupón.
El usuario no puede canjear el cupón por sí mismo.
string
memoNotas Se puede usar para la gestión interna de cupones.
No es visible para los usuarios.
string
urlURL Si introduces una URL, la página del cupón mostrará un botón “Canjear cupón” que dirige a esa URL.
Si se sube una imagen del cupón, al hacer clic en la imagen también se accede a la URL.
string
useLimitLímite máximo de canjes por persona Establece el número máximo de veces que un cupón puede ser canjeado por una persona.
Para la API de Vivoldi, debes definir un rango entre 2 y 5, junto con el ID de usuario.
Al gestionar manualmente desde el panel, puedes elegir “Ilimitado” o “1 vez”.
Si eliges “Ilimitado”, cualquiera puede canjear el cupón sin límite.
0: Ilimitado, 1: 1 vez, 2: 2 veces, 3: 3 veces, 4: 4 veces, 5: 5 veces
int
colorColor del texto Establece el color del texto del cupón en la página.
Se debe ingresar un valor HEX de hasta 9 dígitos (con transparencia).
Valor por defecto: #4F4F4FFF
string
backgroundColor de fondo En la página de cupones, define el color de fondo del cupón.
Se debe ingresar un valor HEX de hasta 9 dígitos (con transparencia).
Valor por defecto: #FFFFFFFF
string
userIdID de usuario Se usa para saber quién emitió y canjeó el cupón.
Si el límite de canjes por persona es entre 2 y 5, debes ingresar el ID de usuario.
Por lo general, es el ID de usuario que se registró en tu web.
string
userNmNombre de usuario Si ya sabes a quién quieres entregar el cupón, introduce el nombre del usuario.
Esto ayuda a gestionar la emisión y el canje.
string
userPhnnoContacto del usuario Define el número de contacto del usuario que canjeará el cupón. string
userEmlEmail del usuario Define el correo electrónico del usuario que canjeará el cupón. string
userEtc1Otra información del usuario 1 Define información adicional del usuario para fines internos. string
userEtc2Otra información del usuario 2 Define información adicional del usuario para fines internos. string
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnCreateCoupon" type="button">Create Coupon</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnCreateCoupon").on('click', function(evt){
		evt.preventDefault();
		const data = JSON.stringify({
			'cpnNo':'',  // auto create
			'grpIdx':271,
			'tmplIdx':0,
			'nm':'5,000원 할인 쿠폰',
			'discTypeIdx':458,
			'disc':5000,
			'strtYmd':'2024-10-01',
			'endYmd':'2025-12-31',
			'memo':'신규 회원가입, Address:211.111.222.33',
			'url':'https://bestshop.com/product/bags/42316',
			'useLimit':1,
			'userId':'att78z',
			'userNm':'홍길동',
			'userPhnno':'010-1111-2345',
			'userEml':'test@gmail.com',
			'userEtc1':'VIP 회원'
		});
		$.ajax({
			type: 'POST',
			url: 'https://vivoldi.com/api/coupon/v1/create',
			data: data,
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			contentType: 'application/json; charset=utf-8',
			dataType: 'json',
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				alert('Coupon number: ' + res.result);
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$url = "https://vivoldi.com/api/coupon/v1/create";
$params = array (
	"cpnNo" => "",  // auto create
	"grpIdx" => 271,
	"tmplIdx" => 0,
	"nm" => "5,000원 할인 쿠폰",
	"discTypeIdx" => 458,
	"disc" => 5000,
	"strtYmd" => "2024-10-01",
	"endYmd" => "2025-12-31",
	"memo" => "신규 회원가입, Address:211.111.222.33",
	"url" => "https://bestshop.com/product/bags/42316",
	"useLimit" => 1,
	"userId" => "att78z",
	"userNm" => "홍길동",
	"userPhnno" => "010-1111-2345",
	"userEml" => "test@gmail.com",
	"userEtc1" => "VIP 회원"
);
$body = json_encode($params);

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX",
	"Content-Type: application/json"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class CreateCoupon {
    public static void main(String[] args) {
        try (HttpClient client = HttpClient.newBuilder().build()) {
            JSONObject params = new JSONObject();
            params.put("cpnNo", "");  // auto create
			params.put("grpIdx", 271);
			params.put("tmplIdx", 0);
			params.put("nm", "5,000원 할인 쿠폰");
			params.put("discTypeIdx", 458);
			params.put("disc", 5000);
			params.put("strtYmd", "2024-10-01");
			params.put("endYmd", "2025-12-31");
			params.put("memo", "신규 회원가입, Address:211.111.222.33");
			params.put("url", "https://bestshop.com/product/bags/42316");
			params.put("useLimit", 1);
			params.put("userId", "att78z");
			params.put("userNm", "홍길동");
			params.put("userPhnno", "010-1111-2345");
			params.put("userEml", "test@gmail.com");
			params.put("userEtc1", "VIP 회원");

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/coupon/v1/create"))
                .header("Content-Type", "application/json")
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .POST(HttpRequest.BodyPublishers.ofString(params.toString()))
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println("Coupon number: " + json.getString("result"));
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
    }
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":"",
    "result":"ZJLF0399WQBEQZJM"
}
Response:
CamposDescripciónTipo
codeCódigo de respuesta (0:Éxito)int
messageEl mensaje de respuesta, o un mensaje relacionado si el código de respuesta es distinto de cero.string
resultValor de la respuesta (número de cupón)string

Editar cupón

Esta API está disponible a partir del plan Personal.

Cambiar la información del cupón creado.
Al asignar un grupo a un cupón, se ignoran algunos ajustes y se aplican los del grupo de cupones.
Para los cupones que ya han sido canjeados, sólo puede editar las "Notas" pero no el resto de la información.

Request:
Put /api/coupon/v1/edit HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request:
CamposDescripción de los camposDescripciónRequeridoTipo
cpnNo El número de cupón que desea actualizar. Ingrese solo el número de cupón, sin incluir el carácter "-". string
grpIdx Los grupos de cupones se utilizan para gestionar la categorización de los cupones. Si existen configuraciones tanto de grupo como de cupón, se ignorará la configuración del cupón.
Puede encontrar el IDX del grupo en la página de grupos de cupones de su panel de control.
Valor predeterminado: 0
int
tmplIdx Las plantillas de cupones se utilizan para proporcionar a los usuarios una descripción, instrucciones de uso y precauciones para el cupón.
Puede encontrar el IDX de la plantilla en la página de plantillas de cupones de su panel de control.
Valor predeterminado: 0
int
nm El nombre del cupón se muestra en la página del cupón. string
discTypeIdx Establece el tipo de descuento del cupón (porcentaje o monto).
457: Descuento por porcentaje (%), 458: Descuento por monto
Descuento por porcentaje: se utiliza para ofrecer un descuento en porcentaje.
Descuento por monto: se utiliza para ofrecer un descuento por una cantidad fija.
int
disc Cuando el tipo de descuento es porcentaje (457), ingrese un valor entre 1% y 100%.
Cuando el tipo de descuento es monto (458), ingrese el monto del descuento.
double
discCurrency Puede establecer la unidad monetaria cuando el tipo de descuento es monto (458).
KRW: won coreano, USD: dólar estadounidense, JPY: yen japonés, EUR: euro.
Valor predeterminado: KRW
string
strtYmd Establezca la fecha de inicio del período de validez del cupón.
Valor de 10 dígitos en formato aaaa-mm-dd.
Ejemplo: 2024-10-01
date
endYmd Establezca la fecha de vencimiento del período de validez del cupón.
Valor de 10 dígitos en formato aaaa-mm-dd.
Ejemplo: 2024-12-31
date
onsiteYn Si este valor es Y, se mostrará un botón en la página del cupón para canjearlo.
El usuario muestra el cupón a un empleado de la tienda, quien lo canjea. Esto es útil si opera una tienda física.
Y or N
onsitePwd Si establece una contraseña, el personal de la tienda debe ingresarla al canjear el cupón.
Los usuarios no pueden canjear el cupón por sí mismos.
string
memo Se utiliza para la gestión interna de los cupones.
Las notas no son visibles para los usuarios.
string
url Si ingresa una URL, aparecerá un botón "Canjear cupón" en la página del cupón y lo redirigirá a la URL ingresada al hacer clic.
Si se carga una imagen del cupón, al hacer clic en la imagen también se redirigirá a la URL.
string
useLimit Establezca la cantidad máxima de veces que se puede usar un cupón por persona.
Cuando use la API REST de Vivoldi para procesar los canjes de cupones, se requiere un valor entre 2 y 5.
En este caso, se debe proporcionar el ID del usuario.
Al gestionar el canje manualmente desde el panel de control, puede elegir entre "Ilimitado" o "1 vez".
Si elige "Ilimitado", cualquiera puede canjear el cupón sin límite de uso.
0: Ilimitado, 1: 1 vez, 2: 2 veces, 3: 3 veces, 4: 4 veces, 5: 5 veces
int
color Establece el color del texto del cupón en la página.
Debe ingresarse como un valor HEX de hasta 9 dígitos, incluida la transparencia.
Valor predeterminado: #4F4F4FFF
string
background Establece el color de fondo del cupón en la página.
Debe ingresarse como un valor HEX de hasta 9 dígitos, incluida la transparencia.
Valor predeterminado: #FFFFFFFF
string
userId Se utiliza para gestionar quién recibió y quién canjeó el cupón.
Si el valor para el uso máximo del cupón por persona es de 2 a 5, se requiere el ID del usuario.
Por lo general, ingrese el ID de inicio de sesión del miembro registrado en su sitio web.
string
userNm Si ya sabe quién recibirá el cupón, ingrese el nombre del usuario que lo usará.
Esto es necesario para gestionar la emisión y el canje del cupón.
string
userPhnno Establezca la información de contacto del usuario que canjeará el cupón. string
userEml Establezca el correo electrónico del usuario que canjeará el cupón. string
userEtc1 Establezca información adicional sobre el usuario para fines administrativos internos. string
userEtc2 Establezca información adicional sobre el usuario para fines administrativos internos. string
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnEditCoupon" type="button">Edit Coupon</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnEditCoupon").on('click', function(evt){
		evt.preventDefault();
		const data = JSON.stringify({
			'cpnNo':'ZJLF0399WQBEQZJM',
			'nm':'40% 할인 쿠폰',
			'discTypeIdx':457,
			'disc':40
		});
		$.ajax({
			type: 'PUT',
			url: 'https://vivoldi.com/api/coupon/v1/edit',
			data: data,
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			contentType: 'application/json; charset=utf-8',
			dataType: 'json',
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				alert('success!');
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$url = "https://vivoldi.com/api/coupon/v1/edit";
$params = array (
	"cpnNo" => "ZJLF0399WQBEQZJM",
	"nm" => "40% 할인 쿠폰",
	"discTypeIdx" => 457,
	"disc" => 40
);
$body = json_encode($params);

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX",
	"Content-Type: application/json"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class EditCoupon {
    public static void main(String[] args) {
        try (HttpClient client = HttpClient.newBuilder().build()) {
            JSONObject params = new JSONObject();
            params.put("cpnNo", "ZJLF0399WQBEQZJM");
			params.put("nm", "40% 할인 쿠폰");
			params.put("discTypeIdx", 457);
			params.put("disc", 40);

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/coupon/v1/edit"))
                .header("Content-Type", "application/json")
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .PUT(HttpRequest.BodyPublishers.ofString(params.toString()))
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println("Success!");
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
    }
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":"",
    "result":null
}
Response:
CamposDescripciónTipo
codeCódigo de respuesta (0:Éxito)int
messageEl mensaje de respuesta, o un mensaje relacionado si el código de respuesta es distinto de cero.string

Eliminar cupón

Esta API está disponible a partir del plan Personal.

Eliminar el cupón creado.
Para eliminar varios cupones a la vez, utilice el panel de control.

Request:
Delete /api/coupon/v1/remove HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: -
Request:
CamposDescripción de los camposDescripciónRequeridoTipo
cpnNoCoupon number El número de cupón que se va a eliminar. string
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnDeleteCoupon" type="button">Delete Coupon</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnDeleteCoupon").on('click', function(evt){
		evt.preventDefault();

		$.ajax({
			type: 'DELETE',
			url: 'https://vivoldi.com/api/coupon/v1/remove?cpnNo=ZJLF0399WQBEQZJM',
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				alert('Success!');
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$cpnNo = "ZJLF0399WQBEQZJM";
$url = "https://vivoldi.com/api/coupon/v1/remove?cpnNo=$cpnNo";

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class DeleteCoupon {
	public static void main(String[] args) {
		try (HttpClient client = HttpClient.newBuilder().build()) {
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/link/v1/remove?cpnNo=ZJLF0399WQBEQZJM"))
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .DELETE()
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println("Success!");
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
	}
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":""
}
Response:
CamposDescripciónTipo
codeCódigo de respuesta (0:Éxito)int
messageEl mensaje de respuesta, o un mensaje relacionado si el código de respuesta es distinto de cero.string

Validar cupón

Esta API está disponible a partir del plan Personal.

Se utiliza para comprobar y validar si el cupón es válido antes de procesar "Canjear cupón".
Compruebe la validación del cupón como se muestra a continuación.
  • Validar la fecha de caducidad del cupón. (fecha de inicio y fecha de caducidad)
  • Validar el número máximo de cupones por persona.
  • Validar el canje del cupón.
Request:
Get /api/coupon/v1/validate HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request 항목 설명:
CamposDescripción de los camposDescripciónRequeridoTipo
cpnNoCoupon number El número de cupón para validar.
Si la validación falla, revise el mensaje en la respuesta.
string
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnValidate" type="button">Get validate</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnValidate").on('click', function(evt){
		evt.preventDefault();

		$.ajax({
			type: 'GET',
			url: 'https://vivoldi.com/api/coupon/v1/validate?cpnNo=ZJLF0399WQBEQZJM',
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				console.log('사용 가능한 쿠폰입니다.');
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$cpnNo = "ZJLF0399WQBEQZJM";
$url = "https://vivoldi.com/api/coupon/v1/validate?cpnNo=$cpnNo";

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     echo "사용 가능한 쿠폰입니다.";
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class ValidateCoupon {
	public static void main(String[] args) {
		try (HttpClient client = HttpClient.newBuilder().build()) {
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/coupon/v1/validate?cpnNo=ZJLF0399WQBEQZJM"))
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .GET()
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println("사용 가능한 쿠폰입니다.");
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
	}
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":"",
    "result": null
}
Response 항목 설명:
CamposDescripciónTipo
codeCódigo de respuesta (0:Éxito)int
messageEl mensaje de respuesta, o un mensaje relacionado si el código de respuesta es distinto de cero.string

Utilizar cupón

Esta API está disponible a partir del plan Personal.

Aunque puede gestionar el proceso "canjear cupón" manualmente en la lista de cupones de su panel de control, esta API le permite automatizarlo llamándolo cuando un usuario canjea un cupón en su sitio web.

Request:
Put /api/coupon/v1/use HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request:
CamposDescripción de los camposDescripciónRequeridoTipo
cpnNoCoupon number Número de cupón “canjeado” a procesar.
Ingrese solo el número de cupón, excluyendo el signo “-”.
string
onsitePwdOn-site coupon usage password Si se ha configurado una contraseña para el uso en tienda, ingrese la contraseña establecida.
Si la contraseña es incorrecta, no podrá usar el cupón.
string
userIdUser ID Se utiliza para gestionar quién ha emitido y canjeado los cupones.
Si el valor del número máximo de canjes por persona es entre 2 y 5, debe ingresar el ID de usuario.
Normalmente, introduzca el ID de inicio de sesión del miembro registrado en su sitio web.
string
memoNotes Puede ingresar notas para gestionar los canjes de cupones.
Ingrese la dirección IP del usuario, la página y el servicio donde se canjeó el cupón, y otra información.
Cuando el número máximo de canjes por persona es ilimitado, no sabrá quién canjeó el cupón, por lo que puede gestionar por nombre de usuario o nota.
string
Examples:
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8"/>
	<script src="https://code.jquery.com/jquery-3.4.1.min.js" crossorigin="anonymous"></script>
</head>

<body>

<form id="exampleForm">
	<button id="btnUseCoupon" type="button">Use Coupon</button>
</form>

<script type="text/javascript">
$(function(){
	$("#btnUseCoupon").on('click', function(evt){
		evt.preventDefault();
		const data = JSON.stringify({
			'cpnNo':'ZJLF0399WQBEQZJM',
			'userId':'x77hu',
			'memo':'IP Address: 210.123.111.222, Request Page: example.com/shop/bags/p112233'
		});
		$.ajax({
			type: 'PUT',
			url: 'https://vivoldi.com/api/coupon/v1/use',
			data: data,
			headers: {'Authorization':'APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX'},
			contentType: 'application/json; charset=utf-8',
			dataType: 'json',
			timeout: 5000
		}).done(function(res){
			if (res.code === 0) {
				alert('success!');
			} else {
				alert('code: ' + res.code + ', message: ' + res.message);
			}
		}).fail(function(xhr, textStatus, e){
			alert('error: ' + e);
		});
	});
});
</script>

</body>
</html>
<?php
$url = "https://vivoldi.com/api/coupon/v1/use";
$params = array (
	"cpnNo" => "ZJLF0399WQBEQZJM",
	"userId" => "x77hu",
	"memo" => "IP Address: 210.123.111.222, Request Page: example.com/shop/bags/p112233"
);
$body = json_encode($params);

$headers = array(
	"Authorization: APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX",
	"Content-Type: application/json"
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10000);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);

$result = curl_exec($ch);

if ($result === FALSE) {
     echo "Error sending: " . curl_error($ch);
} else {
     print_r($result);
}
curl_close($ch);
?>
package com.example;

import org.json.JSONObject;
import org.springframework.http.HttpStatus;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

public class UseCoupon {
    public static void main(String[] args) {
        try (HttpClient client = HttpClient.newBuilder().build()) {
            JSONObject params = new JSONObject();
            params.put("cpnNo", "ZJLF0399WQBEQZJM");
			params.put("userId", "x77hu");
			params.put("memo", "IP Address: 210.123.111.222, Request Page: example.com/shop/bags/p112233");

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://vivoldi.com/api/coupon/v1/use"))
                .header("Content-Type", "application/json")
                .header("Authorization", "APIKey oc3w9m4ytso9mv5e8yse9XXXXXXXXXX")
                .PUT(HttpRequest.BodyPublishers.ofString(params.toString()))
                .build();

            HttpResponse<String> response;
            try {
                response = client.send(request, HttpResponse.BodyHandlers.ofString());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

            if (response != null) {
                if (response.statusCode() == HttpStatus.OK.value()) {
                    String jsonString = response.body();
                    if (jsonString != null && !jsonString.isEmpty()) {
                        JSONObject json = new JSONObject(jsonString);
                        if (json.getInt("code") == 0) {
                            System.out.println("Success!");
                        } else {
                            System.out.println("Failed: " + String.format("[%d] %s", json.getInt("code"), json.getString("message")));
                        }
                    }
                }
            }
        }
    }
}
Response:
HTTP/1.1 200 OK
Content-type: application/json;charset=UTF-8
{
    "code":0,
    "message":"",
    "result":null
}
Response:
CamposDescripciónTipo
codeCódigo de respuesta (0:Éxito)int
messageEl mensaje de respuesta, o un mensaje relacionado si el código de respuesta es distinto de cero.string

Enviar mensajes push

Esta API es independiente del servicio Acortador de URL de Vivoldi y está destinada a cualquier persona que gestione un sitio web.

Para enviar mensajes push a los usuarios que visitan su sitio web, el usuario debe aceptar el "permiso de notificación" en su navegador web.
Si rechazan el permiso de notificación, no podrá enviar mensajes push.

Después de instalar el SDK de JavaScript proporcionado por Vivoldi en su sitio web, el navegador web mostrará una ventana emergente para "Permisos de notificación" cuando un usuario visite su sitio web.
Si el usuario acepta el permiso, los datos de notificación aparecerán en la página "Mensajes Push -> Enviar push de sitio web" del panel de control.
Por ejemplo, si 100 usuarios han aceptado los permisos de notificación en su sitio web, verá 100 datos en la lista.
Cuando envíe un mensaje push desde el panel de control, el mensaje se enviará a todos los usuarios que aparecen en la lista.

Cualquiera puede instalar el SDK de JavaScript proporcionado por Vivoldi para recopilar los datos de los usuarios.
Sin embargo, necesitarás tener dinero en tu cuenta para enviar mensajes push.
El coste por enviar mensajes push es de 10 KRW por mensaje, o puedes contratar una suscripción mensual para enviar un número ilimitado de mensajes.

Instalar el SDK de JavaScript es tan sencillo como añadirlo entre el <head>...</head>.

<html>
<head>
<title>example page</title>
<script src="https://opencdn.vivoldi.com/js/webpush.min.js?v=202502051" type="text/javascript"></script>
<script>
const apiKey = 'oc3w9m4ytso9mv5e8yse9XXXXXXXXXX';   // your api key
const publicKey = 'XXXXXYTRlpG8mXXXXXiuBZ6BtjyOfgPsDArFYWF2PxZbY4egmDNias1gEfN_5wftScr39K8BbcjXXXXX';   // "푸시 메시지 -> 도메인 관리" 페이지에서 등록한 도메인의 Public Key
const params = {apiKey:apiKey, publicKey:publicKey};
webpush.register(params);   // 알림 권한 팝업 창 띄우기 (이미 권한을 허용하였다면 팝업이 표시되지 않습니다)
</script>
</head>

<body>
.
.
.
</body>
</html>

Las claves API pueden crearse en la página "Developer API" de su panel de control, y la publicKey puede encontrarse en la lista una vez que haya registrado su dominio en la página "Push Messages -> Domain Management".

Una vez que todo esté listo, lo último que debe hacer es crear un nuevo archivo sw.min.js y subirlo a la raíz de su sitio web.
Por ejemplo: https://example.com/sw.min.js

Al acceder a la ruta anterior, el script debe aparecer en el navegador web para que la notificación funcione correctamente.
Copie y pegue el código siguiente en su archivo sw.min.js recién creado.

sw.min.js:
'use strict';const a0_0x5374e1=a0_0xe038;(function(_0x1227c0,_0x51a60b){const _0x31ab77=a0_0xe038,_0x20d84d=_0x1227c0();while(!![]){try{const _0x12de05=parseInt(_0x31ab77(0x189))/0x1+-parseInt(_0x31ab77(0x188))/0x2+-parseInt(_0x31ab77(0x175))/0x3+parseInt(_0x31ab77(0x196))/0x4+parseInt(_0x31ab77(0x191))/0x5*(parseInt(_0x31ab77(0x179))/0x6)+parseInt(_0x31ab77(0x190))/0x7*(-parseInt(_0x31ab77(0x18a))/0x8)+parseInt(_0x31ab77(0x181))/0x9*(parseInt(_0x31ab77(0x173))/0xa);if(_0x12de05===_0x51a60b)break;else _0x20d84d['push'](_0x20d84d['shift']());}catch(_0x40c5f5){_0x20d84d['push'](_0x20d84d['shift']());}}}(a0_0x3c7d,0xc9d27));function a0_0xe038(_0x596680,_0x1be660){const _0x3c7dc3=a0_0x3c7d();return a0_0xe038=function(_0xe03880,_0x22c065){_0xe03880=_0xe03880-0x170;let _0x16ce5f=_0x3c7dc3[_0xe03880];return _0x16ce5f;},a0_0xe038(_0x596680,_0x1be660);}function a0_0x3c7d(){const _0x45d9ad=['waitUntil','notification','20673aXYLrA','navigator','title','focus','icon','toLowerCase','image','168378lbyyZD','193689SqVukM','41896sLUVSk','macintosh','close','registration','userAgent','body','1253fKQvUq','2054765fkWElD','install','includes','openWindow','badge','4620004XrYmFj','notificationclick','ko-KR','url','showNotification','parse','바로가기','window','platform','mac','actions','1490bVkBER','action','1993722LznGRH','navigate','button','activate','12Yewkpl','push','matchAll','data','then','addEventListener'];a0_0x3c7d=function(){return _0x45d9ad;};return a0_0x3c7d();}self['addEventListener'](a0_0x5374e1(0x192),_0x220cef=>{self['skipWaiting']();}),self[a0_0x5374e1(0x17e)](a0_0x5374e1(0x178),_0x4e57ea=>{const _0x4e29f9=a0_0x5374e1;_0x4e57ea[_0x4e29f9(0x17f)](clients['claim']());}),self[a0_0x5374e1(0x17e)](a0_0x5374e1(0x17a),function(_0x5b8772){const _0x578b75=a0_0x5374e1,_0x6a0810=JSON[_0x578b75(0x19b)](_0x5b8772[_0x578b75(0x17c)]['text']()),_0x41c647=navigator['language'],_0x3709b8=_0x41c647==='ko'||_0x41c647===_0x578b75(0x198),_0x398015=self[_0x578b75(0x182)]['platform']['toLowerCase']()[_0x578b75(0x193)](_0x578b75(0x171)),_0x570dee=self[_0x578b75(0x182)]['userAgent']['toLowerCase']()[_0x578b75(0x193)](_0x578b75(0x18b)),_0x417e2c={'tag':'renotify','renotify':!![],'body':_0x6a0810[_0x578b75(0x18f)],'icon':_0x6a0810[_0x578b75(0x185)],'badge':_0x6a0810[_0x578b75(0x195)],'requireInteraction':!![],'vibrate':[0x12c,0x64,0x190,0xc8,0x1f4],'data':_0x6a0810,'actions':[{'action':'go','type':_0x578b75(0x177),'title':_0x3709b8?_0x578b75(0x19c):'GO'},{'action':_0x578b75(0x18c),'type':'button','title':_0x3709b8?'닫기':'CLOSE'}]};_0x6a0810[_0x578b75(0x187)]&&(_0x417e2c[_0x578b75(0x187)]=_0x6a0810[_0x578b75(0x187)]),(_0x398015||_0x570dee)&&delete _0x417e2c[_0x578b75(0x172)],_0x5b8772['waitUntil'](self[_0x578b75(0x18d)][_0x578b75(0x19a)](_0x6a0810[_0x578b75(0x183)],_0x417e2c));}),self[a0_0x5374e1(0x17e)](a0_0x5374e1(0x197),function(_0x278188){const _0x1737d2=a0_0x5374e1;_0x278188['notification'][_0x1737d2(0x18c)]();const _0x381024=self['navigator'][_0x1737d2(0x170)][_0x1737d2(0x186)]()[_0x1737d2(0x193)]('mac'),_0x419533=self[_0x1737d2(0x182)][_0x1737d2(0x18e)][_0x1737d2(0x186)]()[_0x1737d2(0x193)](_0x1737d2(0x18b));if(_0x381024||_0x419533)_0x278188[_0x1737d2(0x17f)](clients[_0x1737d2(0x17b)]({'type':_0x1737d2(0x19d)})[_0x1737d2(0x17d)](_0x55a8eb=>{const _0x25611a=_0x1737d2;_0x55a8eb['length']>0x0?(_0x55a8eb[0x0][_0x25611a(0x176)](_0x278188[_0x25611a(0x180)][_0x25611a(0x17c)][_0x25611a(0x199)]),_0x55a8eb[0x0][_0x25611a(0x184)]()):clients[_0x25611a(0x194)](_0x278188[_0x25611a(0x180)]['data'][_0x25611a(0x199)]);}));else switch(_0x278188[_0x1737d2(0x174)]){case'go':_0x278188[_0x1737d2(0x17f)](clients[_0x1737d2(0x194)](_0x278188[_0x1737d2(0x180)][_0x1737d2(0x17c)][_0x1737d2(0x199)]));break;case _0x1737d2(0x18c):break;default:_0x278188['waitUntil'](clients[_0x1737d2(0x194)](_0x278188[_0x1737d2(0x180)][_0x1737d2(0x17c)][_0x1737d2(0x199)]));}});

Ahora, cuando acceda a su sitio web, debería ver el permiso de notificación.
Cuando haya permitido el permiso de notificación, compruebe si está viendo los datos de notificación en la página "Website Push Sending" de su panel de Vivoldi.