# Delivery methods

> Send gifts by email, SMS or a link you share yourself, track them, and fix a failed delivery.


Every gift in an order has a `delivery` object that says how it reaches the recipient. There are three methods: `email` and `phone`, where we send the gift for you, and `link`, where you deliver it yourself. One order can mix all three.

## Email

Set `method` to `email` and give the address:

**Request**

```json
"delivery": { "method": "email", "email": "sam@example.com" }
```

**What the recipient gets.** We email the gift right away. The sender name reads "The Acme team (via On Me)", using your `sender_name` or, if you didn't send one, your organization name, and the subject line says who sent the gift. The email links to the gift page, where the recipient opens and claims it.

**What you get back.** The gift echoes the address, trimmed and lowercased, with `status` set to `sent`:

**Response**

```json
"delivery": { "method": "email", "status": "sent", "email": "sam@example.com" }
```

`sent` means we've accepted the gift for delivery. If the email later can't be delivered, the status changes to `failed`; see [Fixing a failed delivery](#fixing-a-failed-delivery).

## SMS

Set `method` to `phone`, not `sms`, and give the number:

**Request**

```json
"delivery": { "method": "phone", "phone": "+1 (415) 555-1234" }
```

The number must start with `+` and a country code. Spaces, dashes, dots and parentheses are fine, and we store the number in E.164 format:

| You send | We store |
| --- | --- |
| `+14155551234` | `+14155551234` |
| `+1 (415) 555-1234` | `+14155551234` |
| `+1-415-555-1234` | `+14155551234` |
| `+1.415.555.1234` | `+14155551234` |
| `(415) 555-1234` | Rejected: no country code |
| `4155551234` | Rejected: no country code |

A number that isn't valid for its country is rejected too. Either way you get [`parameter_invalid`](https://business.onme.com/docs/reference#errors/parameter_invalid) with a `param` such as `gifts[0].delivery.phone`, and the order isn't created.

**What the recipient gets.** We text the gift right away. The message greets the recipient by `recipient_name` if you set one ("Hi Sam", otherwise "Hi there"), names the sender and the category, and includes the link to the gift page. It ends with a line saying who sent it, which includes the email address of your organization's billing contact, or of an admin if no billing contact is set.

**What you get back.** The gift echoes the number in E.164:

**Response**

```json
"delivery": { "method": "phone", "status": "sent", "phone": "+14155551234" }
```

As with email, `sent` means accepted for delivery, and it changes to `failed` if the text can't be delivered.

## Link

Set `method` to `link`. There's nothing else to send:

**Request**

```json
"delivery": { "method": "link" }
```

**What the recipient gets.** Nothing from us. We don't email or text anyone. You deliver the link through your own channel: your app, a chat message, an internal tool, a printed card.

**What you get back.** The gift includes `delivery.link`, the URL of the gift page:

**Response**

```json
"delivery": { "method": "link", "status": "sent", "link": "https://gift.onme.com/Xq7mT2pLk9RwZ4vB" }
```

The recipient opens the link, sees the gift, and claims it, the same page an email or SMS recipient lands on. For a link gift, `sent` means the link is ready; a link gift never reaches `failed`.

> **Warning: A link is as good as the gift** Anyone who has the link can claim the gift. Send it only to the recipient, over a channel you trust, and don't log it where others can read it.

## Delivery status

Each gift's `delivery.status` tells you how far it has got:

| Status | Meaning |
| --- | --- |
| `sent` | For email and SMS, we've accepted the gift for delivery. For a link, the link is ready to share. |
| `opened` | The recipient opened the gift page. |
| `claimed` | The recipient claimed the gift onto their On Me card. |
| `failed` | We couldn't deliver the email or text. Only `email` and `phone` gifts can fail. |

The status shows the furthest point a gift has reached. A gift that failed, was redirected and then claimed reads `claimed`.

To track gifts, poll `GET /v1/gifts/{gift_id}` for a single gift, or page through `GET /v1/gifts` to check many at once. Webhooks are planned, so you won't need to poll forever.

**cURL**

```bash
curl https://api.onme.com/v1/gifts/g-XLotjYqCLoI9pgf0jKYl5gXsNzxkBANTiq1VyivdeRA \
  -H "Authorization: Bearer $ONME_API_KEY"
```
**Node**

```js
const response = await fetch(`https://api.onme.com/v1/gifts/${giftId}`, {
  headers: { Authorization: `Bearer ${process.env.ONME_API_KEY}` },
})
const gift = await response.json()
console.log(gift.delivery.status)
```
**Python**

```python
import os

import requests

gift = requests.get(
    f"https://api.onme.com/v1/gifts/{gift_id}",
    headers={"Authorization": f"Bearer {os.environ['ONME_API_KEY']}"},
    timeout=30,
).json()
print(gift["delivery"]["status"])
```

## Link expiry

A gift link stops working a year after it was issued. You don't need to track that date. Fetch the gift with `GET /v1/gifts/{gift_id}` whenever you're about to share or re-share its link: if the link has expired and the gift hasn't been claimed, that response carries a fresh link, and the old one stops working.

Only the single-gift endpoint refreshes links. `GET /v1/gifts` and `GET /v1/orders` return whatever link the gift currently has, which may have expired. Use them for status, and fetch the single gift before sending a link to anyone.

## Fixing a failed delivery

When an email bounces or a text can't be delivered, the gift's status becomes `failed`. Redirect it to a corrected address or number:

`PUT /v1/gifts/{gift_id}/delivery` ([API reference](https://business.onme.com/docs/reference#tag/gifts/PUT/v1/gifts/{gift_id}/delivery))

**cURL**

```bash
curl -X PUT https://api.onme.com/v1/gifts/g-XLotjYqCLoI9pgf0jKYl5gXsNzxkBANTiq1VyivdeRA/delivery \
  -H "Authorization: Bearer $ONME_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "method": "email", "email": "sam.lee@example.com" }'
```
**Node**

```js
const response = await fetch(`https://api.onme.com/v1/gifts/${giftId}/delivery`, {
  method: 'PUT',
  headers: {
    Authorization: `Bearer ${process.env.ONME_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ method: 'email', email: 'sam.lee@example.com' }),
})
const gift = await response.json()
```
**Python**

```python
import os

import requests

gift = requests.put(
    f"https://api.onme.com/v1/gifts/{gift_id}/delivery",
    headers={"Authorization": f"Bearer {os.environ['ONME_API_KEY']}"},
    json={"method": "email", "email": "sam.lee@example.com"},
    timeout=30,
).json()
```

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `method` | string | Yes | (enum: email \| phone) |
| `email` | string | No | When method is email. Address to re-send the gift to. (format: email) |
| `phone` | string | No | When method is phone. Number to re-send the gift to, in international format. Stored in E.164. |

The response is the updated gift, with the new destination and `status` back to `sent`. We send the gift to the new destination right away, and the link in the undelivered message stops working.

You can redirect a gift when all of these are true:

- It was sent by `email` or `phone`. Link gifts can't be redirected, and a gift can't be switched to `link`.
- Its status is `failed`. A gift that was delivered can't be rerouted, even to fix a typo, so that no one can redirect a gift that already reached someone.
- It hasn't been claimed.

You can switch methods while you redirect, from email to SMS or the other way round. Each gift can be redirected up to 10 times.

These errors mean the redirect was refused and nothing changed:

| Code | When |
| --- | --- |
| [`gift_delivery_not_updatable`](https://business.onme.com/docs/reference#errors/gift_delivery_not_updatable) | The gift's delivery hasn't failed, or it's a link gift. |
| [`gift_already_redeemed`](https://business.onme.com/docs/reference#errors/gift_already_redeemed) | The recipient has already claimed the gift. |
| [`gift_resend_limit_reached`](https://business.onme.com/docs/reference#errors/gift_resend_limit_reached) | The gift has been redirected the maximum number of times. |
| [`parameter_invalid`](https://business.onme.com/docs/reference#errors/parameter_invalid) | The new email or phone number is invalid. `param` names the field. |
| [`resource_missing`](https://business.onme.com/docs/reference#errors/resource_missing) | No gift with that ID belongs to your organization. |
