> ## Documentation Index
> Fetch the complete documentation index at: https://docs.trygravity.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Provisioning API

> The contract your platform implements to enable agent-driven account provisioning

To let Gravity [provision accounts](/gravity-index/provisioning) on your
platform automatically, you expose one endpoint: Gravity sends you a user's email, you
create an account under that email and return the credentials. That's the
whole required contract.

You set your API base URL and mint the shared signing secret in the
[Index dashboard](/gravity-index/provisioning); no Gravity-side code changes
are needed.

## The create endpoint (required)

Gravity calls:

```http theme={null}
POST {your-base-url}/accounts
Content-Type: application/json
X-Gravity-Timestamp: <unix seconds>
X-Gravity-Signature: v1=<hex hmac>

{ "email": "user@example.com", "ttl_seconds": 604800 }
```

You create the account/resource under that email and respond:

```json theme={null}
{
  "account_ref": "<your account or resource id>",
  "credentials": { "PAT": "..." }
}
```

`credentials` is a flat object of env-var-style keys: whatever a coding agent
should write into a project's environment (`DATABASE_URL`, an API key, a PAT).
Gravity delivers them to the agent exactly once, then holds them only
encrypted at rest.

Send your own welcome email to the user at creation time. The account is
theirs, on your platform, from the moment it's created.

## Optional endpoints

<AccordionGroup>
  <Accordion title="Account lookup (recommended)">
    `POST {base}/accounts/lookup` with `{ "email": "..." }`, returning
    `{ "exists": true }`. When you expose this, Gravity checks it before
    creating anything and the agent tells the user "you already have an
    account" instead of creating a duplicate. Lookup failures never block
    provisioning.
  </Accordion>

  <Accordion title="Cleanup">
    `DELETE {base}/accounts/{account_ref}`. Called best-effort if Gravity
    fails to persist a provision after you created the resource, so nothing
    is stranded.
  </Accordion>

  <Accordion title="Ownership handoff (only if you need it)">
    Only relevant if your platform creates the resource somewhere the user
    can't immediately log into (e.g. a partner org) and needs the user to
    click a link to move it into their own account. In that case also return
    `ownership_url` (an https URL on your site) and optionally `expires_at`
    from the create call; Gravity passes it through to the agent verbatim.
    When the user completes the handoff, you can notify Gravity with a signed
    webhook:

    ```http theme={null}
    POST https://index.trygravity.ai/provision/webhook/{your-service-slug}

    { "event": "ownership.confirmed", "provision_id": "<uuid Gravity sent>" }
    ```

    If you create the account directly under the user's email (most
    platforms), skip all of this.
  </Accordion>
</AccordionGroup>

## Request signing

Every request Gravity sends you is signed with the shared secret you minted
in the dashboard. Verify it before creating anything:

```
payload   = "{timestamp}.{METHOD}.{path}.{raw_body}"
signature = "v1=" + hex(hmac_sha256(secret, payload))
```

* `METHOD`: uppercase HTTP method
* `path`: request path only, no host/query
* `raw_body`: exact request body bytes (empty string for bodyless requests)
* Reject timestamp skew over 300 seconds (replay protection)
* Compare with a constant-time comparison

Reference implementation:

```python theme={null}
import hmac, hashlib, time

def sign(secret: str, method: str, path: str, body: bytes) -> dict:
    ts = str(int(time.time()))
    payload = ".".join([ts, method.upper(), path]).encode() + b"." + body
    sig = "v1=" + hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest()
    return {"X-Gravity-Timestamp": ts, "X-Gravity-Signature": sig}
```

Webhooks you send to Gravity are signed the same way, with the same secret.

## What the agent receives

Gravity turns your create response into a single response to the requesting
agent; you never talk to the agent directly:

```json theme={null}
{
  "provision_id": "0b1e…",
  "service_slug": "your-service",
  "status": "provisioned",
  "credentials": { "PAT": "..." },
  "credentials_delivery": "inline_once",
  "env_vars": ["YOUR_SERVICE_PAT"],
  "integration_steps": ["Set YOUR_SERVICE_PAT in your env", "..."]
}
```

The agent writes the credentials into the project environment and keeps
building.

## Attribution & billing

Every provision mints a `grclid` and emits a conversion event **at provision
time**, the moment the account is created and credentials are delivered.
Same ledger and CPA billing as click-through conversions.

## Checklist

<Steps>
  <Step title="Implement POST {base}/accounts">
    Verify the signature, create the account under the email, return
    credentials.
  </Step>

  <Step title="Configure the dashboard">
    Turn on API provisioning for your service, save the base URL, mint the signing
    secret.
  </Step>

  <Step title="Send your own welcome email on creation">
    Recommended. Your brand, your inbox placement.
  </Step>
</Steps>

Questions? Contact us at
[myles@trygravity.ai](mailto:myles@trygravity.ai).
