ResourcesAPI ReferenceDeveloper API Overview
API Reference

Developer API Overview

What the server-to-server v1 API is, base URL, quick start examples, and the async write model.

Developer API Overview

This document is for developers of workspaces subscribed to the DEVELOPER product. It describes the outward-facing, server-to-server API called with a workspace API token — a different API from the internal SPA endpoints that power the Dotva Vue front-end.

Source of truth: the OpenAPI 3.1 spec served by the API itself. Interactive docs (Swagger UI): https://dotva.io/api/v1/docs · raw spec: https://dotva.io/api/v1/openapi.yaml.


What this API is

  • Purpose: programmatically manage virtual cards and read orders / wallet / transactions.
  • Base URL: https://dotva.io/api/v1
  • Authentication: every request carries Authorization: Bearer <token>, where the token looks like dotva_sk_... and is created in the workspace's "Developer Settings" page.
  • Writes are asynchronous: any operation that moves money or changes card state returns 202 Accepted plus an Order. The outcome is pushed to you as an order.completed / order.failed webhook; polling stays available as a fallback.
  • Rate limiting + idempotency: every token and every IP has a per-minute ceiling; all write endpoints support X-Idempotency-Key for safe retries.

Prerequisites

  1. The workspace must subscribe to the DEVELOPER product (otherwise it cannot create API tokens).
  2. At least one token must be created in "Developer Settings" and granted the required abilities.
  3. If the token has an IP allowlist, the calling IP must be within it.

Quick start

# 1) Validate the token; see the bound workspace and granted abilities.
curl -s https://dotva.io/api/v1/ping \
  -H "Authorization: Bearer dotva_sk_xxx"

# Response
# {
#   "data": {
#     "workspace_slug": "acme",
#     "workspace_name": "Acme Inc.",
#     "abilities": ["cards.read", "cards.write", "wallet.read"]
#   }
# }
# 2) Issue a card (asynchronous; returns 202 + Order).
curl -s -X POST https://dotva.io/api/v1/cards \
  -H "Authorization: Bearer dotva_sk_xxx" \
  -H "Content-Type: application/json" \
  -H "X-Idempotency-Key: order-2026-0001" \
  -d '{
        "card_product_id": 1,
        "initial_topup_amount": "100.00",
        "cardholder_first_name": "Jane",
        "cardholder_last_name": "Doe"
      }'

# 3) Wait for the order.completed webhook — it carries the card_uuid.
#    (Fallback: poll the Order until status becomes terminal.)
curl -s https://dotva.io/api/v1/orders/<order_uuid> \
  -H "Authorization: Bearer dotva_sk_xxx"

System

GET /ping — health / token probe

  • Ability: none (any valid token)
  • Purpose: validate the token and return the bound workspace and granted abilities.

Success 200

{
  "data": {
    "workspace_slug": "acme",
    "workspace_name": "Acme Inc.",
    "abilities": ["cards.read", "wallet.read"]
  }
}

Errors: 401 api.unauthenticated


Async write model

Write endpoints return 202 Accepted plus an Order:

{
  "data": {
    "uuid": "8f1c...",
    "type": "issue_card",
    "status": "pending",
    "related_card_id": null,
    "held_amount": "106.00",
    "currency": "USD",
    "created_at": "2026-06-08T01:00:00+00:00"
  }
}

The outcome arrives as an order.completed / order.failed webhook — for issue orders, order.completed carries the card_uuid. As a fallback, GET /orders/{uuid} can always be polled until status reaches a terminal value (completed / failed).

See Orders & Wallet for the full Orders endpoint reference, including Order status and type enums. For the end-to-end flow (order matching, transaction stream, card close), see the Integration guide.