The coin you already have
A code-signing-ID with spend is the permission. There is no extra ordinal scope. Do not ask for a new coin just to inscribe.
For developers
Your program asks Link to inscribe a picture, mint a token, or send one it already holds. Link holds the keys. You never open the wallet.
The list of these pages is Nexus Developers. Connect first. That page is Connect an app to Link. This page is only the ordinal door. BSV payments and your own note stay on that other page.
Link listens on http://127.0.0.1:21736. The process that opens the socket must be the exe you signed. A script hosted by python.exe or node.exe is that host. Ship an exe.
A code-signing-ID with spend is the permission. There is no extra ordinal scope. Do not ask for a new coin just to inscribe.
Auto and the Security lamp do not cover a picture, a token, or a send. The person presses Yes in Link. Wait up to 3 minutes.
Copy these. Do not invent a second way.
One file becomes one 1-sat inscription. Do not inscribe a pile of pictures to stand in for a supply.
One deploy+mint. supply is the whole amount. An optional picture is the icon, not the supply.
PNG, JPEG, WebP, or GIF. Hard stop 100 KB. Above 40 KB, Link tells the person it is a lot for an icon.
The miner fee comes from the messenger account. The ordinals account is never the fee. You do not choose the receive address. The new ordinal lands there.
to is an @nexusnode.link name, or a 1… address. Link uses that name’s ordinals address. Any other paymail is refused.
Nexus ID coins and Art Ownership pieces are not in the list. This door will not send them. Do not read the wallet folder.
GET http://127.0.0.1:21736/v1/app/ordinals. No body. Link does not ask. Call this before a send, and again after a mint if you attached a picture.
{
"ok": true,
"ordinals": [
{
"origin": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef_0",
"kind": "picture",
"type": "image/png",
"name": "badge"
},
{
"origin": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210_0",
"kind": "token",
"type": "application/bsv-20",
"name": "Peyton",
"amount": "1000",
"token_id": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210_0",
"sym": "PEY",
"icon": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef_0"
}
]
}
origin is the id you send later. amount is the units on that coin. token_id is the deploy. icon is the picture origin, when the mint had one. A picture row has no amount.
POST http://127.0.0.1:21736/v1/app/ordinal/picture with Content-Type: application/json. data is standard base64 of the file bytes. Not a path. Not a URL.
{
"type": "image/png",
"name": "badge",
"data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="
}
type is image/png, image/jpeg, image/webp, or image/gif. name is optional, up to 48 characters, no |. Link asks, then inscribes.
POST http://127.0.0.1:21736/v1/app/ordinal/token. sym is 1 to 16 letters or numbers. supply is a string of digits, no leading zero. decimals is a JSON number from 0 to 18. Leave it out for 0.
{
"sym": "PEY",
"supply": "1000",
"decimals": 0,
"name": "Peyton"
}
Add type and data only when the token has one icon picture. Same picture rules as above. Omit both when there is no picture. One without the other is bad request.
{
"sym": "PEY",
"supply": "1000",
"name": "Peyton",
"type": "image/png",
"data": "base64-of-the-png"
}
The txid in the answer is the token. The picture, when you sent one, is icon on the list. supply is text. Do not send it as a number.
POST http://127.0.0.1:21736/v1/app/ordinal/send. origin is the origin from the list. A 64-character id means vout 0.
{
"origin": "fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210_0",
"to": "someone@nexusnode.link",
"amount": "10"
}
Leave amount out. The whole inscription moves. A number on a picture is refused.
amount is a digit string, the units to send. Leave it out, or send "all", for every unit on that coin.
The txid in the answer is the transfer. List again if you need the coin that remains.
Read ok first. A yes from a picture or a token looks like this. origin is that new inscription.
{
"ok": true,
"txid": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"origin": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef_0",
"paymail": "payer@nexusnode.link"
}
A send has txid and paymail. It does not add origin. A no looks like {"ok":false,"error":"cancelled"}.
The signed exe is this program. Timeout is 3 minutes because Link waits for Yes. Delete a call you do not need.
using System.Net.Http;
using System.Text;
const string Link = "http://127.0.0.1:21736";
using var http = new HttpClient();
http.Timeout = TimeSpan.FromMinutes(3);
string list = await http.GetStringAsync(Link + "/v1/app/ordinals");
string picture = await (await http.PostAsync(Link + "/v1/app/ordinal/picture",
new StringContent("""
{"type":"image/png","name":"badge","data":"PASTE_BASE64"}
""", Encoding.UTF8, "application/json"))).Content.ReadAsStringAsync();
string token = await (await http.PostAsync(Link + "/v1/app/ordinal/token",
new StringContent("""
{"sym":"PEY","supply":"1000","name":"Peyton"}
""", Encoding.UTF8, "application/json"))).Content.ReadAsStringAsync();
string send = await (await http.PostAsync(Link + "/v1/app/ordinal/send",
new StringContent("""
{"origin":"PASTE_ORIGIN","to":"someone@nexusnode.link","amount":"10"}
""", Encoding.UTF8, "application/json"))).Content.ReadAsStringAsync();
Run this from the signed exe, not from python.exe, or Link answers not allowed.
import json, urllib.request
LINK = "http://127.0.0.1:21736"
def call(method, path, body=None):
data = None if body is None else json.dumps(body).encode()
req = urllib.request.Request(LINK + path, data=data, method=method)
if data:
req.add_header("Content-Type", "application/json")
with urllib.request.urlopen(req, timeout=180) as res:
return json.load(res)
print(call("GET", "/v1/app/ordinals"))
print(call("POST", "/v1/app/ordinal/picture",
{"type": "image/png", "name": "badge", "data": "PASTE_BASE64"}))
print(call("POST", "/v1/app/ordinal/token",
{"sym": "PEY", "supply": "1000", "name": "Peyton"}))
print(call("POST", "/v1/app/ordinal/send",
{"origin": "PASTE_ORIGIN", "to": "someone@nexusnode.link", "amount": "10"}))
Same rule. The signed exe opens the socket. node.exe is not that exe.
const link = "http://127.0.0.1:21736";
async function call(method, path, body) {
const res = await fetch(link + path, {
method,
headers: body ? { "Content-Type": "application/json" } : undefined,
body: body ? JSON.stringify(body) : undefined,
signal: AbortSignal.timeout(180000)
});
return res.json();
}
console.log(await call("GET", "/v1/app/ordinals"));
console.log(await call("POST", "/v1/app/ordinal/token",
{ sym: "PEY", supply: "1000", name: "Peyton" }));
That Link is older than this door. They need a Link that has this page’s calls.
The socket is not the signed exe, the coin has no spend, or no paymail is published.
A field is missing, the wrong type, or the picture is not PNG, JPEG, WebP, or GIF. supply and amount are strings of digits.
They pressed No. Do not retry in a loop.
The messenger account cannot cover the miner fee. Do not take the fee from an ordinal.
The error says the ordinal is not in this wallet. List again and use that origin.
A file over 100 KB says file is over 100 KB. Shrink it first. A picture send with a number says the whole inscription is what moves. Another paymail says to use a 1… address or an @nexusnode.link name.