Remove an endorsement
curl --request POST \
--url http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove \
--header 'Content-Type: application/json' \
--cookie __Host-argus-session= \
--data '
{
"reason": "Quashed on appeal"
}
'import requests
url = "http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove"
payload = { "reason": "Quashed on appeal" }
headers = {
"cookie": "__Host-argus-session=",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {cookie: '__Host-argus-session=', 'Content-Type': 'application/json'},
body: JSON.stringify({reason: 'Quashed on appeal'})
};
fetch('http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "3000",
CURLOPT_URL => "http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove",
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([
'reason' => 'Quashed on appeal'
]),
CURLOPT_COOKIE => "__Host-argus-session=",
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 := "http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove"
payload := strings.NewReader("{\n \"reason\": \"Quashed on appeal\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("cookie", "__Host-argus-session=")
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("http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove")
.header("cookie", "__Host-argus-session=")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"Quashed on appeal\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["cookie"] = '__Host-argus-session='
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"Quashed on appeal\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "cmg6a2lic000hl508lic00001",
"number": "HART9144223PA85",
"categories": [
"B"
],
"status": "VALID",
"suspendedUntil": null,
"issuedAt": "2026-10-06T19:30:00.000Z",
"expiresAt": "2036-10-06T19:30:00.000Z",
"points": 0,
"endorsements": [
{
"id": "cmg6a3end000il508end00001",
"code": "SP30",
"reason": "Exceeding 30 mph limit",
"points": 3,
"createdAt": "2026-10-06T19:42:10.000Z",
"expiresAt": null,
"active": false,
"issuedBy": {
"id": "cmg5x1k2a0000l508a1b2c3d4",
"displayName": "Olivia Officer"
},
"removedAt": "2026-10-06T19:42:10.000Z",
"removedBy": {
"id": "cmg5x1k2a0000l508a1b2c3d4",
"displayName": "Olivia Officer"
},
"removalReason": "Quashed on appeal",
"record": {
"id": "cmg6a5rec000kl508rec00001",
"reference": "REC-000045"
}
}
]
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Request validation failed.",
"details": [
{
"path": [
"reason"
],
"message": "Invalid input"
}
]
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "Sign in to continue."
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}{
"error": {
"code": "FORBIDDEN",
"message": "Permission required: pnc.licences.manage."
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}{
"error": {
"code": "ENDORSEMENT_NOT_ACTIVE",
"message": "The endorsement does not exist or was already removed."
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}{
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests."
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "The request could not be completed."
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}Licences
Remove an endorsement
Permission: pnc.licences.manage. Needs a signed-in user; service credentials are refused with USER_REQUIRED.
Access: Browser session only.
Withdraws an endorsement. It stays in the official view as removed, with who removed it and why, and stops counting towards points.
POST
/
pnc
/
licences
/
{id}
/
endorsements
/
{endorsementId}
/
remove
Remove an endorsement
curl --request POST \
--url http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove \
--header 'Content-Type: application/json' \
--cookie __Host-argus-session= \
--data '
{
"reason": "Quashed on appeal"
}
'import requests
url = "http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove"
payload = { "reason": "Quashed on appeal" }
headers = {
"cookie": "__Host-argus-session=",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {cookie: '__Host-argus-session=', 'Content-Type': 'application/json'},
body: JSON.stringify({reason: 'Quashed on appeal'})
};
fetch('http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_PORT => "3000",
CURLOPT_URL => "http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove",
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([
'reason' => 'Quashed on appeal'
]),
CURLOPT_COOKIE => "__Host-argus-session=",
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 := "http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove"
payload := strings.NewReader("{\n \"reason\": \"Quashed on appeal\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("cookie", "__Host-argus-session=")
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("http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove")
.header("cookie", "__Host-argus-session=")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"Quashed on appeal\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("http://localhost:3000/api/pnc/licences/{id}/endorsements/{endorsementId}/remove")
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url)
request["cookie"] = '__Host-argus-session='
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"Quashed on appeal\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "cmg6a2lic000hl508lic00001",
"number": "HART9144223PA85",
"categories": [
"B"
],
"status": "VALID",
"suspendedUntil": null,
"issuedAt": "2026-10-06T19:30:00.000Z",
"expiresAt": "2036-10-06T19:30:00.000Z",
"points": 0,
"endorsements": [
{
"id": "cmg6a3end000il508end00001",
"code": "SP30",
"reason": "Exceeding 30 mph limit",
"points": 3,
"createdAt": "2026-10-06T19:42:10.000Z",
"expiresAt": null,
"active": false,
"issuedBy": {
"id": "cmg5x1k2a0000l508a1b2c3d4",
"displayName": "Olivia Officer"
},
"removedAt": "2026-10-06T19:42:10.000Z",
"removedBy": {
"id": "cmg5x1k2a0000l508a1b2c3d4",
"displayName": "Olivia Officer"
},
"removalReason": "Quashed on appeal",
"record": {
"id": "cmg6a5rec000kl508rec00001",
"reference": "REC-000045"
}
}
]
}
}{
"error": {
"code": "INVALID_INPUT",
"message": "Request validation failed.",
"details": [
{
"path": [
"reason"
],
"message": "Invalid input"
}
]
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}{
"error": {
"code": "UNAUTHENTICATED",
"message": "Sign in to continue."
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}{
"error": {
"code": "FORBIDDEN",
"message": "Permission required: pnc.licences.manage."
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}{
"error": {
"code": "ENDORSEMENT_NOT_ACTIVE",
"message": "The endorsement does not exist or was already removed."
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}{
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests."
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "The request could not be completed."
},
"requestId": "3f1c9d5e-7a42-4f0b-9c1e-8b6d2a4e5f70"
}Authorizations
The opaque session cookie set by Discord sign-in. Named argus-session outside production. HttpOnly, so scripts cannot read it; same-origin requests send it automatically. Requests other than GET must also carry an Origin header equal to the application's own origin.
Path Parameters
Licence ID. Argus record identifier.
Required string length:
1 - 64Pattern:
^[a-zA-Z0-9_-]+$Endorsement ID. Argus record identifier.
Required string length:
1 - 64Pattern:
^[a-zA-Z0-9_-]+$Body
application/json
Required string length:
3 - 500Response
Success.
A driving licence as the PNC shows it, including removed endorsements and who recorded each.
Show child attributes
Show child attributes