Cancel a Label
/api/v1/labels/{labelId}
Outcome
After successful Label purchase,
retain postageLabel.id. Send that identifier to
Cancel Label,
then inspect the JSON result containing data.isSuccess.
Keep that documented operation result separate from provider action, Mailhub local state, financial outcomes, and Order or Shipment state.
When to use
Use this guide when your application wants to request cancellation of a
previously purchased Label identified by postageLabel.id.
Download Label is surrounding workflow context only; downloading is not a cancellation prerequisite.
When not to use
This guide does not define refunds or credits, provider confirmation, cancellation windows, guaranteed eligibility, tracking cancellation, Order status updates, Shipment lifecycle changes, safe blind retry, reconciliation after ambiguous outcomes, or a support escalation path.
Prerequisites
Have:
- a valid bearer credential for the intended Account;
- the retained
postageLabel.idfrom a successful Label-purchase response; - application handling for a state-changing request and an ambiguous transport outcome.
X-SubAccount-Id is optional in the current operation contract. Its metadata
states that it has no effect on Cancel Label, so it is not a required input.
Conceptual explanation
The current public response exposes only the bounded operation result.
| Concern | Public response coverage |
|---|---|
| Operation result | data.isSuccess |
| Provider or carrier action | Not represented separately. |
| Mailhub local Label state | Not represented separately. |
| Refund or credit | Not represented. |
| Order or Shipment state | Not represented. |
The API Reference remains the complete request and response schema source.
End-to-end flow
successful Label purchase
-> retain postageLabel.id
-> send CancelLabel request
-> inspect HTTP status and JSON envelope
-> read data.isSuccess
-> do not infer provider, state, or financial completion beyond the public result
Request example
labelId is the required path-parameter name. Supply the retained
postageLabel.id value for it. The operation has no request body.
DELETE <API_BASE_URL>/api/v1/labels/<LABEL_ID>
Authorization: Bearer <ACCESS_TOKEN>
Use a configured base URL; no fixed public host is published. The optional
X-SubAccount-Id header has no effect on this operation. See the
API Reference for complete parameter details.
The same request in a runnable form. MAILHUB_API_BASE_URL,
MAILHUB_ACCESS_TOKEN, and the Label identifier come from your environment;
nothing is inlined:
- cURL
- JavaScript
- Python
- C#
- Java
curl -s -X DELETE "${MAILHUB_API_BASE_URL}/api/v1/labels/${LABEL_ID}" \
-H "Authorization: Bearer ${MAILHUB_ACCESS_TOKEN}"
const response = await fetch(
`${process.env.MAILHUB_API_BASE_URL}/api/v1/labels/${labelId}`,
{
method: 'DELETE',
headers: {Authorization: `Bearer ${process.env.MAILHUB_ACCESS_TOKEN}`},
},
);
const payload = await response.json();
// payload.data.isSuccess is the documented operation result — nothing more.
const cancellationResult = payload.data?.isSuccess;
import os
import requests
response = requests.delete(
f"{os.environ['MAILHUB_API_BASE_URL']}/api/v1/labels/{label_id}",
headers={"Authorization": f"Bearer {os.environ['MAILHUB_ACCESS_TOKEN']}"},
)
payload = response.json()
# payload["data"]["isSuccess"] is the documented operation result — nothing more.
cancellation_result = (payload.get("data") or {}).get("isSuccess")
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Bearer", Environment.GetEnvironmentVariable("MAILHUB_ACCESS_TOKEN"));
var baseUrl = Environment.GetEnvironmentVariable("MAILHUB_API_BASE_URL");
var response = await client.DeleteAsync($"{baseUrl}/api/v1/labels/{labelId}");
// Read data.isSuccess from the JSON body as the documented operation result.
var payload = await response.Content.ReadAsStringAsync();
// Java 11+ java.net.http — no MailHub package to install and no third-party client.
var request = HttpRequest.newBuilder()
.uri(URI.create(System.getenv("MAILHUB_API_BASE_URL") + "/api/v1/labels/" + labelId))
.header("Authorization", "Bearer " + System.getenv("MAILHUB_ACCESS_TOKEN"))
.DELETE()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
// Read data.isSuccess from response.body() as the documented operation result.
Success response
A successful cancellation answers 200. The whole payload is the one
documented boolean:
{
"success": true,
"data": {
"isSuccess": true
},
"errors": null
}
Read the boolean rather than inferring anything further from the status. What that boolean does and does not mean is the next section.
Interpreting data.isSuccess
The operation returns a JSON result containing data.isSuccess. Treat the
boolean only as the documented operation result.
Do not treat it as refund confirmation. Do not treat it as provider or carrier void proof. Do not treat it as an Order-status or Label-state response. Do not infer timing from it.
Eligibility and state boundaries
Cancellation can fail. Eligibility is not defined as a universal public carrier/time-window contract, and the current public documentation does not define a complete Label state machine. Do not convert the operation result into an automatic Order or Shipment lifecycle claim.
Handling errors
Inspect the actual response and Label Errors. The API keeps these documented outcomes distinct:
| Status | Current public description |
|---|---|
400 | Invalid request. |
401 | Not authenticated. |
403 | Authenticated, but not with an Open API integration token. Sent without a body. |
404 | The label, its shipment, or its carrier does not exist for your account. |
409 | The sub-account given in X-SubAccount-Id is not active. |
422 | The label cannot be cancelled as it stands — its shipment has no tracking code to cancel against. |
500 | The request could not be completed because of an unexpected server-side failure. |
The API Reference is the complete source for response details. This guide does not promise that retrying an error will change its outcome.
Handling timeout or lost response
After a timeout or lost response, the cancellation outcome may be ambiguous. Do not blindly repeat the cancellation request.
Provider, local-state, and financial outcomes cannot be determined from the missing response. No public reconciliation workflow is currently defined. No blanket repeat-request safety contract exists.
Production guidance
- Retain
postageLabel.idfrom the successful purchase response. - Log the HTTP status and bounded response metadata without credentials.
- Do not log bearer credentials or other secrets.
- Keep the cancellation result separate from accounting or refund logic.
- Do not update local Order or Shipment state solely from assumptions.
- Do not rely on undeclared headers.
- Route an ambiguous outcome through your application's controlled operational process without presenting that process as a Mailhub public contract.
- Use the API Reference for complete schemas.
Next steps
- Review the Labels concept.
- Start with Buy a Label when purchasing a Label.
- Use Download a Label for the documented binary retrieval operation.
- Review Label Errors.
- Use Order Lifecycle as the separate public reference for Order status information.
- Open the API Reference for complete operation schemas.