# Export the org's definitions as a sendops.json bundle

`GET /v1/export`

- Authentication: required (Bearer token)

Returns the organization's **managed** definitions as a bundle: a
`sendops.json` manifest plus the files it names — templates, segment
`.sendql` predicates, workflow `.flow` sources, the list / topic /
attribute / activity-property schema files, and the org's uploaded
images.

**Content is negotiated on `Accept`.** `Accept: application/zip` returns
a zip archive whose root is `sendops.json` (no wrapper directory —
the archive is a directory a CI job can zip and push back unchanged).
Anything else returns the JSON form, which inlines every file.

**Deterministic.** Two exports of an unchanged org are byte-identical:
sorted ordering throughout, fixed zip timestamps, and `.flow` files
rendered through the canonical formatter. An export is safe to commit on
a schedule without producing a diff every night.

**Scopes.** Any one view scope is enough. Each section needs its kind's
`.view` scope (`api.templates.view`, `api.segments.view`,
`api.lists.view`, `api.topics.view`, `api.attributes.view`,
`api.activities.view`, `api.workflows.view`, `api.assets.view`); a
section the credential cannot read is omitted and named in `omitted[]`
(or in the `X-SendOps-Omitted` response header, for the zip form) rather
than failing the call. A credential with none of them gets `403`.

## Example request

```bash
curl 'https://api.sendops.dev/v1/export' \
  -H "Authorization: Bearer $SENDOPS_API_KEY"
```

## Responses

### 200 — The bundle. `omitted[]` names the kinds the credential could not
read — empty means the bundle is the whole org.

Content type: `application/json`

```json
{
  "manifest": {},
  "files": {
    "templates/welcome.html": "<html>…</html>",
    "audience/all-contacts.sendql": "contact.email exists\n"
  },
  "images": {},
  "omitted": [
    "workflow"
  ]
}
```

### 401 — Missing, malformed, or unknown API key

Content type: `application/problem+json`

```json
{
  "type": "https://example.com",
  "title": "string",
  "status": 0,
  "detail": "string",
  "code": "invalid_key",
  "request_id": "string",
  "retry_after": 0,
  "retention_days": 0,
  "scope": "string",
  "resource": "string",
  "errors": [
    {
      "field": "string",
      "reason": "string"
    }
  ],
  "attribute_id": "00000000-0000-0000-0000-000000000000",
  "content_hash": "string",
  "differs": [
    "string"
  ]
}
```

### 403 — Key lacks the required scope or plan limit violated

Content type: `application/problem+json`

```json
{
  "type": "https://example.com",
  "title": "string",
  "status": 0,
  "detail": "string",
  "code": "invalid_key",
  "request_id": "string",
  "retry_after": 0,
  "retention_days": 0,
  "scope": "string",
  "resource": "string",
  "errors": [
    {
      "field": "string",
      "reason": "string"
    }
  ],
  "attribute_id": "00000000-0000-0000-0000-000000000000",
  "content_hash": "string",
  "differs": [
    "string"
  ]
}
```

### 429 — Per-org rate limit exceeded

Content type: `application/problem+json`

```json
{
  "type": "https://example.com",
  "title": "string",
  "status": 0,
  "detail": "string",
  "code": "invalid_key",
  "request_id": "string",
  "retry_after": 0,
  "retention_days": 0,
  "scope": "string",
  "resource": "string",
  "errors": [
    {
      "field": "string",
      "reason": "string"
    }
  ],
  "attribute_id": "00000000-0000-0000-0000-000000000000",
  "content_hash": "string",
  "differs": [
    "string"
  ]
}
```

### 500 — Unexpected server-side failure. The `code` is `internal_error`. The
`request_id` field can be quoted to SendOps support to investigate.

Content type: `application/problem+json`

```json
{
  "type": "https://example.com",
  "title": "string",
  "status": 0,
  "detail": "string",
  "code": "invalid_key",
  "request_id": "string",
  "retry_after": 0,
  "retention_days": 0,
  "scope": "string",
  "resource": "string",
  "errors": [
    {
      "field": "string",
      "reason": "string"
    }
  ],
  "attribute_id": "00000000-0000-0000-0000-000000000000",
  "content_hash": "string",
  "differs": [
    "string"
  ]
}
```
