---
title: "Create S3 Grant"
method: POST
path: "/api/v1/admin/ledger/s3-grants"
tags: ["Admin APIs", "ledger"]
---

# Create S3 Grant

`POST /api/v1/admin/ledger/s3-grants`

Award S3 tokens to a client, writing the grant and its full vesting schedule.

Credits nothing here — the vesting executor posts each period's credit when its
``vest_at`` arrives, including an ``immediate`` grant's single already-due period. That
keeps every S3 credit on one code path with one idempotency anchor.

Returns the ``grant_id`` so the UI can link to the award it just created, and replays
safely: the same idempotency key returns the stored grant with ``already_existed=true``
and writes nothing.

Naming a ``block_request_id`` whose contract does not exist yet holds the award
``awaiting_contract`` with **no vesting rows**: there is no billing anchor until the
contract starts, and the subscription webhook builds the schedule then. Such a response
carries ``effective_at: null`` and ``vesting_count: 0``.

## Request body

- S3GrantCreateRequest — Cole's S3 token award. ``order_id`` and ``vesting_kind`` are typed columns rather than ``metadata`` entries: Finance searches awards by order reference, and the vesting kind decides how many rows get written. Neither survives being buried in an untyped JSON blob.
  - `client_id` string, required
  - `order_id` string, required
  - `reason` string, required
  - `amount` union, required
    - number
    - string
  - `vesting_kind` 'immediate' | 'monthly_12' — How a grant releases its tokens.
  - `effective_at` string, date-time, nullable
  - `block_contract_id` string, uuid, nullable
  - `block_request_id` string, uuid, nullable
  - `auto_apply` boolean, nullable
  - `idempotency_key` string, nullable
  - `metadata` object

## Response `200`

Successful Response

- S3GrantCreateResponse — The created award. Always carries ``grant_id`` so the UI can link to what it made.
  - `grant_id` string, uuid, required
  - `client_id` string, uuid, required
  - `order_id` string, required
  - `status` string, required
  - `vesting_kind` string, required
  - `allocated` string, required
  - `effective_at` string, date-time, nullable
  - `block_contract_id` string, uuid, nullable
  - `block_request_id` string, uuid, nullable
  - `auto_apply` boolean
  - `vesting_count` integer, required
  - `vestings` S3GrantVestingRow[], required
    - `period_seq` integer, required
    - `vest_at` string, date-time, required
    - `amount` string, required
    - `status` string, required
  - `already_existed` boolean, required

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.net/carbonarc/apis/carbon-arc-client-admin-api.md) · [All operations](https://skmtc.net/carbonarc/apis/carbon-arc-client-admin-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/carbonarc/carbon-arc-client-admin-api/revisions/a8ca30023371/schema)
