URL Shortener Developer API

Introduction to the developer API

Vivoldi provides a dedicated REST API for your platform or system.
The REST API gives you the freedom to create links from your own servers or mobile apps without having to create links from the Vivoldi dashboard.

The provided REST API can be called from any development language and operating system, including JavaScript, PHP, Java, Android, and iOS.
Before calling the API, an API key must be generated, and the generated API key must be managed so that it is not exposed to others.

You can change your API key once a month, and changing your API key will not affect any links that have already been created.
All APIs are free to use and follow the request specifications set by Vivoldi, and API processing and response speeds vary depending on the plan.

If you get an HTTP 403 error after an API call, specify a separate User-agent value in the header.
Vivoldi blocks some User-agents.

단축url, url단축, 링크줄이기를 위한 개발자 REST API

How to call the API

Request:
Host: https://vivoldi.com/api HTTP/1.1
Authorization: APIKey {Your API Key}
Content-type: application/json
Simply add Authorisation, Content-type to your Http Header and call the API.
Response:
{
    "code": 0,
    "message": "",
    "result": Object
}
code - The response code, where 0 is success and any other value is a failure code.
message - The response message, an error message is returned if the response code is non-zero.
result - The response value, returned as a character or JSON object depending on the API type.
Please contact Vivoldi if you need REST API improvements or modifications.

Create link

Create 1 shortened link. If you want to create a large number of links, use the "Create Bulk Links" menu in your dashboard.

Request:
Post /api/link/v2/create HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request:
FieldsField DescriptionsDescriptionRequiredType
urlLong URLsThe long URL to be redirected to when the generated short link is clicked.string
domainDomain Link domain, if the value is empty, the vvd.bz domain is automatically selected.
If you are using a random domain from Vivoldi, or if you have integrated your own domain with Vivoldi, you can set that domain.
string
grpIdxGroup ID Setting a group ID will create a link to that group.
To check the GroupID, you need to call the "Group List" API to get it.
int
brandLinkIdBrand Link ID If you specify a value, a link will be created with that ID.
(If a branded link is set, the domain will be vvd.im, not vvd.bz)
If the value is empty, the linkID is generated automatically.
string
ttlLink Title If the value is empty, it is automatically saved as the webpage title of the long link. string
memoNotes You can set additional information that you need for administration without exposing it to users. string
notfSubscYnPush Link If the value is Y, when the generated link is clicked, a web push notification pop-up will be displayed before being taken to the long link, and a push message can be sent to all users who have allowed it, if the user has given permission for push notifications.
If they disagree or cancel the notification pop-up, they are immediately taken to the original long URL.
If no value is entered, the default value is N.
To learn more about push subscription links, take a look at the Web Push feature introduction page.
Y or N
clksIpFilteringYnIP filtering for clicks If the value is Y, then the number of link clicks from the same IP over a 24-hour period will be fixed at 1 instead of continuing to increase.
If the link is clicked again after midnight (12am), the click count will be +1.
The clicks IP filtering feature can only be set at the time of link creation and the value cannot be changed by subsequent link edits.
This feature is available starting with the Personal plan.
Y or N
pushNotifyYnPush notifications If the value is Y, you can receive clicks push notifications to mobile devices with the Vivoldi app installed whenever a link reaches the number of clicks set in the link settings on the "Settings -> Preferences" page.
This feature is available starting with the Personal plan.
Y or N
mailNotifyYnMail notifications If the value is Y, you can receive click count information to your Vivoldi subscribed email whenever you reach the number of link clicks set in the link settings on the "Settings -> Preferences" page.
This feature is available starting with the Personal plan.
Y or N
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:
FieldsDescriptionType
codeResponse code (0:Success)int
messageThe response message, or a related message if the response code is non-zero.string
resultResponse value (shortened link)string

Edit a link

Edit the short link you created.
You can only modify the link type if it is a URL; other types are not modified even if the API call succeeds.

Request:
Put /api/link/v2/edit HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request:
FieldsField DescriptionsDescriptionRequiredType
linkIdLink ID ID of the generated short link
Example:
If the address of the short link is "https://vvd.bz/fML", the link ID is fML.
string
domainDomain The domain of the short link address.
Example:
If the address of the short link is "https://vvd.bz/fML", the domain is https://vvd.bz. Important: The value https:// or http:// must be entered.
If you set it to a domain other than the domain of the generated short link, an error occurs.
string
grpIdxGroup ID Change the group of the generated link.
To find out the group ID, you need to call the "Group list" API.
int
urlLong URL Change a long URL.
You can change long URLs starting with the Premium plan.
string
ttlLink title If the value is empty, the link title is not modified. string
memoNotes You can set additional information for administration without exposing it to users.
If the value is empty, the note will not be modified.
string
notfSubscYnPush Link If the value is Y, clicking on the generated link will display a web push notification pop-up before being taken to the long link, and if the user has opted in to push notifications, you can send a push message to all users you have allowed.
If they disagree or cancel the notification pop-up, they are immediately taken to the original long URL.
If you don′t enter a value, then the default value is N.
To learn more about push subscription links, click here.
Y or N
pushNotifyYnPush notifications If the value is Y, you can receive clicks push notifications to mobile devices with the Vivoldi app installed whenever a link reaches the number of clicks set in the link settings on the "Settings -> Preferences" page.
This feature is available starting with the Personal plan.
Y or N
mailNotifyYnMail notifications If the value is Y, you can receive click count information to your Vivoldi subscribed email whenever you reach the number of link clicks set in the link settings on the "Settings -> Preferences" page.
This feature is available starting with the Personal plan.
Y or N
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:
FieldsDescriptionType
codeResponse code (0:Success)int
messageThe response message, or a related message if the response code is non-zero.string

Delete a link

Delete the short link you created.

Request:
Delete /api/link/v1/remove HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: -
Request:
FieldsField DescriptionsDescriptionRequiredType
linkIdLink ID ID of the generated short link
Example:
If the address of the short link is "https://vvd.bz/fML", the linkID is fML.
URLEncode is required if a branded LinkID is set (you set the LinkID yourself) and contains special characters.
string
domainDomain The domain of the short link address.
Example:
If the address of the short link is "https://vvd.bz/fML", the domain is https://vvd.bz. Important: The value https:// or http:// must be entered.
If you set it to a domain other than the domain of the generated short link, an error occurs.
For a branded LinkID (you set the LinkID yourself), the domain is 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:
FieldsDescriptionType
codeResponse code (0:Success)int
messageThe response message, or a related message if the response code is non-zero.string

Clicks statistics by time of day

View clicks and clickers over time for a single link.

This API is available starting with the Business plan.

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

Clicks statistics by date

You can view the number of clicks on a single link by date and the number of people who clicked it.
When searching, the range of start and end dates cannot be more than one month.

This API is available starting with the Business plan.

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

Group List

Gets a list of created link groups.

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

Validate links with expiration dates, passwords, and maximum clicks allowed

This API is available on the Premium plan.

When you restrict access to a link, you set an expiration date, password, and maximum number of clicks allowed.
If users click on a link generated by Vivoldi, it′s fine, but if they go directly to a long URL in their browser, there′s no way to validate it.
Vivoldi provides a separate JavaScript SDK to solve this problem.

When you add the SDK to a page with a long link, the SDK retrieves the link′s information and checks the expiration date, password, and maximum number of clicks allowed.
Redirect back to the Vivoldi short link or block access.

Add the script provided by Vivoldi to your event or promotion page between the ... and easily validate with just one line of code.

Add Vivoldi′s script to your page as shown below:

<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

Create coupon

This API is available starting with the Personal plan.

Create a discount coupon. If you want to create multiple coupons at once, then create them in the dashboard.
You can′t upload coupon images using the API.
In this case, you can upload coupon images when you create a coupon group in the dashboard and specify the group when you create the coupon.
If you specify a coupon group when you create a coupon, then some settings are ignored and the settings in the coupon group are applied.

Request:
Post /api/coupon/v1/create HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request:
FieldsField DescriptionsDescriptionRequiredType
cpnNoCoupon number A 8~16 digit coupon number that is a combination of uppercase letters and numbers. Special characters can′t be used in the coupon number.
If the value is empty, then the coupon number is automatically generated by the system.
string
grpIdxCoupon group Coupon groups are used to manage the categorization of coupons, and if a group setting and a coupon setting overlap, then the coupon setting is ignored.
You can find the group IDX on the Coupon groups page of your dashboard.
Default value: 0
int
tmplIdxCoupon template Coupon templates are used to describe a coupon and tell users what it′s for, how to use it, and any caveats.
The template IDX can be found on the Coupon templates page in your dashboard.
Default value: 0
int
nmCoupon name The name of the coupon appears on the coupon page. string
discTypeIdxDiscount type Set the discount type (rate or amount) for the coupon.
457: Rate discount (%), 458: Amount discount
Rate discount: Used when you offer a percentage discount for a coupon.
Discount by amount: Used to offer a discount by the amount entered.
int
discDiscount value Enter a value between 1% and 100% when the discount type is Rate (457).
Enter the amount to discount when the discount type is Amount (458).
double
discCurrencyAmount Currency You can set a monetary unit when the discount type is Amount (458).
KRW: Korean won, USD: US dollar, JPY: Japanese yen, EUR: European euro
Default value: KRW
string
strtYmdValidity start date Set the start date of the validity period to indicate when the coupon is available for use.
10-digit value in yyyy-mm-dd date format.
Example: 2024-10-01
date
endYmdValidity expiration date Set the expiration date of the coupon to indicate how long the coupon is available for use.
10-digit value in yyyy-mm-dd date format.
Example: 2024-12-31
date
onsiteYnOn-site coupons or not If this value is Y, then the coupon page displays a button to redeem the coupon.
The user shows the coupon to a store associate, and the associate redeems the coupon.
This is a useful feature if you have a brick-and-mortar store.
Default value: N
Y or N
memoNotes It can be used for internal purposes to manage coupons.
Notes are not visible to users.
string
urlURL After you enter the URL, the coupon page displays a “Go to redeem coupon” button that, when clicked, takes you to the URL that you entered.
If an image of the coupon has been uploaded, then clicking on the image will also take you to the URL.
string
useLimitMaximum number of coupon redemptions per person Set the maximum number of times a coupon can be redeemed.
The number of coupon redemptions per person “2 ~ 5” is required when processing coupon redemptions using the REST API provided by Vivoldi.
In this case, the user ID value must be entered.
When managing coupon redemptions manually on the dashboard, you can select only one of the following options: “Unlimited” or “1 time”.
If you select “Unlimited”, then anyone can redeem the coupon an unlimited number of times.
0:Unlimited, 1:1 time limit, 2:2 time limit, 3:3 time limit, 4:4 time limit, 5:5 time limit
int
colorText color Set the color of the coupon text on the coupon page.
It must be entered as a HEX value and can be up to 9 digits long, including the transparency.
Default value: #4F4F4FFF
string
backgroundBackground color On the Coupons page, set the background color for the coupon.
It must be entered as a HEX value and can be up to 9 digits long, including the transparency.
Default value: #FFFFFFFF
string
userIdUser ID Used to manage who has issued coupons and who has redeemed them.
If the value of Maximum coupon redemptions per person is between 2 and 5, then the user ID must be entered.
Typically, you enter the login ID of the member who signed up for your website.
string
userNmUsername If you already know who you want to issue the coupon to, then enter the name of the user who will use the coupon.
You need this to manage the issuance and redemption of coupons.
string
userPhnnoUser contacts Set the contacts of the users who will redeem the coupon. string
userEmlUser email Set the email of the user who will redeem the coupon. string
userEtc1User Other Information1 Set additional information about the user for internal administrative purposes. string
userEtc2User Other Information2 Set additional information about the user for internal administrative purposes. 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:
FieldsDescriptionType
codeResponse code (0:Success)int
messageThe response message, or a related message if the response code is non-zero.string
resultResponse value (Coupon number)string

Edit coupon

This API is available starting with the Personal plan.

Change the information in the created coupon.
When you assign a group to a coupon, some settings are ignored and the settings in the coupon group are applied.
For coupons that have already been redeemed, you can only edit the “Notes” but not the other information.

Request:
Put /api/coupon/v1/edit HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request:
FieldsField DescriptionsDescriptionRequiredType
cpnNoCoupon number The coupon number whose information you want to change. Enter only the coupon number, excluding the “-” sign. string
grpIdxCoupon group Coupon groups are used to manage the categorization of coupons, and if a group setting and a coupon setting overlap, then the coupon setting is ignored.
You can find the group IDX on the Coupon groups page of your dashboard.
Default value: 0
int
tmplIdxCoupon template Coupon templates are used to describe a coupon and tell users what it′s for, how to use it, and any caveats.
The template IDX can be found on the Coupon templates page in your dashboard.
Default value: 0
int
nmCoupon name The name of the coupon appears on the coupon page. string
discTypeIdxDiscount type Set the discount type (rate or amount) for the coupon.
457: Rate discount (%), 458: Amount discount
Rate discount: Used when you offer a percentage discount for a coupon.
Discount by amount: Used to offer a discount by the amount entered.
int
discDiscount value Enter a value between 1% and 100% when the discount type is Rate (457).
Enter the amount to discount when the discount type is Amount (458).
double
discCurrencyAmount Currency You can set a monetary unit when the discount type is Amount (458).
KRW: Korean won, USD: US dollar, JPY: Japanese yen, EUR: European euro
Default value: KRW
string
strtYmdValidity start date Set the start date of the validity period to indicate when the coupon is available for use.
10-digit value in yyyy-mm-dd date format.
Example: 2024-10-01
date
endYmdValidity expiration date Set the expiration date of the coupon to indicate how long the coupon is available for use.
10-digit value in yyyy-mm-dd date format.
Example: 2024-12-31
date
onsiteYnOn-site coupons or not If this value is Y, then the coupon page displays a button to redeem the coupon.
The user shows the coupon to a store associate, and the associate redeems the coupon.
This is a useful feature if you have a brick-and-mortar store.
Y or N
memoNotes It can be used for internal purposes to manage coupons.
Notes are not visible to users.
string
urlURL After you enter the URL, the coupon page displays a “Go to redeem coupon” button that, when clicked, takes you to the URL that you entered.
If an image of the coupon has been uploaded, then clicking on the image will also take you to the URL.
string
useLimitMaximum number of coupon redemptions per person Set the maximum number of times a coupon can be redeemed.
The number of coupon redemptions per person “2 ~ 5” is required when processing coupon redemptions using the REST API provided by Vivoldi.
In this case, the user ID value must be entered.
When managing coupon redemptions manually on the dashboard, you can select only one of the following options: “Unlimited” or “1 time”.
If you select “Unlimited”, then anyone can redeem the coupon an unlimited number of times.
0:Unlimited, 1:1 time limit, 2:2 time limit, 3:3 time limit, 4:4 time limit, 5:5 time limit
int
colorText color Set the color of the coupon text on the coupon page.
It must be entered as a HEX value and can be up to 9 digits long, including the transparency.
Default value: #4F4F4FFF
string
backgroundBackground color On the Coupons page, set the background color for the coupon.
It must be entered as a HEX value and can be up to 9 digits long, including the transparency.
Default value: #FFFFFFFF
string
userIdUser ID Used to manage who has issued coupons and who has redeemed them.
If the value of Maximum coupon redemptions per person is be
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:
FieldsDescriptionType
codeResponse code (0:Success)int
messageThe response message, or a related message if the response code is non-zero.string

Delete coupon

This API is available starting with the Personal plan.

Delete the created coupon.
To delete multiple coupons at once, use the dashboard.

Request:
Delete /api/coupon/v1/remove HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: -
Request:
FieldsField DescriptionsDescriptionRequiredType
cpnNoCoupon number The coupon number to delete. 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:
FieldsDescriptionType
codeResponse code (0:Success)int
messageThe response message, or a related message if the response code is non-zero.string

Validate coupon

This API is available starting with the Personal plan.

Used to check and validate if the coupon is valid before processing “Redeem coupon”.
Verify the coupon validation as shown below.
  • Validate coupon expiration date. (start date and expiration date)
  • Validate the maximum number of coupons per person.
  • Validate coupon redemption.
Request:
Get /api/coupon/v1/validate HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request 항목 설명:
FieldsField DescriptionsDescriptionRequiredType
cpnNoCoupon number The coupon number to validate.
If the validation fails, check the message in the Response.
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 항목 설명:
FieldsDescriptionType
codeResponse code (0:Success)int
messageThe response message, or a related message if the response code is non-zero.string

Use coupon

This API is available starting with the Personal plan.

While you can manage the “redeem coupon” processing manually in the coupon list in your dashboard, this API allows you to automate it by calling it when a user redeems a coupon on your website.

Request:
Put /api/coupon/v1/use HTTP/1.1
Host: https://vivoldi.com
Authorization: APIKey {Your API Key}
Content-type: application/json
Request:
FieldsField DescriptionsDescriptionRequiredType
cpnNoCoupon number “Redeemed” coupon number to process.
Enter only the coupon number, excluding the “-” sign.
string
userIdUser ID Used to manage who has issued coupons and who has redeemed them.
If the value of Maximum coupon redemptions per person is between 2 and 5, then the user ID must be entered.
Typically, you enter the login ID of the member who signed up for your website.
string
memoNotes You can enter notes to manage coupon redemptions.
Enter the user′s IP address, the page and service where the coupon was redeemed, and other information.
When the maximum number of coupon redemptions per person is unlimited, you don′t know who redeemed the coupon, so you can manage by username or note.
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:
FieldsDescriptionType
codeResponse code (0:Success)int
messageThe response message, or a related message if the response code is non-zero.string

Send push messages

This API is independent of Vivoldi′s URL Shortener service and is intended for anyone who runs a website.

In order to send push messages to users who visit your website, the user must agree to the “notification permission” in their web browser.
If they decline the notification permission, you will not be able to send push messages.

After you install the JavaScript SDK provided by Vivoldi on your website, the web browser will display a pop-up window for “Notification Permissions” when a user visits your website.
If the user agrees to the permission, the notification data will be listed on the “Push Messages -> Send website push” page of the dashboard.
For example, if 100 users have agreed to notification permissions on your website, you will see 100 data in the list.
When you send a push message from the dashboard, the message will be sent to all users displayed in the list.

Anyone can install the JavaScript SDK provided by Vivoldi to collect user data.
However, you′ll need to have money in your account to send push messages.
The cost for sending push messages is 10 KRW per message, or you can sign up for a monthly subscription to send an unlimited number of messages.

Installing the JavaScript SDK is as simple as adding it between the <head>...</head>.

<html>
<head>
<title>example page</title>
<script src="https://opencdn.vivoldi.com/js/webpush.min.js?v=202411181" 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>

API keys can be created on the “Developer API” page in your dashboard, and publicKey can be found in the list once you register your domain on the “Push Messages -> Domain Management” page.

Once everything is ready, the last thing you need to do is create a new sw.min.js file and upload it to the root of your website.
For example: https://example.com/sw.min.js

When accessing the above path, the script should be displayed in the web browser for the notification to work properly.
Copy and paste the code below into your newly created sw.min.js file.

sw.min.js:
'use strict';const a0_0x51b6dd=a0_0x3e4e;(function(_0x455f80,_0x52a324){const _0x42ada9=a0_0x3e4e,_0x54a984=_0x455f80();while(!![]){try{const _0x379b56=parseInt(_0x42ada9(0x1df))/0x1*(parseInt(_0x42ada9(0x1c8))/0x2)+parseInt(_0x42ada9(0x1ce))/0x3*(-parseInt(_0x42ada9(0x1ca))/0x4)+parseInt(_0x42ada9(0x1d4))/0x5+parseInt(_0x42ada9(0x1d2))/0x6+-parseInt(_0x42ada9(0x1d5))/0x7*(-parseInt(_0x42ada9(0x1cb))/0x8)+-parseInt(_0x42ada9(0x1dc))/0x9+-parseInt(_0x42ada9(0x1c7))/0xa;if(_0x379b56===_0x52a324)break;else _0x54a984['push'](_0x54a984['shift']());}catch(_0x53d562){_0x54a984['push'](_0x54a984['shift']());}}}(a0_0x4326,0x30e43));self[a0_0x51b6dd(0x1c1)](a0_0x51b6dd(0x1de),function(_0x5de01b){const _0x12a008=a0_0x51b6dd,_0x4c6a51=JSON[_0x12a008(0x1c6)](_0x5de01b['data'][_0x12a008(0x1d0)]()),_0x370b6a=navigator[_0x12a008(0x1e1)],_0x1189f4=_0x370b6a==='ko'||_0x370b6a===_0x12a008(0x1c2),_0xf41fb1={'tag':_0x12a008(0x1d8),'renotify':!![],'body':_0x4c6a51[_0x12a008(0x1c5)],'icon':_0x4c6a51[_0x12a008(0x1d1)],'badge':_0x4c6a51[_0x12a008(0x1db)],'requireInteraction':!![],'vibrate':[0x12c,0x64,0x190,0xc8,0x1f4],'data':_0x4c6a51,'actions':[{'action':'go','type':_0x12a008(0x1cd),'title':_0x1189f4?_0x12a008(0x1d9):'GO'},{'action':_0x12a008(0x1d6),'type':_0x12a008(0x1cd),'title':_0x1189f4?'닫기':_0x12a008(0x1d7)}]};_0x4c6a51[_0x12a008(0x1cc)]&&(_0xf41fb1[_0x12a008(0x1cc)]=_0x4c6a51[_0x12a008(0x1cc)]),_0x5de01b['waitUntil'](self['registration']['showNotification'](_0x4c6a51[_0x12a008(0x1dd)],_0xf41fb1));}),self[a0_0x51b6dd(0x1c1)](a0_0x51b6dd(0x1c9),function(_0x54c778){const _0x251318=a0_0x51b6dd;_0x54c778['notification'][_0x251318(0x1d6)]();switch(_0x54c778[_0x251318(0x1c4)]){case'go':_0x54c778[_0x251318(0x1cf)](clients[_0x251318(0x1d3)](_0x54c778['notification'][_0x251318(0x1c3)][_0x251318(0x1e0)]));break;case'close':break;default:_0x54c778[_0x251318(0x1cf)](clients[_0x251318(0x1d3)](_0x54c778[_0x251318(0x1da)]['data'][_0x251318(0x1e0)]));}});function a0_0x3e4e(_0x45e3e2,_0x295c86){const _0x432642=a0_0x4326();return a0_0x3e4e=function(_0x3e4efa,_0x64bcb5){_0x3e4efa=_0x3e4efa-0x1c1;let _0x8300ae=_0x432642[_0x3e4efa];return _0x8300ae;},a0_0x3e4e(_0x45e3e2,_0x295c86);}function a0_0x4326(){const _0x561e9e=['2980062TMYstt','title','push','287tTaamn','url','language','addEventListener','ko-KR','data','action','body','parse','747230eHBXAQ','194YOCWVb','notificationclick','44frpzaF','16UnLXXA','image','button','56778ZtTfDI','waitUntil','text','icon','981276hWPfTB','openWindow','1160955tkUXYQ','1367485DBAToW','close','CLOSE','renotify','바로가기','notification','badge'];a0_0x4326=function(){return _0x561e9e;};return a0_0x4326();}

Now, when you access your website, you should see the notification permission.
When you′ve allowed the notification permission, check to see if you′re seeing notification data on the “Website Push Sending” page of your Vivoldi dashboard.