# Important concepts

A few objects and ideas turn up across the whole API. Reading these once saves
re-reading them on every endpoint.

## Addresses

An address is always the same object, whatever key it appears under:
`collection_address` and `delivery_address` have identical fields.

```json
"collection_address": {
  "type": "business",
  "company": "Bob Go",
  "street_address": "125 Dallas Avenue",
  "local_area": "Menlyn",
  "city": "Pretoria",
  "zone": "Gauteng",
  "country": "ZA",
  "code": "0181"
}
```

| Field | Type | Notes |
| --- | --- | --- |
| `type` | string | `business`, `residential`, `locker` or `unknown`. Defaults to `unknown`. Affects both price and which service levels are offered. |
| `company` | string | Optional. |
| `street_address` | string | Street number and name. |
| `local_area` | string | Suburb. |
| `city` | string | |
| `zone` | string | Province, as its name (`Gauteng`) or its code (`GP`). Bob Go stores the code, so addresses come back with `EC`, `FS`, `GP`, `KZN`, `LP`, `MP`, `NC`, `NW` or `WC`, and filters on the province take the code. |
| `code` | string | Postal code. |
| `country` | string | `ZA` or `South Africa`. Bob Go ships within South Africa only, and an empty value is read as South Africa. Addresses come back with `South Africa`. |
| `lat`, `lng` | number | Optional. Supply them and Bob Go skips geocoding. |

Send the fields separately rather than packing everything into
`street_address`. Rating and courier acceptance both depend on the address
resolving to a real point on the map, and a single free-text line geocodes
badly.

## Parcels

Wherever a set of parcels is sent, it is the same array.

```json
"parcels": [
  {
    "description": "Box",
    "submitted_length_cm": 42.5,
    "submitted_width_cm": 38.5,
    "submitted_height_cm": 5.5,
    "submitted_weight_kg": 3,
    "custom_parcel_reference": "custom reference"
  },
  {
    "description": "Flyer",
    "submitted_length_cm": 42.5,
    "submitted_width_cm": 38.5,
    "submitted_height_cm": 5.5,
    "submitted_weight_kg": 1.3
  }
]
```

| Field | Type | Notes |
| --- | --- | --- |
| `submitted_length_cm` | number | Max 1000. |
| `submitted_width_cm` | number | Max 1000. |
| `submitted_height_cm` | number | Max 1000. |
| `submitted_weight_kg` | number | A parcel over the maximum weight is rejected, and the message gives the limit. Each service level also has its own limit, on the total and the volumetric weight: a consignment over it fails that one rate with the limit in `failed_reason`, rather than failing the request. |
| `description` | string | Optional. |
| `custom_parcel_reference` | string | Optional, your own reference. |

The `submitted_` prefix is deliberate: these are the dimensions *you* declared.
Couriers re-measure, and the values they come back with land in the matching
`actual_` fields on the shipment. Couriers charge on the greater of actual and
volumetric weight, so dimensions matter as much as weight, and a parcel
declared smaller than it is will be re-rated after collection.

## Rates at checkout vs. Rates

Two endpoints return shipping prices, and they answer different questions.

**[Rates at checkout](../5_Rates%20at%20checkout/rates_at_checkout.md)**
(`POST /v2/rates-at-checkout`) returns the options *you have configured in Bob
Go*: your service levels, your zones, your markups, your exclusions. It is
what a buyer should see in a cart. Each option is priced the way you set it up,
whether that is a dynamic, fixed, courier or formula rate, and it can
deliberately return nothing for an area you do not ship to.

**[Rates](../8_Rates/rates.md)** (`POST /v2/rates`) returns what each courier
will cost you for a specific consignment, with none of your checkout rules
applied. It is what you use to decide which courier to book.

| | Rates at checkout | Rates |
| --- | --- | --- |
| Answers | "What should this buyer be charged?" | "What will each courier charge me?" |
| Shaped by | Your Bob Go configuration | The couriers |
| Typical caller | Your cart or checkout page | Your fulfilment code |
| Returns | Priced options, buyer-facing | Per-courier quotes with a `rate_amount` |

The two are not interchangeable. A buyer quoted a checkout rate is not being
quoted the courier's price, and the difference between them is your shipping
margin.

## Pickup points

Shipments can collect from, or deliver to, a locker or counter instead of an
address. Pickup points work through the same rates, checkout-rates and shipment
endpoints, with a couple of extra fields.
See [Pickup points](../12_Pickup%20points/locations.md).
