---
title: Instructions to Export Usage Data
slug: instructions-to-export-usage-data
docTags: 
createdAt: 2026-06-30T21:55:50.208Z
---

Jobs to export data can be configured by calling the Jobs API.

### API Endpoints

| Method   | Endpoint                             | Description                     |
| -------- | ------------------------------------ | ------------------------------- |
| `GET`    | `https://app.amberflo.io/jobs`       | List all jobs                   |
| `GET`    | `https://app.amberflo.io/jobs/{id}`  | Get a job by ID                 |
| `POST`   | `https://app.amberflo.io/jobs`       | Create a job                    |
| `PUT`    | `https://app.amberflo.io/jobs`       | Update a job                    |
| `DELETE` | `https://app.amberflo.io/jobs/{id}`  | Delete a job by ID              |
| `POST`   | `https://app.amberflo.io/jobs/check` | Validate a job without creating |

All endpoints require the `X-API-KEY` header for authentication.

### Required Fields

| Field               | Description                                                                                                                                  |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `jobName`           | Unique name (alphanumeric, hyphens, spaces, commas, parentheses only)                                                                        |
| `s3Url`             | S3 bucket/path where exported data will be written                                                                                           |
| `format`            | Output format: `json`, `csv`, or `ndjson`                                                                                                    |
| `aggregationBucket` | Time granularity: `hour`, `day`, `week`, or `month`                                                                                          |
| `range`             | Lookback window in format `ago(#x)` where `#` is a positive integer and `x` is `d` (days), `h` (hours), or `m` (minutes). Example: `ago(7d)` |

### Scheduling (pick one)

| Field                    | Description                                                                   |
| ------------------------ | ----------------------------------------------------------------------------- |
| `cron`                   | Standard 5-field cron expression for recurring execution (e.g. `*/5 * * * *`) |
| `scheduledTimeInSeconds` | Unix epoch timestamp (seconds) for a one-off execution                        |

See [https://crontab.guru/](https://crontab.guru/) for constructing cron expression.

:::BlockQuote
**Note:** `cron` and `scheduledTimeInSeconds` are mutually exclusive. Provide one or neither.
:::

### Optional Fields

| Field             | Default | Description                                                    |
| ----------------- | ------- | -------------------------------------------------------------- |
| `description`     | `null`  | Human-readable description                                     |
| `email`           | `null`  | Notification email address                                     |
| `enabled`         | `true`  | Whether the job is active                                      |
| `sparse`          | `true`  | Return sparse query results                                    |
| `minimizeFresh`   | `true`  | Minimize fresh data in results                                 |
| `endTimeOffset`   | `null`  | End time offset in `ago(#x)` format                            |
| `meterApiNames`   | `null`  | Array of meter API names to query                              |
| `groupBy`         | `null`  | Array of dimensions to group by                                |
| `filter`          | `null`  | Object mapping dimension names to arrays of allowed values     |
| `rescaleFunction` | `null`  | Object with `function` (`multiply`) and `coefficient` (number) |

### Create a Job

```bash
curl -X POST https://app.amberflo.io/jobs \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: <YOUR_API_KEY>" \
  -d '{
    "jobName": "Daily export",
    "s3Url": "my-usage-bucket",
    "format": "csv",
    "aggregationBucket": "day",
    "range": "ago(7d)",
    "cron": "0 2 * * *",
    "enabled": true,
    "meterApiNames": ["api_calls", "storage"],
    "groupBy": ["customer_id"],
    "filter": {
      "region": ["us-east-1", "eu-west-1"]
    }
  }'
```

### Update a Job

```bash
curl -X PUT https://app.amberflo.io/jobs \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: <YOUR_API_KEY>" \
  -d '{
    "id": "<JOB_ID>",
    "jobName": "Daily export",
    "s3Url": "my-usage-bucket",
    "format": "csv",
    "aggregationBucket": "day",
    "range": "ago(7d)",
    "cron": "0 3 * * *",
    "enabled": true
  }'
```

### Delete a Job

```bash
curl -X DELETE https://app.amberflo.io/jobs/<JOB_ID> \
  -H "X-API-KEY: <YOUR_API_KEY>"
```

### Validate a Job (dry run)

```bash
curl -X POST https://app.amberflo.io/jobs/check \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: <YOUR_API_KEY>" \
  -d '{
    "jobName": "Daily export",
    "s3Url": "my-usage-bucket",
    "format": "csv",
    "aggregationBucket": "day",
    "range": "ago(7d)",
    "cron": "0 2 * * *"
  }'
```

### Validation

Use `POST /jobs/check` to validate a job configuration without creating it. It returns the validated job and the query that would be built.

### S3 Bucket Permissions

The user must grant Amberflo cross-account write access to their S3 bucket. The only permission required is `s3:PutObject`.

Add a bucket policy like:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<AMBERFLO_ACCOUNT_ID>:root"
      },
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::<CUSTOMER_BUCKET>/*",
      "Condition": {
        "StringEquals": {
          "s3:x-amz-acl": "bucket-owner-full-control"
        }
      }
    }
  ]
}
```

Objects are written with the `bucket-owner-full-control` ACL so the customer retains full ownership of the files in their bucket. No read, list, or delete permissions are needed.
