API reference
Billing and usage API
Balances, limits, metered usage, invoice preview, and billing management.
- Get billing:
GET /v1/billing - Change billing settings:
PATCH /v1/billing - Start a checkout:
POST /v1/billing/checkout - Open the payment portal:
POST /v1/billing/portal - Verify a card for the trial:
POST /v1/billing/card-check - Cancel the plan at period end:
POST /v1/billing/subscription/cancel - Resume a cancelled plan:
POST /v1/billing/subscription/resume - End the trial early:
POST /v1/billing/trial/end - Get automatic refill:
GET /v1/billing/auto-refill - Change automatic refill:
PUT /v1/billing/auto-refill - Preview the invoice:
GET /v1/billing/invoice-preview - Get limits:
GET /v1/limits - Get organization usage:
GET /v1/usage - Get machine usage:
GET /v1/machines/{machine_id}/usage - Receive a Stripe event:
POST /v1/billing/stripe/webhook - Grant credits or time (operators):
POST /v1/operator/billing/grants - List wallet movements:
GET /v1/billing/ledger - Grant credits from VMYard (operators):
POST /v1/operator/billing/credits
Get billing
GET /v1/billing
- API key:
Authorization: Bearer vmy_…with presetread_only,use_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie. - Who: Any member.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | BillingDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
curl "$VMYARD_API_URL/v1/billing" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"balances": {
"credit_micros": 0,
"plan_micros": 0,
"spendable_micros": 0,
"trial_micros": 0
},
"card_check": {
"required": false,
"verified_at": "string"
},
"credit_spent_this_month_micros": 0,
"currency": "USD",
"exhausted_since": "string",
"limits": {
"concurrent_machines": {
"limit": 0,
"used": 0
},
"starts": [
{
"limit": 0,
"used": 0,
"window": "hour"
}
],
"status": "trial",
"tier": "pro"
},
"minimum_balance_micros": 0,
"organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"payment_customer_linked": false,
"payments_available": false,
"plan": {
"active": false,
"cancel_at_period_end": false,
"included_micros": 0,
"included_seconds": 0,
"period_end": "string",
"period_start": "string",
"price_micros": 0,
"renews": false,
"tier": "pro"
},
"spend_cap_micros": 0,
"status": "trial",
"trial": {
"active": false,
"concurrent_machines": 0,
"ended_at": "string",
"max_hourly_micros": 0,
"remaining_micros": 0,
"remaining_seconds": 0,
"total_micros": 0
}
}Change billing settings
PATCH /v1/billing
- API key:
Authorization: Bearer vmy_…with presetfull_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner or Billing.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Request body (application/json, UpdateBillingRequest)
| Field | Type | Required | Description |
|---|---|---|---|
minimum_balance_micros | integer | null | No | |
spend_cap_micros | integer | null | No | Monthly credit spend cap in micros, or null to remove it. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | BillingDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
curl -X PATCH "$VMYARD_API_URL/v1/billing" \
-H "Authorization: Bearer $VMYARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"spend_cap_micros": 100000000,
"minimum_balance_micros": 0
}'{
"balances": {
"credit_micros": 0,
"plan_micros": 0,
"spendable_micros": 0,
"trial_micros": 0
},
"card_check": {
"required": false,
"verified_at": "string"
},
"credit_spent_this_month_micros": 0,
"currency": "USD",
"exhausted_since": "string",
"limits": {
"concurrent_machines": {
"limit": 0,
"used": 0
},
"starts": [
{
"limit": 0,
"used": 0,
"window": "hour"
}
],
"status": "trial",
"tier": "pro"
},
"minimum_balance_micros": 0,
"organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"payment_customer_linked": false,
"payments_available": false,
"plan": {
"active": false,
"cancel_at_period_end": false,
"included_micros": 0,
"included_seconds": 0,
"period_end": "string",
"period_start": "string",
"price_micros": 0,
"renews": false,
"tier": "pro"
},
"spend_cap_micros": 0,
"status": "trial",
"trial": {
"active": false,
"concurrent_machines": 0,
"ended_at": "string",
"max_hourly_micros": 0,
"remaining_micros": 0,
"remaining_seconds": 0,
"total_micros": 0
}
}Start a checkout
POST /v1/billing/checkout
- API key:
Authorization: Bearer vmy_…with presetfull_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner or Billing.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Request body (application/json, CheckoutRequestDto)
| Field | Type | Required | Description |
|---|---|---|---|
credit_packs | integer | null | No | Buy this many $20 credit packs (1-50). |
end_trial | boolean | No | With plan: forfeit the remaining trial once the plan's first payment is confirmed, so the plan's allowance is used right away. |
plan | string | null | No | Subscribe to starter, pro, team, or scale. |
Responses
| Status | Description | Body |
|---|---|---|
201 | — | CheckoutDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
501 | billing_unavailable: payments are not configured | ProblemDetails |
502 | payment_provider_error | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/billing/checkout" \
-H "Authorization: Bearer $VMYARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"credit_packs": 2
}'{
"checkout_url": "string",
"session_id": "string"
}Open the payment portal
POST /v1/billing/portal
- API key:
Authorization: Bearer vmy_…with presetfull_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner or Billing.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
201 | — | PortalDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
409 | billing_customer_missing: no purchase has linked a payment customer yet | ProblemDetails |
501 | billing_unavailable: payments are not configured | ProblemDetails |
502 | payment_provider_error | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/billing/portal" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"url": "https://hooks.example.com/vmyard"
}Verify a card for the trial
POST /v1/billing/card-check
Start a card check: a hosted setup page where a billing manager enters a
card, which the provider verifies (and screens for fraud) without
charging it. The signed checkout.session.completed webhook records the
verification; until then a trial cannot start machines when the service
requires a card (402 card_verification_required).
Opens the payment provider's page where a card is checked, not charged. When card_check.required is true on GET /v1/billing, a trial can't create, start, or restart machines (402 card_verification_required) until the check completes. See Usage, billing, and limits.
- API key:
Authorization: Bearer vmy_…with presetfull_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner or Billing.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
201 | — | CardCheckSessionDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
501 | billing_unavailable: payments are not configured | ProblemDetails |
502 | payment_provider_error | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/billing/card-check" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"checkout_url": "string",
"session_id": "string"
}Cancel the plan at period end
POST /v1/billing/subscription/cancel
The plan keeps its allowance until plan.period_end, then ends. See Cancel a plan or end the trial.
- API key:
Authorization: Bearer vmy_…with presetfull_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner or Billing.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
200 | The plan stays active until plan.period_end, then ends | BillingDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
409 | subscription_missing: no renewing subscription is linked | ProblemDetails |
501 | billing_unavailable | ProblemDetails |
502 | payment_provider_error | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/billing/subscription/cancel" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"balances": {
"credit_micros": 0,
"plan_micros": 0,
"spendable_micros": 0,
"trial_micros": 0
},
"card_check": {
"required": false,
"verified_at": "string"
},
"credit_spent_this_month_micros": 0,
"currency": "USD",
"exhausted_since": "string",
"limits": {
"concurrent_machines": {
"limit": 0,
"used": 0
},
"starts": [
{
"limit": 0,
"used": 0,
"window": "hour"
}
],
"status": "trial",
"tier": "pro"
},
"minimum_balance_micros": 0,
"organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"payment_customer_linked": false,
"payments_available": false,
"plan": {
"active": false,
"cancel_at_period_end": false,
"included_micros": 0,
"included_seconds": 0,
"period_end": "string",
"period_start": "string",
"price_micros": 0,
"renews": false,
"tier": "pro"
},
"spend_cap_micros": 0,
"status": "trial",
"trial": {
"active": false,
"concurrent_machines": 0,
"ended_at": "string",
"max_hourly_micros": 0,
"remaining_micros": 0,
"remaining_seconds": 0,
"total_micros": 0
}
}Resume a cancelled plan
POST /v1/billing/subscription/resume
- API key:
Authorization: Bearer vmy_…with presetfull_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner or Billing.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
200 | The plan renews again at plan.period_end | BillingDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
409 | subscription_missing: the subscription already ended | ProblemDetails |
501 | billing_unavailable | ProblemDetails |
502 | payment_provider_error | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/billing/subscription/resume" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"balances": {
"credit_micros": 0,
"plan_micros": 0,
"spendable_micros": 0,
"trial_micros": 0
},
"card_check": {
"required": false,
"verified_at": "string"
},
"credit_spent_this_month_micros": 0,
"currency": "USD",
"exhausted_since": "string",
"limits": {
"concurrent_machines": {
"limit": 0,
"used": 0
},
"starts": [
{
"limit": 0,
"used": 0,
"window": "hour"
}
],
"status": "trial",
"tier": "pro"
},
"minimum_balance_micros": 0,
"organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"payment_customer_linked": false,
"payments_available": false,
"plan": {
"active": false,
"cancel_at_period_end": false,
"included_micros": 0,
"included_seconds": 0,
"period_end": "string",
"period_start": "string",
"price_micros": 0,
"renews": false,
"tier": "pro"
},
"spend_cap_micros": 0,
"status": "trial",
"trial": {
"active": false,
"concurrent_machines": 0,
"ended_at": "string",
"max_hourly_micros": 0,
"remaining_micros": 0,
"remaining_seconds": 0,
"total_micros": 0
}
}End the trial early
POST /v1/billing/trial/end
End the trial now: its remaining balance is forfeited (a
trial_forfeit ledger row) and cannot be restored. Trial rules (two
machines, small/default sizes) still apply until the first payment.
Ending an ended trial changes nothing.
Forfeits the remaining trial balance for good; trial rules apply until the first payment. See Cancel a plan or end the trial.
- API key:
Authorization: Bearer vmy_…with presetfull_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner or Billing.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | BillingDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/billing/trial/end" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"balances": {
"credit_micros": 0,
"plan_micros": 0,
"spendable_micros": 0,
"trial_micros": 0
},
"card_check": {
"required": false,
"verified_at": "string"
},
"credit_spent_this_month_micros": 0,
"currency": "USD",
"exhausted_since": "string",
"limits": {
"concurrent_machines": {
"limit": 0,
"used": 0
},
"starts": [
{
"limit": 0,
"used": 0,
"window": "hour"
}
],
"status": "trial",
"tier": "pro"
},
"minimum_balance_micros": 0,
"organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"payment_customer_linked": false,
"payments_available": false,
"plan": {
"active": false,
"cancel_at_period_end": false,
"included_micros": 0,
"included_seconds": 0,
"period_end": "string",
"period_start": "string",
"price_micros": 0,
"renews": false,
"tier": "pro"
},
"spend_cap_micros": 0,
"status": "trial",
"trial": {
"active": false,
"concurrent_machines": 0,
"ended_at": "string",
"max_hourly_micros": 0,
"remaining_micros": 0,
"remaining_seconds": 0,
"total_micros": 0
}
}Get automatic refill
GET /v1/billing/auto-refill
- API key:
Authorization: Bearer vmy_…with presetread_only,use_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie. - Who: Any member.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | AutoRefillDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
curl "$VMYARD_API_URL/v1/billing/auto-refill" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"amount_micros": 0,
"charged_this_month_micros": 0,
"consecutive_failures": 0,
"credit_packs": 0,
"disabled_reason": "string",
"enabled": false,
"last_charge": {
"amount_micros": 0,
"created_at": "string",
"credit_packs": 0,
"failure_code": "string",
"id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"status": "string"
},
"monthly_cap_micros": 0,
"threshold_micros": 0
}Change automatic refill
PUT /v1/billing/auto-refill
Configure automatic refill. Enabling needs online payments, a linked customer, and a default payment method at the provider; it also clears the failure count of a refill that turned itself off.
All four fields are required. Enabling needs a linked customer and a default card at the payment provider. See Automatic refill.
- API key:
Authorization: Bearer vmy_…with presetfull_access. - Browser session: the
vmyard_sessioncookie and thex-csrf-tokenheader. - Who: Owner or Billing.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Request body (application/json, UpdateAutoRefillRequest)
| Field | Type | Required | Description |
|---|---|---|---|
credit_packs | integer | Yes | 1-50 packs of $20. 1–50. |
enabled | boolean | Yes | |
monthly_cap_micros | integer | Yes | At least one refill's amount. |
threshold_micros | integer | Yes |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | AutoRefillDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
403 | Refused for this caller: role, key preset, CSRF token, or organization (forbidden, insufficient_scope, csrf_invalid, organization_mismatch, session_required). | ProblemDetails |
409 | billing_customer_missing or payment_method_missing (set a default card in the portal) | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
501 | billing_unavailable | ProblemDetails |
502 | payment_provider_error | ProblemDetails |
curl -X PUT "$VMYARD_API_URL/v1/billing/auto-refill" \
-H "Authorization: Bearer $VMYARD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"credit_packs": 1,
"enabled": false,
"monthly_cap_micros": 0,
"threshold_micros": 0
}'{
"amount_micros": 0,
"charged_this_month_micros": 0,
"consecutive_failures": 0,
"credit_packs": 0,
"disabled_reason": "string",
"enabled": false,
"last_charge": {
"amount_micros": 0,
"created_at": "string",
"credit_packs": 0,
"failure_code": "string",
"id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"status": "string"
},
"monthly_cap_micros": 0,
"threshold_micros": 0
}Preview the invoice
GET /v1/billing/invoice-preview
- API key:
Authorization: Bearer vmy_…with presetread_only,use_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie. - Who: Any member.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | InvoicePreviewDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
curl "$VMYARD_API_URL/v1/billing/invoice-preview" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"applied": {
"credit_micros": 0,
"plan_micros": 0,
"trial_micros": 0
},
"credit_balance_micros": 0,
"currency": "USD",
"lines": [
{
"amount_micros": 0,
"description": "default · machine time",
"hourly_micros": 0,
"multiplier": 0.5,
"plan_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"plan_version": 0,
"seconds": 0
}
],
"next_charge_micros": 0,
"period_end": "string",
"period_start": "string",
"plan": {
"active": false,
"cancel_at_period_end": false,
"included_micros": 0,
"included_seconds": 0,
"period_end": "string",
"period_start": "string",
"price_micros": 0,
"renews": false,
"tier": "pro"
},
"unbilled_micros": 0,
"usage_micros": 0
}Get limits
GET /v1/limits
- API key:
Authorization: Bearer vmy_…with presetread_only,use_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie. - Who: Any member.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | LimitsDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
curl "$VMYARD_API_URL/v1/limits" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"concurrent_machines": {
"limit": 0,
"used": 0
},
"starts": [
{
"limit": 0,
"used": 0,
"window": "hour"
}
],
"status": "trial",
"tier": "pro"
}Get organization usage
GET /v1/usage
- API key:
Authorization: Bearer vmy_…with presetread_only,use_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie. - Who: Any member.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
since | query | string | No | RFC 3339 start (inclusive). Defaults to the current plan period's start, or the UTC month's start without a plan; for one machine, to its first run. |
until | query | string | No | RFC 3339 end (exclusive). Defaults to now. |
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | UsageDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
curl "$VMYARD_API_URL/v1/usage" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"cost_micros": 0,
"machines": [
{
"cost_micros": 0,
"hourly_micros": 0,
"machine_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"multiplier": 0.5,
"running": false,
"seconds": 0
}
],
"seconds": 0,
"since": "string",
"until": "string"
}Get machine usage
GET /v1/machines/{machine_id}/usage
- API key:
Authorization: Bearer vmy_…with presetread_only,use_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie. - Who: Any member.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
machine_id | path | string (uuid) | Yes | |
since | query | string | No | RFC 3339 start (inclusive). Defaults to the current plan period's start, or the UTC month's start without a plan; for one machine, to its first run. |
until | query | string | No | RFC 3339 end (exclusive). Defaults to now. |
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | MachineUsageDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
404 | Not found in this organization (resource_not_found). | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
curl "$VMYARD_API_URL/v1/machines/$MACHINE_ID/usage" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"cost_micros": 0,
"hourly_micros": 0,
"machine_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"multiplier": 0.5,
"running": false,
"seconds": 0
}Receive a Stripe event
POST /v1/billing/stripe/webhook
Stripe calls this with signed events. It needs no session or API key: the signature over the exact body is the authentication.
- Authentication: none on this route.
- Who: Stripe (signed request).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
Stripe-Signature | header | string | Yes | t=<unix seconds>,v1=<hex HMAC-SHA256> |
Request body (application/json)
No fields.
Responses
| Status | Description | Body |
|---|---|---|
200 | — | WebhookAckDto |
400 | invalid_signature or invalid_event | ProblemDetails |
501 | billing_unavailable | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/billing/stripe/webhook" \
-H "Stripe-Signature: $STRIPE_SIGNATURE" \
-H "Content-Type: application/json" \
-d '"string"'{
"outcome": "applied",
"received": false
}Grant credits or time (operators)
POST /v1/operator/billing/grants
Operators grant credits, trial time, or plan periods by hand (support, invoices paid offline, or a deployment without online payments). The caller presents the operator token configured for the service; members of an organization, however privileged, cannot reach it.
- Authentication: none on this route.
- Who: Service operators (operator token).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-VMYard-Operator-Token | header | string | Yes | Operator token from the service configuration |
Request body (application/json, OperatorGrantRequest)
| Field | Type | Required | Description |
|---|---|---|---|
idempotency_key | string | Yes | Replaying the same key applies the grant once. |
kind | GrantKindDto | Yes | |
organization_id | string (uuid) | Yes | |
reason | string | Yes | Why the grant was made; recorded in the audit log. |
amount_micros | integer | null | No | Micros for credits and trial. |
period_days | integer | null | No | Period length for plan_period, starting now (1-366, default 30). |
tier | string | null | No | Tier for plan_period. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | GrantResultDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
404 | operator grants are not configured or the organization is unknown | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/operator/billing/grants" \
-H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"organization_id": "2a7d4c1e-8b3f-4f6a-9c5d-0e1f2a3b4c5d",
"kind": "credits",
"amount_micros": 20000000,
"reason": "Invoice 1042 paid by bank transfer",
"idempotency_key": "grant-invoice-1042"
}'{
"outcome": "applied"
}List wallet movements
GET /v1/billing/ledger
The wallet's movements other than usage (grants, credits from VMYard,
purchases, expiries), newest first. Usage is reported by /v1/usage.
Grants, credits from VMYard, purchases, and expiries, newest first. Usage is in GET /v1/usage.
- API key:
Authorization: Bearer vmy_…with presetread_only,use_existing,create_and_use,full_access. - Browser session: the
vmyard_sessioncookie. - Who: Any member.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
limit | query | integer | No | 1-100, default 50. |
before | query | integer | No | Entries before this one (next_before of the previous page). |
X-Organization-ID | header | string (uuid) | No | Required with a browser session. Optional with an API key, which fixes the organization; when sent it must match. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | LedgerPage |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
curl "$VMYARD_API_URL/v1/billing/ledger" \
-H "Authorization: Bearer $VMYARD_API_KEY"{
"items": [
{
"amount_micros": 0,
"at": "string",
"bucket": "string",
"id": 0,
"kind": "trial_grant",
"label": "k7f2mq3x9a1b",
"plan_tier": "string"
}
],
"next_before": 0
}Grant credits from VMYard (operators)
POST /v1/operator/billing/credits
Grant credits from VMYard to an organization, or claw them back. They
are a gift, not a payment: the organization's status (and trial rules)
do not change. The organization sees each as "Credit from VMYard" in
GET /v1/billing/ledger.
- Authentication: none on this route.
- Who: Service operators (operator token).
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-VMYard-Operator-Token | header | string | Yes | Operator token from the service configuration |
Request body (application/json, OperatorCreditRequest)
| Field | Type | Required | Description |
|---|---|---|---|
amount_micros | integer | Yes | Positive micros (1 USD = 1000000). at least 1. |
idempotency_key | string | Yes | Replaying the same key applies the change once. |
kind | CreditKindDto | Yes | |
operator | string | Yes | The individual operator acting, 1-200 characters. |
organization_id | string (uuid) | Yes | |
reason | string | Yes | Why, 1-500 characters; kept on the ledger row and in the audit log, never shown to the organization. |
Responses
| Status | Description | Body |
|---|---|---|
200 | — | OperatorCreditDto |
401 | Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key). | ProblemDetails |
404 | operator access is not configured or the organization is unknown | ProblemDetails |
409 | insufficient_credit: a claw-back larger than the credit balance | ProblemDetails |
422 | Invalid request (invalid_request); field_errors names the fields. | ProblemDetails |
curl -X POST "$VMYARD_API_URL/v1/operator/billing/credits" \
-H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"amount_micros": 1,
"idempotency_key": "string",
"kind": "grant",
"operator": "string",
"organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
"reason": "string"
}'{
"credit_balance_micros": 0,
"outcome": "string"
}