Skip to Content
NovoDIDNovoDIDdocumentation
Public APIOperation referenceBuy numbers

Create a DID checkout

Catalog, quotes, checkout and order tracking.

POST /api/v1/orders

Permission: orders:create

Scope: orders:create. Set Idempotency-Key before sending. Use exactly one didId and quantity=1; select the cycle/payment method quoted. Include required SMS booleans only after the customer accepts. Optional couponCode has the same rules as quote. Returns HTTP 201 with order. For Pix, scan qrCodeDataUrl or copy copyPaste; for card, open checkoutUrl. No saved card is charged by this request. Read the order after a timeout and preserve the key. 400: invalid body/missing acknowledgement/key; 403: scope or number-restricted token; 409: pending reservation for the same DID or key conflict. A pending reservation applies only to the selected DID and lasts at most 15 minutes from order creation. Other DIDs may be purchased during this period, subject to account limits. A pending reservation expires within 15 minutes, including failed creation or orders requiring review. This does not confirm immediate external cancellation or a refund. Do not pay expired instructions; a payment confirmed after expiry is reviewed without replacing another reservation or ownership. Already confirmed payments and active numbers remain protected. For review_required, contact support with the order ID. 503: payment outcome unavailable. Do not automatically retry with a new key.

During temporary mobile-number offers, available billing cycles and SMS inclusion may vary. Always request a quote: did.smsEnabled states whether SMS is included, and acknowledgements.mobileMonthlySms.required indicates whether mobileMonthlySmsAcknowledged=true is required after customer consent. Despite their names, these fields apply to any mobile cycle without SMS. A quote does not guarantee an offer; conditions are checked again when payment is created. Payments issued during an offer keep their conditions until the payment itself expires. After an offer ends, new purchases follow current conditions, while completed subscriptions keep their cycle and SMS entitlement on renewals for as long as the subscription remains in effect. This is not a price guarantee. Account eligibility, verification, limits, available stock and one number per order remain required.

409 checkout_initializing means another purchase for this account is still being prepared. Wait briefly and retry with the same Idempotency-Key and request body. This wait applies only to initial creation, not to the 15-minute payment period.

409 order_expired means the checkout creation response arrived after the order deadline. No expired QR code or checkout link is returned. Check details.orderId before starting another purchase, and do not pay old instructions.

While an account is under security review, reads and operations are blocked with HTTP 403 and code account_security_review, including previously issued tokens. Do not bypass the restriction or retry automatically. Access resumes after administrative release; other limits and restrictions still apply. Pending webhooks and events during the restriction are suppressed without automatic replay. Billing, due dates and expiration follow existing rules. Follow the review at https://novodid.com/seguranca/atendimento. Only the linked security ticket can be read and answered, including attachments, on the authenticated website. Other tickets and the public API remain blocked. The customer must wait for the first staff message and may send only one reply to each new staff message, including requested attachments.

HTTP 409 did_number_unavailable: the selected telephone could not be confirmed before creating payment. Check the order in error.details.orderId and refresh the catalog before retrying; do not create another payment without checking the previous order.

Request body

{
  "didId": 1234,
  "quantity": 1,
  "cycle": "monthly",
  "paymentMethod": "pix",
  "fixedDidSmsAcknowledged": true
}

Success response (201)

{
  "order": {
    "id": "11111111-1111-4111-8111-111111111111",
    "didId": 1234,
    "quantity": 1,
    "status": "awaiting_payment",
    "paymentMethod": "pix",
    "currency": "BRL",
    "amount": 1499,
    "createdAt": "2026-09-23T15:00:00.000Z",
    "expiresAt": "2026-09-23T15:15:00.000Z",
    "checkoutUrl": null,
    "pix": {
      "copyPaste": "PIX_COPY_AND_PASTE_EXAMPLE",
      "qrCodeDataUrl": "data:image/png;base64,EXAMPLE"
    }
  }
}

Error example

{
  "error": {
    "code": "checkout_in_progress",
    "message": "Este número já tem um pedido pendente. A reserva dura até 15 minutos. Você pode escolher outro número."
  }
}

curl

curl -X POST \
  -H "Idempotency-Key: order_example_20260923_01" \
  -H "Authorization: Bearer $NOVODID_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"didId":1234,"quantity":1,"cycle":"monthly","paymentMethod":"pix","fixedDidSmsAcknowledged":true}' \
  "https://novodid.com/api/v1/orders"

Node

const response = await fetch("https://novodid.com/api/v1/orders", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.NOVODID_API_TOKEN}`,
    "Idempotency-Key": "order_example_20260923_01",
    "Content-Type": "application/json"
  },
  body: JSON.stringify({
  "didId": 1234,
  "quantity": 1,
  "cycle": "monthly",
  "paymentMethod": "pix",
  "fixedDidSmsAcknowledged": true
})
});
const payload = await response.json();

if (!response.ok) {
  throw new Error(payload.error?.message || "Erro na API NovoDID");
}

console.log({ status: response.status });

Python

import os
import requests

response = requests.post(
    "https://novodid.com/api/v1/orders",
    headers={"Idempotency-Key": "order_example_20260923_01", "Authorization": f"Bearer {os.environ['NOVODID_API_TOKEN']}"},
    json={
  "didId": 1234,
  "quantity": 1,
  "cycle": "monthly",
  "paymentMethod": "pix",
  "fixedDidSmsAcknowledged": True
},
    timeout=30,
)

payload = response.json()
response.raise_for_status()
print({"status": response.status_code})

Go

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "strings"
)

func main() {
    req, err := http.NewRequest("POST", "https://novodid.com/api/v1/orders", strings.NewReader(`{"didId":1234,"quantity":1,"cycle":"monthly","paymentMethod":"pix","fixedDidSmsAcknowledged":true}`))
    if err != nil {
        panic(err)
    }

    req.Header.Set("Idempotency-Key", "order_example_20260923_01")
    req.Header.Set("Authorization", "Bearer "+os.Getenv("NOVODID_API_TOKEN"))
    req.Header.Set("Content-Type", "application/json")

    res, err := http.DefaultClient.Do(req)
    if err != nil {
        panic(err)
    }
    defer res.Body.Close()

    _, _ = io.Copy(io.Discard, res.Body)
    if res.StatusCode >= 300 {
        panic(fmt.Sprintf("NovoDID API HTTP %d", res.StatusCode))
    }

    fmt.Println(res.StatusCode)
}

Rust

use serde_json::json;
use reqwest::blocking::Client;
use std::env;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new();
    let response = client
        .post("https://novodid.com/api/v1/orders")
        .header("Idempotency-Key", "order_example_20260923_01")
        .bearer_auth(env::var("NOVODID_API_TOKEN")?)
        .json(&json!({
  "didId": 1234,
  "quantity": 1,
  "cycle": "monthly",
  "paymentMethod": "pix",
  "fixedDidSmsAcknowledged": true
}))
        .send()?;

    let status = response.status();
    let _payload = response.text()?;
    if !status.is_success() {
        return Err(format!("NovoDID API HTTP {}", status).into());
    }

    println!("HTTP {}", status);
    Ok(())
}

PHP

<?php

$ch = curl_init("https://novodid.com/api/v1/orders");

curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_HTTPHEADER => [
    "Idempotency-Key: order_example_20260923_01",
    "Authorization: Bearer " . getenv("NOVODID_API_TOKEN"),
    "Content-Type: application/json"
  ],
  CURLOPT_POSTFIELDS => '{"didId":1234,"quantity":1,"cycle":"monthly","paymentMethod":"pix","fixedDidSmsAcknowledged":true}',
]);

$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($response === false || $status >= 300) {
  throw new RuntimeException("NovoDID API HTTP " . $status);
}

echo $status . PHP_EOL;

Ruby

require "net/http"

uri = URI("https://novodid.com/api/v1/orders")
request = Net::HTTP::Post.new(uri)
request["Idempotency-Key"] = "order_example_20260923_01"
request["Authorization"] = "Bearer #{ENV.fetch("NOVODID_API_TOKEN")}"
request["Content-Type"] = "application/json"
request.body = %q({"didId":1234,"quantity":1,"cycle":"monthly","paymentMethod":"pix","fixedDidSmsAcknowledged":true})

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") do |http|
  http.request(request)
end

raise "NovoDID API HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess)

puts response.code

C#

using System.Net.Http.Headers;
using System.Text;

using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, "https://novodid.com/api/v1/orders");

request.Headers.Add("Idempotency-Key", "order_example_20260923_01");
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Bearer",
    Environment.GetEnvironmentVariable("NOVODID_API_TOKEN")
);

request.Content = new StringContent(
    """
{
  "didId": 1234,
  "quantity": 1,
  "cycle": "monthly",
  "paymentMethod": "pix",
  "fixedDidSmsAcknowledged": true
}
""",
    Encoding.UTF8,
    "application/json"
);

using var response = await client.SendAsync(request);
var payload = await response.Content.ReadAsStringAsync();

response.EnsureSuccessStatusCode();
Console.WriteLine(response.StatusCode);

On this page