curl --request POST \
--url https://api.sandbox.nevermined.app/oauth/authorize \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"client_id": "fleet",
"redirect_uri": "cursor://oauth/callback",
"code_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
"code_challenge_method": "S256",
"agent_id": "agent-123",
"resource": "https://mcp-server.example.com",
"state": "xyz",
"plan_id": "105906634574379352540220884472",
"provider_payment_method_id": "<string>",
"spending_limit_cents": 5000,
"duration_secs": 2592000
}
'import requests
url = "https://api.sandbox.nevermined.app/oauth/authorize"
payload = {
"client_id": "fleet",
"redirect_uri": "cursor://oauth/callback",
"code_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
"code_challenge_method": "S256",
"agent_id": "agent-123",
"resource": "https://mcp-server.example.com",
"state": "xyz",
"plan_id": "105906634574379352540220884472",
"provider_payment_method_id": "<string>",
"spending_limit_cents": 5000,
"duration_secs": 2592000
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
client_id: 'fleet',
redirect_uri: 'cursor://oauth/callback',
code_challenge: 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM',
code_challenge_method: 'S256',
agent_id: 'agent-123',
resource: 'https://mcp-server.example.com',
state: 'xyz',
plan_id: '105906634574379352540220884472',
provider_payment_method_id: '<string>',
spending_limit_cents: 5000,
duration_secs: 2592000
})
};
fetch('https://api.sandbox.nevermined.app/oauth/authorize', 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://api.sandbox.nevermined.app/oauth/authorize",
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([
'client_id' => 'fleet',
'redirect_uri' => 'cursor://oauth/callback',
'code_challenge' => 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM',
'code_challenge_method' => 'S256',
'agent_id' => 'agent-123',
'resource' => 'https://mcp-server.example.com',
'state' => 'xyz',
'plan_id' => '105906634574379352540220884472',
'provider_payment_method_id' => '<string>',
'spending_limit_cents' => 5000,
'duration_secs' => 2592000
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://api.sandbox.nevermined.app/oauth/authorize"
payload := strings.NewReader("{\n \"client_id\": \"fleet\",\n \"redirect_uri\": \"cursor://oauth/callback\",\n \"code_challenge\": \"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\",\n \"code_challenge_method\": \"S256\",\n \"agent_id\": \"agent-123\",\n \"resource\": \"https://mcp-server.example.com\",\n \"state\": \"xyz\",\n \"plan_id\": \"105906634574379352540220884472\",\n \"provider_payment_method_id\": \"<string>\",\n \"spending_limit_cents\": 5000,\n \"duration_secs\": 2592000\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://api.sandbox.nevermined.app/oauth/authorize")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"client_id\": \"fleet\",\n \"redirect_uri\": \"cursor://oauth/callback\",\n \"code_challenge\": \"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\",\n \"code_challenge_method\": \"S256\",\n \"agent_id\": \"agent-123\",\n \"resource\": \"https://mcp-server.example.com\",\n \"state\": \"xyz\",\n \"plan_id\": \"105906634574379352540220884472\",\n \"provider_payment_method_id\": \"<string>\",\n \"spending_limit_cents\": 5000,\n \"duration_secs\": 2592000\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.nevermined.app/oauth/authorize")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"client_id\": \"fleet\",\n \"redirect_uri\": \"cursor://oauth/callback\",\n \"code_challenge\": \"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\",\n \"code_challenge_method\": \"S256\",\n \"agent_id\": \"agent-123\",\n \"resource\": \"https://mcp-server.example.com\",\n \"state\": \"xyz\",\n \"plan_id\": \"105906634574379352540220884472\",\n \"provider_payment_method_id\": \"<string>\",\n \"spending_limit_cents\": 5000,\n \"duration_secs\": 2592000\n}"
response = http.request(request)
puts response.read_body{
"code": "abc123…"
}{
"code": "BCK.OAUTH.0016",
"message": "Unknown OAuth client",
"category": "auth",
"hint": "<string>",
"retryable": true,
"httpStatus": 400
}{
"code": "BCK.OAUTH.0016",
"message": "Unknown OAuth client",
"category": "auth",
"hint": "<string>",
"retryable": true,
"httpStatus": 400
}Generate an OAuth 2.1 authorization code
Authorization Code flow with PKCE (mandatory). Mints an x402 payment permission for a specific agent and plan. Browser-initiated in the signed-in user’s context — authenticated with the user’s Nevermined API key (unauthenticated → BCK.OAUTH.0007). Requires a pre-registered client_id (unregistered → BCK.OAUTH.0016).
curl --request POST \
--url https://api.sandbox.nevermined.app/oauth/authorize \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"client_id": "fleet",
"redirect_uri": "cursor://oauth/callback",
"code_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
"code_challenge_method": "S256",
"agent_id": "agent-123",
"resource": "https://mcp-server.example.com",
"state": "xyz",
"plan_id": "105906634574379352540220884472",
"provider_payment_method_id": "<string>",
"spending_limit_cents": 5000,
"duration_secs": 2592000
}
'import requests
url = "https://api.sandbox.nevermined.app/oauth/authorize"
payload = {
"client_id": "fleet",
"redirect_uri": "cursor://oauth/callback",
"code_challenge": "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
"code_challenge_method": "S256",
"agent_id": "agent-123",
"resource": "https://mcp-server.example.com",
"state": "xyz",
"plan_id": "105906634574379352540220884472",
"provider_payment_method_id": "<string>",
"spending_limit_cents": 5000,
"duration_secs": 2592000
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
client_id: 'fleet',
redirect_uri: 'cursor://oauth/callback',
code_challenge: 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM',
code_challenge_method: 'S256',
agent_id: 'agent-123',
resource: 'https://mcp-server.example.com',
state: 'xyz',
plan_id: '105906634574379352540220884472',
provider_payment_method_id: '<string>',
spending_limit_cents: 5000,
duration_secs: 2592000
})
};
fetch('https://api.sandbox.nevermined.app/oauth/authorize', 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://api.sandbox.nevermined.app/oauth/authorize",
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([
'client_id' => 'fleet',
'redirect_uri' => 'cursor://oauth/callback',
'code_challenge' => 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM',
'code_challenge_method' => 'S256',
'agent_id' => 'agent-123',
'resource' => 'https://mcp-server.example.com',
'state' => 'xyz',
'plan_id' => '105906634574379352540220884472',
'provider_payment_method_id' => '<string>',
'spending_limit_cents' => 5000,
'duration_secs' => 2592000
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"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://api.sandbox.nevermined.app/oauth/authorize"
payload := strings.NewReader("{\n \"client_id\": \"fleet\",\n \"redirect_uri\": \"cursor://oauth/callback\",\n \"code_challenge\": \"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\",\n \"code_challenge_method\": \"S256\",\n \"agent_id\": \"agent-123\",\n \"resource\": \"https://mcp-server.example.com\",\n \"state\": \"xyz\",\n \"plan_id\": \"105906634574379352540220884472\",\n \"provider_payment_method_id\": \"<string>\",\n \"spending_limit_cents\": 5000,\n \"duration_secs\": 2592000\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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://api.sandbox.nevermined.app/oauth/authorize")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"client_id\": \"fleet\",\n \"redirect_uri\": \"cursor://oauth/callback\",\n \"code_challenge\": \"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\",\n \"code_challenge_method\": \"S256\",\n \"agent_id\": \"agent-123\",\n \"resource\": \"https://mcp-server.example.com\",\n \"state\": \"xyz\",\n \"plan_id\": \"105906634574379352540220884472\",\n \"provider_payment_method_id\": \"<string>\",\n \"spending_limit_cents\": 5000,\n \"duration_secs\": 2592000\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sandbox.nevermined.app/oauth/authorize")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"client_id\": \"fleet\",\n \"redirect_uri\": \"cursor://oauth/callback\",\n \"code_challenge\": \"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\",\n \"code_challenge_method\": \"S256\",\n \"agent_id\": \"agent-123\",\n \"resource\": \"https://mcp-server.example.com\",\n \"state\": \"xyz\",\n \"plan_id\": \"105906634574379352540220884472\",\n \"provider_payment_method_id\": \"<string>\",\n \"spending_limit_cents\": 5000,\n \"duration_secs\": 2592000\n}"
response = http.request(request)
puts response.read_body{
"code": "abc123…"
}{
"code": "BCK.OAUTH.0016",
"message": "Unknown OAuth client",
"category": "auth",
"hint": "<string>",
"retryable": true,
"httpStatus": 400
}{
"code": "BCK.OAUTH.0016",
"message": "Unknown OAuth client",
"category": "auth",
"hint": "<string>",
"retryable": true,
"httpStatus": 400
}Authorizations
A Nevermined API key: Authorization: Bearer <sandbox:… | live:…>. Environment-prefixed, not a bare JWT — send the whole string.
Body
Pre-registered OAuth client (connector).
"fleet"
"cursor://oauth/callback"
PKCE challenge (base64url SHA-256).
"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"
S256 "S256"
Target agent for the grant. Optional.
"agent-123"
RFC 8707 resource (audience) — SELECTS the credential type: this API's host → NVM API key; any other resource → x402 payment permission. Omit it and the binding decides (delegation-backed → x402 permission; plan-only → NVM API key).
"https://mcp-server.example.com"
CSRF protection.
"xyz"
Plan to authorize against. Optional.
"105906634574379352540220884472"
Account-level (account_access) spend mandate only: the card rail backing the cap. Plan-agnostic card providers only. All five spend-mandate fields are REQUIRED together for an account-level grant (partial presence → BCK.OAUTH.0026); they are ignored for an agent-specific grant.
stripe, braintree, vgs Account-level only: the enrolled card id backing the delegation. Part of the all-or-nothing spend-mandate set (see provider).
Account-level only: cumulative spend cap in cents (smallest currency unit), 1..100000000 ($1,000,000 ceiling). This is where a cap is SET; its consumption surfaces later as AgentBindingSummary.spendingLimitCents / amountSpentCents.
1 <= x <= 1000000005000
Account-level only: the spend cap's active window in seconds, 1..31536000 (1-year ceiling).
1 <= x <= 315360002592000
Account-level only: the fiat currency of the spend cap. Card rails only — crypto codes are rejected.
usd, eur Response
Authorization code
Authorization code to exchange at /oauth/token.
"abc123…"
Was this page helpful?