Quickstart

Send your first Corvo shipment in three API calls: upload a PDF, create a draft shipment to get live rates, and buy the quote you want.

Step 1: Upload a PDF

Upload the PDF you want Corvo to print and mail. The response returns a document_key that you use in shipment creation.

POST/api/v1/documents/upload

Upload a PDF document via multipart form data.

Shell
curl -X POST https://corvo.to/api/v1/documents/upload \
  -H "Authorization: Bearer $CORVO_API_KEY" \
  -F file=@lease-agreement.pdf
Response201Document uploaded
{
  "data": {
    "document_key": "documents/a3b8c1d2-e4f5-6789-abcd-ef0123456789/lease-agreement.pdf",
    "filename": "lease-agreement.pdf",
    "page_count": 8,
    "size_bytes": 245760
  }
}

Step 2: Create a draft shipment

Create a shipment with the uploaded document, addresses, and print options. Corvo always returns draft quotes first so you can choose the rate you want before buying.

POST/api/v1/shipments

Create a draft shipment and return live rate quotes.

Shell
curl -X POST https://corvo.to/api/v1/shipments \
  -H "Authorization: Bearer $CORVO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "document_key": "documents/a3b8c1d2-e4f5-6789-abcd-ef0123456789/lease-agreement.pdf",
    "shipment_name": "Lease Agreement",
    "to_address": {
      "name": "Jordan Reed",
      "street1": "123 Main St",
      "city": "Austin",
      "state": "TX",
      "zip": "78701"
    },
    "from_address": {
      "name": "Acme Property Management",
      "street1": "500 Congress Ave",
      "city": "Austin",
      "state": "TX",
      "zip": "78701"
    },
    "print_options": {
      "color": false,
      "duplex": true
    },
    "shipping_options": {
      "certified_mail": true,
      "return_receipt": true
    }
  }'
Response201Draft shipment with rate quotes
{
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "status": "draft",
    "shipment_name": "Lease Agreement",
    "page_count": 8,
    "shipping_options": {
      "delivery_confirmation": null,
      "certified_mail": true,
      "return_receipt": true
    },
    "rates": [
      {
        "quote_id": "9f0a1b2c-3d4e-4f5a-8b9c-0d1e2f3a4b5c",
        "carrier": "USPS",
        "service": "Priority",
        "postage_cents": 855,
        "handling_fee_cents": 300,
        "printing_fee_cents": 200,
        "color_surcharge_cents": 0,
        "total_cents": 1355,
        "delivery_days": 2,
        "delivery_date": "2026-03-11T00:00:00.000Z",
        "delivery_date_guaranteed": false
      }
    ],
    "quotes_expire_at": "2026-03-09T15:30:00.000Z"
  }
}

Step 3: Buy the selected quote

Choose one of the returned quote IDs and pass it to the buy endpoint. Corvo charges the organization card on file and moves the shipment into fulfillment.

POST/api/v1/shipments/{id}/buy

Buy a draft shipment using a selected quote.

Shell
curl -X POST https://corvo.to/api/v1/shipments/f47ac10b-58cc-4372-a567-0e02b2c3d479/buy \
  -H "Authorization: Bearer $CORVO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "quote_id": "9f0a1b2c-3d4e-4f5a-8b9c-0d1e2f3a4b5c"
  }'
Response200Shipment purchased
{
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "status": "queued",
    "carrier": "USPS",
    "service": "Priority",
    "total_charged_cents": 1355,
    "tracking_number": "9405511899223033005084",
    "tracking_url": "https://tools.usps.com/go/TrackConfirmAction?tLabels=9405511899223033005084"
  }
}

Step 4: Poll shipment status

Use shipment detail responses for fulfillment status, tracking, proof artifacts, mailing-record state, and event history. When you poll with an API key, Corvo limits this endpoint to one request per shipment every five minutes and may return a cached response inside that window.

Shell
curl https://corvo.to/api/v1/shipments/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
  -H "Authorization: Bearer $CORVO_API_KEY"
Response200Shipment detail
{
  "data": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "status": "queued",
    "carrier": "USPS",
    "service": "Priority",
    "shipping_options": {
      "delivery_confirmation": null,
      "certified_mail": true,
      "return_receipt": false
    },
    "tracking_number": "9405511899223033005084",
    "tracking_url": "https://tools.usps.com/go/TrackConfirmAction?tLabels=9405511899223033005084",
    "total_charged_cents": 1355,
    "created_at": "2026-03-09T15:00:00.000Z",
    "shipped_at": null,
    "mailing_records": {
      "acceptance": {
        "requested": true,
        "manifested": false,
        "accepted_at": null,
        "source": null,
        "scan_form_available": false
      },
      "delivery": {
        "latest_status": "pre_transit",
        "latest_status_detail": "label_created",
        "delivered_at": null,
        "attempted_at": null,
        "signed_by": null,
        "returned_to_sender_at": null
      },
      "return_receipt": {
        "requested": false,
        "status": "not_requested",
        "artifact_id": null,
        "available_at": null
      },
      "retention": {
        "evidence_expires_at": "2036-03-09T15:00:00.000Z",
        "document_expires_at": "2028-03-08T15:00:00.000Z",
        "original_document_retained": true
      }
    },
    "artifacts": [
      {
        "id": "mailing-record-summary",
        "kind": "mailing_record_summary_pdf",
        "provenance": "corvo_generated",
        "download_url": "/api/v1/shipments/f47ac10b-58cc-4372-a567-0e02b2c3d479/proof"
      }
    ],
    "events": [
      {
        "id": "evt_01",
        "status": "payment_pending",
        "from_status": "draft",
        "message": "Payment initiated for draft shipment",
        "actor": "user:4c1b8b16-2e4f-4de0-9ad5-e0ec0f16dbe8",
        "metadata": null,
        "created_at": "2026-03-09T15:00:04.000Z"
      }
    ]
  }
}

End-to-end TypeScript example

TypeScript
import { readFileSync } from "node:fs";

const API_KEY = process.env.CORVO_API_KEY!;
const BASE_URL = "https://corvo.to/api/v1";

async function main() {
  const file = new Blob([readFileSync("lease-agreement.pdf")], {
    type: "application/pdf",
  });

  const uploadForm = new FormData();
  uploadForm.append("file", file, "lease-agreement.pdf");

  const uploadResponse = await fetch(`${BASE_URL}/documents/upload`, {
    method: "POST",
    headers: { Authorization: `Bearer ${API_KEY}` },
    body: uploadForm,
  });
  const uploadJson = await uploadResponse.json();
  const documentKey = uploadJson.data.document_key;

  const draftResponse = await fetch(`${BASE_URL}/shipments`, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      document_key: documentKey,
      shipment_name: "Lease Agreement",
      to_address: {
        name: "Jordan Reed",
        street1: "123 Main St",
        city: "Austin",
        state: "TX",
        zip: "78701",
      },
      print_options: { color: false, duplex: true },
      shipping_options: { certified_mail: true, return_receipt: true },
    }),
  });
  const draftJson = await draftResponse.json();
  const quote = draftJson.data.rates[0];

  const buyResponse = await fetch(
    `${BASE_URL}/shipments/${draftJson.data.id}/buy`,
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${API_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ quote_id: quote.quote_id }),
    },
  );
  const buyJson = await buyResponse.json();

  console.log({
    shipmentId: buyJson.data.id,
    status: buyJson.data.status,
    trackingNumber: buyJson.data.tracking_number,
  });
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});