curl --request POST \
--url https://purps.lol/api/v2/launches \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"symbol": "<string>",
"quoteMint": "<string>",
"feeSplit": {
"strategyBps": 123,
"airdropBps": 123,
"creatorBps": 123
},
"devBuySol": 123,
"creatorFeeBps": 123,
"strategy": {
"splitBuybackBps": 123,
"splitMarginBps": 123,
"splitReserveBps": 123,
"perpLegs": [
{}
],
"payoutMint": "<string>",
"payoutMintsExtra": [
"<string>"
],
"payoutMint2": "<string>",
"strategy": {},
"ownerControls": true
},
"creatorWallet": "<string>",
"image": "<string>",
"imageUrl": "<string>",
"description": "<string>",
"twitter": "<string>",
"telegram": "<string>"
}
'import requests
url = "https://purps.lol/api/v2/launches"
payload = {
"name": "<string>",
"symbol": "<string>",
"quoteMint": "<string>",
"feeSplit": {
"strategyBps": 123,
"airdropBps": 123,
"creatorBps": 123
},
"devBuySol": 123,
"creatorFeeBps": 123,
"strategy": {
"splitBuybackBps": 123,
"splitMarginBps": 123,
"splitReserveBps": 123,
"perpLegs": [{}],
"payoutMint": "<string>",
"payoutMintsExtra": ["<string>"],
"payoutMint2": "<string>",
"strategy": {},
"ownerControls": True
},
"creatorWallet": "<string>",
"image": "<string>",
"imageUrl": "<string>",
"description": "<string>",
"twitter": "<string>",
"telegram": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
symbol: '<string>',
quoteMint: '<string>',
feeSplit: {strategyBps: 123, airdropBps: 123, creatorBps: 123},
devBuySol: 123,
creatorFeeBps: 123,
strategy: {
splitBuybackBps: 123,
splitMarginBps: 123,
splitReserveBps: 123,
perpLegs: [{}],
payoutMint: '<string>',
payoutMintsExtra: ['<string>'],
payoutMint2: '<string>',
strategy: {},
ownerControls: true
},
creatorWallet: '<string>',
image: '<string>',
imageUrl: '<string>',
description: '<string>',
twitter: '<string>',
telegram: '<string>'
})
};
fetch('https://purps.lol/api/v2/launches', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://purps.lol/api/v2/launches",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'symbol' => '<string>',
'quoteMint' => '<string>',
'feeSplit' => [
'strategyBps' => 123,
'airdropBps' => 123,
'creatorBps' => 123
],
'devBuySol' => 123,
'creatorFeeBps' => 123,
'strategy' => [
'splitBuybackBps' => 123,
'splitMarginBps' => 123,
'splitReserveBps' => 123,
'perpLegs' => [
[
]
],
'payoutMint' => '<string>',
'payoutMintsExtra' => [
'<string>'
],
'payoutMint2' => '<string>',
'strategy' => [
],
'ownerControls' => true
],
'creatorWallet' => '<string>',
'image' => '<string>',
'imageUrl' => '<string>',
'description' => '<string>',
'twitter' => '<string>',
'telegram' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://purps.lol/api/v2/launches"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"symbol\": \"<string>\",\n \"quoteMint\": \"<string>\",\n \"feeSplit\": {\n \"strategyBps\": 123,\n \"airdropBps\": 123,\n \"creatorBps\": 123\n },\n \"devBuySol\": 123,\n \"creatorFeeBps\": 123,\n \"strategy\": {\n \"splitBuybackBps\": 123,\n \"splitMarginBps\": 123,\n \"splitReserveBps\": 123,\n \"perpLegs\": [\n {}\n ],\n \"payoutMint\": \"<string>\",\n \"payoutMintsExtra\": [\n \"<string>\"\n ],\n \"payoutMint2\": \"<string>\",\n \"strategy\": {},\n \"ownerControls\": true\n },\n \"creatorWallet\": \"<string>\",\n \"image\": \"<string>\",\n \"imageUrl\": \"<string>\",\n \"description\": \"<string>\",\n \"twitter\": \"<string>\",\n \"telegram\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://purps.lol/api/v2/launches")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"symbol\": \"<string>\",\n \"quoteMint\": \"<string>\",\n \"feeSplit\": {\n \"strategyBps\": 123,\n \"airdropBps\": 123,\n \"creatorBps\": 123\n },\n \"devBuySol\": 123,\n \"creatorFeeBps\": 123,\n \"strategy\": {\n \"splitBuybackBps\": 123,\n \"splitMarginBps\": 123,\n \"splitReserveBps\": 123,\n \"perpLegs\": [\n {}\n ],\n \"payoutMint\": \"<string>\",\n \"payoutMintsExtra\": [\n \"<string>\"\n ],\n \"payoutMint2\": \"<string>\",\n \"strategy\": {},\n \"ownerControls\": true\n },\n \"creatorWallet\": \"<string>\",\n \"image\": \"<string>\",\n \"imageUrl\": \"<string>\",\n \"description\": \"<string>\",\n \"twitter\": \"<string>\",\n \"telegram\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://purps.lol/api/v2/launches")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"symbol\": \"<string>\",\n \"quoteMint\": \"<string>\",\n \"feeSplit\": {\n \"strategyBps\": 123,\n \"airdropBps\": 123,\n \"creatorBps\": 123\n },\n \"devBuySol\": 123,\n \"creatorFeeBps\": 123,\n \"strategy\": {\n \"splitBuybackBps\": 123,\n \"splitMarginBps\": 123,\n \"splitReserveBps\": 123,\n \"perpLegs\": [\n {}\n ],\n \"payoutMint\": \"<string>\",\n \"payoutMintsExtra\": [\n \"<string>\"\n ],\n \"payoutMint2\": \"<string>\",\n \"strategy\": {},\n \"ownerControls\": true\n },\n \"creatorWallet\": \"<string>\",\n \"image\": \"<string>\",\n \"imageUrl\": \"<string>\",\n \"description\": \"<string>\",\n \"twitter\": \"<string>\",\n \"telegram\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"data": {
"mint": "<string>",
"transactions": [
"<string>"
],
"createIndex": 123,
"mintSecret": "<string>",
"imageUrl": "<string>",
"url": "<string>"
}
}{
"ok": true,
"error": "<string>"
}{
"ok": true,
"error": "<string>"
}{
"ok": true,
"error": "<string>"
}{
"ok": true,
"error": "<string>"
}{
"ok": true,
"error": "<string>"
}{
"ok": true,
"error": "<string>"
}Build a purps.lol launch
One call, no message to sign. Send the launch’s terms, the coin’s image and socials. We upload the metadata, build the launch transaction (and a SOL-to-pair swap in front of it when the pair is not SOL and there is a dev buy), simulate it, and record the launch as pending. You get back unsigned transactions and the throwaway mint key. The launch transaction can only land with the creator wallet’s signature, and that is the proof: sign each transaction with the creator wallet, and the one at createIndex with the mint key as well, then send them in order through /transactions/send. The launch goes live on its own once the pool exists on chain; poll /launches/. A wallet the launchpad does not admit is refused with a 403 before anything is uploaded; a wallet that cannot afford the launch (about 0.03 SOL plus the dev buy) with a 400. imageUrl fetches are budgeted (20 an hour per address, 200 an hour site-wide); a 429 naming image fetches means send image as a data URL instead.
curl --request POST \
--url https://purps.lol/api/v2/launches \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"symbol": "<string>",
"quoteMint": "<string>",
"feeSplit": {
"strategyBps": 123,
"airdropBps": 123,
"creatorBps": 123
},
"devBuySol": 123,
"creatorFeeBps": 123,
"strategy": {
"splitBuybackBps": 123,
"splitMarginBps": 123,
"splitReserveBps": 123,
"perpLegs": [
{}
],
"payoutMint": "<string>",
"payoutMintsExtra": [
"<string>"
],
"payoutMint2": "<string>",
"strategy": {},
"ownerControls": true
},
"creatorWallet": "<string>",
"image": "<string>",
"imageUrl": "<string>",
"description": "<string>",
"twitter": "<string>",
"telegram": "<string>"
}
'import requests
url = "https://purps.lol/api/v2/launches"
payload = {
"name": "<string>",
"symbol": "<string>",
"quoteMint": "<string>",
"feeSplit": {
"strategyBps": 123,
"airdropBps": 123,
"creatorBps": 123
},
"devBuySol": 123,
"creatorFeeBps": 123,
"strategy": {
"splitBuybackBps": 123,
"splitMarginBps": 123,
"splitReserveBps": 123,
"perpLegs": [{}],
"payoutMint": "<string>",
"payoutMintsExtra": ["<string>"],
"payoutMint2": "<string>",
"strategy": {},
"ownerControls": True
},
"creatorWallet": "<string>",
"image": "<string>",
"imageUrl": "<string>",
"description": "<string>",
"twitter": "<string>",
"telegram": "<string>"
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
symbol: '<string>',
quoteMint: '<string>',
feeSplit: {strategyBps: 123, airdropBps: 123, creatorBps: 123},
devBuySol: 123,
creatorFeeBps: 123,
strategy: {
splitBuybackBps: 123,
splitMarginBps: 123,
splitReserveBps: 123,
perpLegs: [{}],
payoutMint: '<string>',
payoutMintsExtra: ['<string>'],
payoutMint2: '<string>',
strategy: {},
ownerControls: true
},
creatorWallet: '<string>',
image: '<string>',
imageUrl: '<string>',
description: '<string>',
twitter: '<string>',
telegram: '<string>'
})
};
fetch('https://purps.lol/api/v2/launches', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://purps.lol/api/v2/launches",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'symbol' => '<string>',
'quoteMint' => '<string>',
'feeSplit' => [
'strategyBps' => 123,
'airdropBps' => 123,
'creatorBps' => 123
],
'devBuySol' => 123,
'creatorFeeBps' => 123,
'strategy' => [
'splitBuybackBps' => 123,
'splitMarginBps' => 123,
'splitReserveBps' => 123,
'perpLegs' => [
[
]
],
'payoutMint' => '<string>',
'payoutMintsExtra' => [
'<string>'
],
'payoutMint2' => '<string>',
'strategy' => [
],
'ownerControls' => true
],
'creatorWallet' => '<string>',
'image' => '<string>',
'imageUrl' => '<string>',
'description' => '<string>',
'twitter' => '<string>',
'telegram' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://purps.lol/api/v2/launches"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"symbol\": \"<string>\",\n \"quoteMint\": \"<string>\",\n \"feeSplit\": {\n \"strategyBps\": 123,\n \"airdropBps\": 123,\n \"creatorBps\": 123\n },\n \"devBuySol\": 123,\n \"creatorFeeBps\": 123,\n \"strategy\": {\n \"splitBuybackBps\": 123,\n \"splitMarginBps\": 123,\n \"splitReserveBps\": 123,\n \"perpLegs\": [\n {}\n ],\n \"payoutMint\": \"<string>\",\n \"payoutMintsExtra\": [\n \"<string>\"\n ],\n \"payoutMint2\": \"<string>\",\n \"strategy\": {},\n \"ownerControls\": true\n },\n \"creatorWallet\": \"<string>\",\n \"image\": \"<string>\",\n \"imageUrl\": \"<string>\",\n \"description\": \"<string>\",\n \"twitter\": \"<string>\",\n \"telegram\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://purps.lol/api/v2/launches")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"symbol\": \"<string>\",\n \"quoteMint\": \"<string>\",\n \"feeSplit\": {\n \"strategyBps\": 123,\n \"airdropBps\": 123,\n \"creatorBps\": 123\n },\n \"devBuySol\": 123,\n \"creatorFeeBps\": 123,\n \"strategy\": {\n \"splitBuybackBps\": 123,\n \"splitMarginBps\": 123,\n \"splitReserveBps\": 123,\n \"perpLegs\": [\n {}\n ],\n \"payoutMint\": \"<string>\",\n \"payoutMintsExtra\": [\n \"<string>\"\n ],\n \"payoutMint2\": \"<string>\",\n \"strategy\": {},\n \"ownerControls\": true\n },\n \"creatorWallet\": \"<string>\",\n \"image\": \"<string>\",\n \"imageUrl\": \"<string>\",\n \"description\": \"<string>\",\n \"twitter\": \"<string>\",\n \"telegram\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://purps.lol/api/v2/launches")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"symbol\": \"<string>\",\n \"quoteMint\": \"<string>\",\n \"feeSplit\": {\n \"strategyBps\": 123,\n \"airdropBps\": 123,\n \"creatorBps\": 123\n },\n \"devBuySol\": 123,\n \"creatorFeeBps\": 123,\n \"strategy\": {\n \"splitBuybackBps\": 123,\n \"splitMarginBps\": 123,\n \"splitReserveBps\": 123,\n \"perpLegs\": [\n {}\n ],\n \"payoutMint\": \"<string>\",\n \"payoutMintsExtra\": [\n \"<string>\"\n ],\n \"payoutMint2\": \"<string>\",\n \"strategy\": {},\n \"ownerControls\": true\n },\n \"creatorWallet\": \"<string>\",\n \"image\": \"<string>\",\n \"imageUrl\": \"<string>\",\n \"description\": \"<string>\",\n \"twitter\": \"<string>\",\n \"telegram\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"ok": true,
"data": {
"mint": "<string>",
"transactions": [
"<string>"
],
"createIndex": 123,
"mintSecret": "<string>",
"imageUrl": "<string>",
"url": "<string>"
}
}{
"ok": true,
"error": "<string>"
}{
"ok": true,
"error": "<string>"
}{
"ok": true,
"error": "<string>"
}{
"ok": true,
"error": "<string>"
}{
"ok": true,
"error": "<string>"
}{
"ok": true,
"error": "<string>"
}Body
A purps.lol launch, in one call. No ts or signature: the launch transaction you sign is the proof.
1 to 32 characters.
1 to 10 characters.
The pair, from /pairs purps.
Where creator fees go: airdrop to holders in the pair token, split half to holders half to you, creator all to your wallet, strategy into a strategy you send now. Send feeSplit for any other share.
airdrop, split, creator, strategy Optional three-way share of the creator fee, basis points summing to 10000. strategy is required when strategyBps is above zero.
Show child attributes
Show child attributes
Your own first buy, in SOL. Converted to the pair on the way in when the pair is not SOL. Default 0.
Your fee tier, basis points of curve volume, on top of the platform's 1%. Default 100 (1%); 50 (0.5%) to 980 (9.8%).
Required when feePreset is strategy or feeSplit.strategyBps is above zero. Checked before anything is uploaded; registered by us the moment the launch goes live.
Show child attributes
Show child attributes
The Solana wallet that signs the transactions and pays.
The coin's logo as a data URL (data:image/png;base64,…). PNG, JPEG, WebP or GIF, 512KB max. Send this or imageUrl.
A public https link to the logo instead of image. Fetched by us under the same size and type rules.
Up to 500 characters. The coin's website in its metadata is always its purps.lol page; add your own links as twitter and telegram.
https:// link.
https:// link.