# Social Contact Expand

`POST /social_contact_expand`

- Live: `POST https://gdapi.globaldata.net.au/api/v2/social_contact_expand`
- Sandbox: `POST https://sandbox-gdapi.globaldata.net.au/api/v2/social_contact_expand`

The `social_contact_expand` method takes a batch of contact identifiers (phone numbers, email
addresses, or social media profile URLs) and, for each one, surfaces additional contact phones
and emails associated with that person.

For each input the endpoint runs two stages:

1. **`social_search`** - a social media check is performed against the supplied identifier.
   Any phones or emails returned by the social check are included in this block.
2. **`universe_search`** - one universe lookup is performed for each phone or email known for
   the contact: the original input itself (when it is a phone or email), plus any phones or
   emails returned by the social check. Each lookup that finds related persons in our universe
   database produces its own `universe_search` block listing the additional phones and emails
   discovered for those persons.

## Result blocks - "no match" means the block is omitted

Each lookup is treated independently and **only blocks that actually returned phones or emails
appear in the response**. There is no fixed number or order guarantee for the blocks - the
caller should iterate over `records` and inspect each block's `type`. Specifically:

- If the social check found nothing but a universe lookup did, only the matching
  `universe_search` block(s) are returned (no `social_search` block).
- If the social check found phones or emails but none of the universe lookups (including the
  one for the original input, if applicable) found anything, only the `social_search` block is
  returned (no `universe_search` blocks).
- If both stages produced data, the response contains the `social_search` block and one
  `universe_search` block per universe lookup that found data.
- If nothing matched anywhere, `records` is an empty array and `message` is `No match`.

The per-item `message` field summarises this overall outcome (`Ok` if any block has data,
`No match` otherwise). Suppressed phones and emails are excluded from results.

## Supported inputs

Each request item's `search` value is auto-detected as one of the following:

- **Email address** - any RFC-compliant email address.
- **Phone number** - in either E.164 format (e.g. `+61412345678`) or Australian local 0NSN
  format (e.g. `0412345678`).
- **Social media profile URL** - same supported networks and URL formats as the
  [Social Check](#operation/social_check) endpoint. Profile URLs cannot be searched in the
  universe database, so a profile-only input will only yield universe matches when the social
  check returns associated phones or emails.

Invalid inputs (e.g. malformed values) return a per-item `Error: Invalid search value` message
in the response and are not billed.

## Sandbox environment data

The sandbox uses the same simulated dataset as the [Social Check](#operation/social_check)
endpoint. Universe searches in the sandbox run against the sample Pango database.

## Request body

Batch of search records to expand.

| Field | Type | Description |
|-------|------|-------------|
| `requests` | array of objects [1..50 items] | **Required.** An array of search records to expand. Maximum 50 records per call. |
| `requests[].search_id` | string [max 50 characters] | An optional caller-provided identifier for this search. When provided, it is echoed back in the corresponding result item so the caller can match results to inputs. Maximum 50 characters. Example: `abc-1` |
| `requests[].search` | string [max 200 characters] | **Required.** The contact identifier to expand. May be an email address, a phone number (E.164 or 0NSN format), or a social media profile URL. Maximum 200 characters. Example: `john@example.com` |

**Sample request**

```json
{
    "requests": [
        {
            "search_id": "abc-1",
            "search": "john@example.com"
        }
    ]
}
```

## Responses

### 200 Result of the contact expansion.

Content type: `application/json`

| Field | Type | Description |
|-------|------|-------------|
| `message` | string | A message indicating the result of the request. Will be `Ok` for any successful call. Example: `Ok` |
| `api_reference` | string (uuid) | Example: `738d9a89-b6fe-4fc1-96be-1389b2a506a2` |
| `results` | array of objects | Per-input result items, returned in the same order as the request. |
| `results[].search_id` | string or null | The caller-provided `search_id` (if any) for this input. Example: `abc-1` |
| `results[].search` | string | The original `search` value as supplied in the request. Example: `john@example.com` |
| `results[].message` | string | The per-input result. * `Ok` - The social search or at least one universe search returned phones/emails. * `No match` - No phones or emails were discovered for this input. * `Error: Invalid search value` - The supplied `search` value could not be recognised as an email, phone or social profile URL. Example: `Ok` |
| `results[].records` | array of objects | The discovered records for this input. Each item is either a `social_search` block (the social media check on the original input) or a `universe_search` block (a universe lookup on a phone or email). Only blocks that actually returned phones or emails are included - blocks for searches that produced no match are omitted entirely (so a response may contain only `universe_search` blocks if the social check produced no match, or only a `social_search` block if no universe lookup found anything). When `message` is `No match`, this array is empty. |
| `results[].records[].type` | string | The type of search this block represents. * `social_search` - results from the social media check. * `universe_search` - results from a universe lookup on a phone or email. Enum: `social_search`, `universe_search` Example: `social_search` |
| `results[].records[].search_for` | string | The phone, email or profile URL this block was searched for. For `social_search` this is the original input. For `universe_search` this is the phone or email that was looked up in the universe. Example: `john@example.com` |
| `results[].records[].emails` | array of strings | Email addresses discovered for this search. Lowercased. The original input email (if any) and the universe key being searched are excluded. |
| `results[].records[].phones` | array of strings | Phone numbers discovered for this search, in E.164 format. The original input phone (if any) and the universe key being searched are excluded. |

**Sample response**

```json
{
    "message": "Ok",
    "api_reference": "738d9a89-b6fe-4fc1-96be-1389b2a506a2",
    "results": [
        {
            "search_id": "abc-1",
            "search": "john@example.com",
            "message": "Ok",
            "records": [
                {
                    "type": "social_search",
                    "search_for": "john@example.com",
                    "emails": [
                        "john.doe@example.com"
                    ],
                    "phones": [
                        "+61412345001"
                    ]
                }
            ]
        }
    ]
}
```

Standard error responses: 400, 401, 402, 403, 429, 5XX (see [Common error responses](/docs/reference/general/common-error-responses.md))

