Z Zise Developers 简体中文

Add a shipping address

POST /v1/shipping-addresses scope: addresses:write
On behalf of a member · x-on-behalf-of required Requires x-idempotency-key

The first address automatically becomes the default; no separate request is needed. To add an address and immediately make it the default, pass is_default: true.

── Required and optional fields ── Required: country (ISO 3166-1 alpha-2, two uppercase letters), recipient name (at least one of recipient_last / recipient_first), phone_code, phone_number, line1, city, and postal_code. Optional: label, province, district, and line2.

⚠ province / district are deliberately optional: not every country has provincial divisions (Singapore, Monaco, etc.). Requiring them would only encourage fabricated data.

⚠ Either a last name or a first name is sufficient: not every culture divides names into two parts.

⚠ postal_code is required. Known limitation: Hong Kong, Macao, the UAE, and some other regions have no postal codes; users there commonly enter 000000.

⚠ phone_code is stored as digits without +, and phone_number retains digits only. We sanitize +852 / 5123-4567 on input; reads return the sanitized form.

⚠ Field length limits are deliberately generous (name 40 / address line 120, etc.), exceeding most issuers' limits. Actual validation takes place when submitting the card application, according to the destination country and carrier. Tightening address entry based on assumptions would reject addresses that could be delivered successfully.

Each member may have at most 20 addresses; exceeding the limit returns limit_exceeded.

FieldTypeRequiredDescription
x-idempotency-key string Required
x-on-behalf-of string Required

Request Body

Request body fields have not been declared in the specification for this operation.

Response

201Created
400invalid_fields: fields[].key in the response identifies the field (country / recipient_last / phone_code / phone_number / line1 / city / postal_code); use it to take the user back to the relevant step. limit_exceeded: 20 addresses already exist. idempotency_key_required · member_context_required
Request
curl -X POST 'https://api.zinfra.vip/v1/shipping-addresses' \
  -H 'x-auth-token: Bearer $TOKEN' \
  -H 'x-on-behalf-of: $MEMBER_ID' \
  -H 'x-idempotency-key: $IDEMPOTENCY_KEY' \
  -H 'content-type: application/json' \
  -d '{
    "label": "家",
    "country": "HK",
    "recipient_last": "陈",
    "recipient_first": "小明",
    "phone_code": "852",
    "phone_number": "51234567",
    "city": "香港",
    "district": "中西区",
    "line1": "干诺道中 200 号",
    "postal_code": "000000",
    "is_default": true
  }'
const res = await fetch("https://api.zinfra.vip/v1/shipping-addresses", {
  method: "POST",
  headers: {
    "x-auth-token": "Bearer $TOKEN",
    "x-on-behalf-of": "$MEMBER_ID",
    "x-idempotency-key": "$IDEMPOTENCY_KEY",
    "content-type": "application/json",
  },
  body: JSON.stringify({
    "label": "家",
    "country": "HK",
    "recipient_last": "陈",
    "recipient_first": "小明",
    "phone_code": "852",
    "phone_number": "51234567",
    "city": "香港",
    "district": "中西区",
    "line1": "干诺道中 200 号",
    "postal_code": "000000",
    "is_default": true
  }),
});
// Keep monetary amounts as strings, never numbers.
const data = await res.json();
import requests

res = requests.post(
    "https://api.zinfra.vip/v1/shipping-addresses",
    headers={
        "x-auth-token": "Bearer $TOKEN",
        "x-on-behalf-of": "$MEMBER_ID",
        "x-idempotency-key": "$IDEMPOTENCY_KEY",
        "content-type": "application/json",
    },
    json={
      "label": "家",
      "country": "HK",
      "recipient_last": "陈",
      "recipient_first": "小明",
      "phone_code": "852",
      "phone_number": "51234567",
      "city": "香港",
      "district": "中西区",
      "line1": "干诺道中 200 号",
      "postal_code": "000000",
      "is_default": true
    },
)
# Use Decimal(str(...)) for amounts, not float.
data = res.json()
req, _ := http.NewRequest("POST", "https://api.zinfra.vip/v1/shipping-addresses",
    strings.NewReader(`{
  "label": "家",
  "country": "HK",
  "recipient_last": "陈",
  "recipient_first": "小明",
  "phone_code": "852",
  "phone_number": "51234567",
  "city": "香港",
  "district": "中西区",
  "line1": "干诺道中 200 号",
  "postal_code": "000000",
  "is_default": true
}`))
req.Header.Set("x-auth-token", "Bearer $TOKEN")
req.Header.Set("x-on-behalf-of", "$MEMBER_ID")
req.Header.Set("x-idempotency-key", "$IDEMPOTENCY_KEY")
req.Header.Set("content-type", "application/json")
res, err := http.DefaultClient.Do(req)
// Decode amount fields as string, not float64.
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.zinfra.vip/v1/shipping-addresses"))
    .header("x-auth-token", "Bearer $TOKEN")
    .header("x-on-behalf-of", "$MEMBER_ID")
    .header("x-idempotency-key", "$IDEMPOTENCY_KEY")
    .header("content-type", "application/json")
    .method("POST", HttpRequest.BodyPublishers.ofString("""
{
  "label": "家",
  "country": "HK",
  "recipient_last": "陈",
  "recipient_first": "小明",
  "phone_code": "852",
  "phone_number": "51234567",
  "city": "香港",
  "district": "中西区",
  "line1": "干诺道中 200 号",
  "postal_code": "000000",
  "is_default": true
}
"""))
    .build();
// Use String / BigDecimal for amounts, not double.
$ch = curl_init('https://api.zinfra.vip/v1/shipping-addresses');
curl_setopt_array($ch, [
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_HTTPHEADER => [
    'x-auth-token: Bearer $TOKEN',
    'x-on-behalf-of: $MEMBER_ID',
    'x-idempotency-key: $IDEMPOTENCY_KEY',
    'content-type: application/json',
  ],
  CURLOPT_POSTFIELDS => <<<'JSON'
{
  "label": "家",
  "country": "HK",
  "recipient_last": "陈",
  "recipient_first": "小明",
  "phone_code": "852",
  "phone_number": "51234567",
  "city": "香港",
  "district": "中西区",
  "line1": "干诺道中 200 号",
  "postal_code": "000000",
  "is_default": true
}
JSON,
]);
$res = curl_exec($ch);
// Use bcmath / strings for amounts, not floatval.
201
// No response example is declared in the specification for this operation.