Create/reuse extension and return credentials
Read, change and remove forwarding; retrieve exclusive SIP credentials.
PATCH /api/v1/dids/1234/forwardingPermission: forwarding:write + sip:create + sip:credentials:read
Required scopes
forwarding:write + sip:create + sip:credentials:read
Omit sipAccountId entirely. All three scopes are mandatory. Creates or reuses the number’s own exclusive extension, configures SIP forwarding and returns sipCredentials. Existing eligible extension passwords are not rotated. The generated password cannot be supplied by the caller. Store credentials securely; never attach real responses to support tickets or collection examples. A partial failure may leave an extension created; retry can reuse it. Errors include sip_persistence_failed (503) and sip_unavailable (502). forwarding remains null without forwarding:read, even when credentials are returned.
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.
Request body
{
"type": "sip"
}Success response (200)
{
"didId": 1234,
"number": "5511999999999",
"forwarding": null,
"sipCredentials": {
"username": "example-extension",
"password": "EXAMPLE_NOT_A_SECRET",
"server": "ramal.novodid.com",
"port": 5060,
"transport": "udp",
"uri": "sip:[email protected]"
}
}Error example
{
"error": {
"code": "insufficient_scope",
"message": "Token sem permissão para esta operação."
}
}curl
curl -X PATCH \
-H "Authorization: Bearer $NOVODID_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"type":"sip"}' \
"https://novodid.com/api/v1/dids/1234/forwarding"Node
const response = await fetch("https://novodid.com/api/v1/dids/1234/forwarding", {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.NOVODID_API_TOKEN}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"type": "sip"
})
});
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.patch(
"https://novodid.com/api/v1/dids/1234/forwarding",
headers={"Authorization": f"Bearer {os.environ['NOVODID_API_TOKEN']}"},
json={
"type": "sip"
},
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("PATCH", "https://novodid.com/api/v1/dids/1234/forwarding", strings.NewReader(`{"type":"sip"}`))
if err != nil {
panic(err)
}
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
.patch("https://novodid.com/api/v1/dids/1234/forwarding")
.bearer_auth(env::var("NOVODID_API_TOKEN")?)
.json(&json!({
"type": "sip"
}))
.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/dids/1234/forwarding");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("NOVODID_API_TOKEN"),
"Content-Type: application/json"
],
CURLOPT_POSTFIELDS => '{"type":"sip"}',
]);
$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/dids/1234/forwarding")
request = Net::HTTP::Patch.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch("NOVODID_API_TOKEN")}"
request["Content-Type"] = "application/json"
request.body = %q({"type":"sip"})
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.codeC#
using System.Net.Http.Headers;
using System.Text;
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Patch, "https://novodid.com/api/v1/dids/1234/forwarding");
request.Headers.Authorization = new AuthenticationHeaderValue(
"Bearer",
Environment.GetEnvironmentVariable("NOVODID_API_TOKEN")
);
request.Content = new StringContent(
"""
{
"type": "sip"
}
""",
Encoding.UTF8,
"application/json"
);
using var response = await client.SendAsync(request);
var payload = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
Console.WriteLine(response.StatusCode);
