Skip to content

API reference

Waitlist and access API

Invite-only access: the form service's sign-up hook, and for the people who run the service, the waitlist and access grants. Operator routes need the operator token.

On this page

Receive a waitlist sign-up

POST /v1/waitlist/tally

Accept a waitlist sign-up from the form service (Tally). The raw body must carry a valid Tally-Signature (base64 HMAC-SHA256 under the configured signing secret); unsigned or mis-signed requests are refused. Events other than FORM_RESPONSE are acknowledged and ignored. A second sign-up from the same address refreshes its answers.

  • Authentication: none on this route.
  • Who: The form service (signed request).

Parameters

NameInTypeRequiredDescription
Tally-SignatureheaderstringYesBase64 HMAC-SHA256 of the raw body under the waitlist signing secret

Request body (application/json)

No fields.

Responses

StatusDescriptionBody
200—WaitlistAckDto
401invalid_signature: missing or wrong signatureProblemDetails
404the waitlist webhook is not configuredProblemDetails
422the event has no valid email answerProblemDetails
Request
curl -X POST "$VMYARD_API_URL/v1/waitlist/tally" \
  -H "Tally-Signature: $TALLY_SIGNATURE" \
  -H "Content-Type: application/json" \
  -d '"string"'
Response 200
{
  "received": false
}

List waitlist entries (operators)

GET /v1/operator/waitlist

Waitlist entries, newest first.

  • Authentication: none on this route.
  • Who: Service operators (operator token).

Parameters

NameInTypeRequiredDescription
statusqueryWaitlistFilterDtoNopending (default), approved, rejected, revoked, or all.
limitqueryintegerNo1-500, default 100; newest first.
X-VMYard-Operator-TokenheaderstringYesOperator token from the service configuration

Responses

StatusDescriptionBody
200—WaitlistPage
401Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key).ProblemDetails
404operator access is not configuredProblemDetails
Request
curl "$VMYARD_API_URL/v1/operator/waitlist" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN"
Response 200
{
  "items": [
    {
      "access_grant_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
      "company": "string",
      "created_at": "string",
      "decided_at": "string",
      "decided_by": "string",
      "decision_reason": "string",
      "email": "ada@example.com",
      "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
      "name": "dev",
      "raw_answers": {},
      "status": "pending",
      "updated_at": "string",
      "use_case": "string"
    }
  ]
}

Approve a waitlist entry (operators)

POST /v1/operator/waitlist/{entry_id}/approve

Approve an entry: its email gets an access grant (with the initial credit), and the "you're in" email is sent. Approving an approved entry changes nothing; a rejected or revoked entry may be approved again.

  • Authentication: none on this route.
  • Who: Service operators (operator token).

Parameters

NameInTypeRequiredDescription
entry_idpathstring (uuid)Yes
X-VMYard-Operator-TokenheaderstringYesOperator token from the service configuration

Request body (application/json, ApproveWaitlistRequest)

FieldTypeRequiredDescription
operatorstringYesThe individual operator acting, 1-200 characters.
initial_credit_microsinteger | nullNoCredits from VMYard granted once to the person's own organization (now if they already signed in, else at their first sign-in). Defaults to the service's access.initial_credit_micros; 0 grants none.
notifyboolean | nullNoSend the "you're in" email (default true).
reasonstring | nullNoWhy, 1-500 characters; optional.

Responses

StatusDescriptionBody
200—WaitlistDecisionDto
401Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key).ProblemDetails
404operator access is not configured or the entry is unknownProblemDetails
422Invalid request (invalid_request); field_errors names the fields.ProblemDetails
Request
curl -X POST "$VMYARD_API_URL/v1/operator/waitlist/$ENTRY_ID/approve" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "operator": "string"
}'
Response 200
{
  "changed": false,
  "entry": {
    "access_grant_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "company": "string",
    "created_at": "string",
    "decided_at": "string",
    "decided_by": "string",
    "decision_reason": "string",
    "email": "ada@example.com",
    "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "name": "dev",
    "raw_answers": {},
    "status": "pending",
    "updated_at": "string",
    "use_case": "string"
  },
  "grant": {
    "created_at": "string",
    "credited_at": "string",
    "credited_organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "email": "ada@example.com",
    "granted_by": "string",
    "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "initial_credit_micros": 0,
    "provider": "github",
    "reason": "string",
    "revoke_reason": "string",
    "revoked_at": "string",
    "revoked_by": "string",
    "subject": "string"
  },
  "notification": "sent"
}

Reject a waitlist entry (operators)

POST /v1/operator/waitlist/{entry_id}/reject

Reject a pending entry. Rejecting a rejected entry changes nothing; an approved entry is revoked instead (409 waitlist_decision_conflict).

  • Authentication: none on this route.
  • Who: Service operators (operator token).

Parameters

NameInTypeRequiredDescription
entry_idpathstring (uuid)Yes
X-VMYard-Operator-TokenheaderstringYesOperator token from the service configuration

Request body (application/json, WaitlistDecisionRequest)

FieldTypeRequiredDescription
operatorstringYesThe individual operator acting, 1-200 characters.
reasonstringYesWhy, 1-500 characters.

Responses

StatusDescriptionBody
200—WaitlistDecisionDto
401Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key).ProblemDetails
404operator access is not configured or the entry is unknownProblemDetails
409waitlist_decision_conflictProblemDetails
422Invalid request (invalid_request); field_errors names the fields.ProblemDetails
Request
curl -X POST "$VMYARD_API_URL/v1/operator/waitlist/$ENTRY_ID/reject" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "operator": "string",
  "reason": "string"
}'
Response 200
{
  "changed": false,
  "entry": {
    "access_grant_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "company": "string",
    "created_at": "string",
    "decided_at": "string",
    "decided_by": "string",
    "decision_reason": "string",
    "email": "ada@example.com",
    "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "name": "dev",
    "raw_answers": {},
    "status": "pending",
    "updated_at": "string",
    "use_case": "string"
  },
  "grant": {
    "created_at": "string",
    "credited_at": "string",
    "credited_organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "email": "ada@example.com",
    "granted_by": "string",
    "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "initial_credit_micros": 0,
    "provider": "github",
    "reason": "string",
    "revoke_reason": "string",
    "revoked_at": "string",
    "revoked_by": "string",
    "subject": "string"
  },
  "notification": "sent"
}

Revoke a waitlist entry (operators)

POST /v1/operator/waitlist/{entry_id}/revoke

Revoke an approved entry: its grant is revoked, so the person (and the organizations only they approve) can no longer create organizations, machines, or API keys. Running machines keep running; suspend the organization to stop them.

  • Authentication: none on this route.
  • Who: Service operators (operator token).

Parameters

NameInTypeRequiredDescription
entry_idpathstring (uuid)Yes
X-VMYard-Operator-TokenheaderstringYesOperator token from the service configuration

Request body (application/json, WaitlistDecisionRequest)

FieldTypeRequiredDescription
operatorstringYesThe individual operator acting, 1-200 characters.
reasonstringYesWhy, 1-500 characters.

Responses

StatusDescriptionBody
200—WaitlistDecisionDto
401Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key).ProblemDetails
404operator access is not configured or the entry is unknownProblemDetails
409waitlist_decision_conflict: the entry is not approvedProblemDetails
422Invalid request (invalid_request); field_errors names the fields.ProblemDetails
Request
curl -X POST "$VMYARD_API_URL/v1/operator/waitlist/$ENTRY_ID/revoke" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "operator": "string",
  "reason": "string"
}'
Response 200
{
  "changed": false,
  "entry": {
    "access_grant_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "company": "string",
    "created_at": "string",
    "decided_at": "string",
    "decided_by": "string",
    "decision_reason": "string",
    "email": "ada@example.com",
    "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "name": "dev",
    "raw_answers": {},
    "status": "pending",
    "updated_at": "string",
    "use_case": "string"
  },
  "grant": {
    "created_at": "string",
    "credited_at": "string",
    "credited_organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "email": "ada@example.com",
    "granted_by": "string",
    "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "initial_credit_micros": 0,
    "provider": "github",
    "reason": "string",
    "revoke_reason": "string",
    "revoked_at": "string",
    "revoked_by": "string",
    "subject": "string"
  },
  "notification": "sent"
}

List access grants (operators)

GET /v1/operator/access-grants

Access grants, newest first.

  • Authentication: none on this route.
  • Who: Service operators (operator token).

Parameters

NameInTypeRequiredDescription
include_revokedquerybooleanNoInclude revoked grants (default false).
limitqueryintegerNo1-500, default 100; newest first.
X-VMYard-Operator-TokenheaderstringYesOperator token from the service configuration

Responses

StatusDescriptionBody
200—AccessGrantPage
401Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key).ProblemDetails
404operator access is not configuredProblemDetails
Request
curl "$VMYARD_API_URL/v1/operator/access-grants" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN"
Response 200
{
  "items": [
    {
      "created_at": "string",
      "credited_at": "string",
      "credited_organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
      "email": "ada@example.com",
      "granted_by": "string",
      "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
      "initial_credit_micros": 0,
      "provider": "github",
      "reason": "string",
      "revoke_reason": "string",
      "revoked_at": "string",
      "revoked_by": "string",
      "subject": "string"
    }
  ]
}

Grant access (operators)

POST /v1/operator/access-grants

Grant access without a waitlist entry: a verified login email, or one sign-in identity (provider and subject, such as an ERP.AI account's OIDC subject). No email is sent.

  • Authentication: none on this route.
  • Who: Service operators (operator token).

Parameters

NameInTypeRequiredDescription
X-VMYard-Operator-TokenheaderstringYesOperator token from the service configuration

Request body (application/json, CreateAccessGrantRequest)

FieldTypeRequiredDescription
operatorstringYesThe individual operator acting, 1-200 characters.
emailstring | nullNoGrant a verified login email; or name provider and subject.
initial_credit_microsinteger | nullNoAs on approval; defaults to the service's initial credit, 0 for none.
providerstring | nullNoA configured sign-in provider such as erpai.
reasonstring | nullNo
subjectstring | nullNoThe provider's subject (sub) for the account, 1-255 characters.

Responses

StatusDescriptionBody
200An active grant already named this personAccessGrantCreatedDto
201—AccessGrantCreatedDto
401Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key).ProblemDetails
404operator access is not configuredProblemDetails
422Invalid request (invalid_request); field_errors names the fields.ProblemDetails
Request
curl -X POST "$VMYARD_API_URL/v1/operator/access-grants" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "operator": "string"
}'
Response 200
{
  "created": false,
  "grant": {
    "created_at": "string",
    "credited_at": "string",
    "credited_organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "email": "ada@example.com",
    "granted_by": "string",
    "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
    "initial_credit_micros": 0,
    "provider": "github",
    "reason": "string",
    "revoke_reason": "string",
    "revoked_at": "string",
    "revoked_by": "string",
    "subject": "string"
  }
}

Revoke an access grant (operators)

POST /v1/operator/access-grants/{grant_id}/revoke

Revoke a grant; a waitlist entry approved through it becomes revoked. Revoking a revoked grant changes nothing.

  • Authentication: none on this route.
  • Who: Service operators (operator token).

Parameters

NameInTypeRequiredDescription
grant_idpathstring (uuid)Yes
X-VMYard-Operator-TokenheaderstringYesOperator token from the service configuration

Request body (application/json, WaitlistDecisionRequest)

FieldTypeRequiredDescription
operatorstringYesThe individual operator acting, 1-200 characters.
reasonstringYesWhy, 1-500 characters.

Responses

StatusDescriptionBody
200—AccessGrantDto
401Not signed in, or the API key is malformed, expired, or revoked (unauthenticated, invalid_api_key).ProblemDetails
404operator access is not configured or the grant is unknownProblemDetails
422Invalid request (invalid_request); field_errors names the fields.ProblemDetails
Request
curl -X POST "$VMYARD_API_URL/v1/operator/access-grants/$GRANT_ID/revoke" \
  -H "X-VMYard-Operator-Token: $X_VMYARD_OPERATOR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "operator": "string",
  "reason": "string"
}'
Response 200
{
  "created_at": "string",
  "credited_at": "string",
  "credited_organization_id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
  "email": "ada@example.com",
  "granted_by": "string",
  "id": "6f1c2d3e-4b5a-4c7d-8e9f-0a1b2c3d4e5f",
  "initial_credit_micros": 0,
  "provider": "github",
  "reason": "string",
  "revoke_reason": "string",
  "revoked_at": "string",
  "revoked_by": "string",
  "subject": "string"
}