> Fetch clean Markdown by appending `.md` to any page URL under https://signalwire.com/docs or requesting it with the HTTP header `Accept: text/markdown`. The root index at https://signalwire.com/docs/llms.txt lists the available documentation indexes. # Create API token POST https://%7BYour_Space_Name%7D.signalwire.com/api/project/tokens Content-Type: application/json Creates a project API token for server-side authentication to SignalWire REST APIs, with only the permission categories supplied in the request. Use it when a backend service needs durable project credentials; client applications should receive a service-specific token such as a [Chat Token](/docs/apis/rest/chat-tokens/create-chat-token), [PubSub Token](/docs/apis/rest/pubsub/create-token), [Room Token](/docs/apis/rest/video/room-tokens/create-room-token), or [Subscriber Token](/docs/apis/rest/subscribers/tokens/create-subscriber-token) instead. The token remains usable until you delete it or remove required permissions. The Compatibility API exposes the same project tokens through its account-scoped route. Use [Generate a new API Token](/docs/compatibility-api/rest/tokens/create-token) for that request format. The response is the only place the token secret is returned. Store it securely; no later request, including [Update API token](/docs/apis/rest/project-tokens/update-token), can read it back. With a project API token, the new token belongs to the authenticated project, or to one of its subprojects when `subproject_id` is given; `project_id` is ignored. With a [Personal access token](/docs/apis/authorization#personal-access-tokens), `project_id` is required and names the project the token is created for, which is how a root project created with [Create a project](/docs/apis/rest/projects/create-subproject) gets its first credential. #### Permissions With a project API token, the token must have the following scope(s) enabled to make a successful request: _Management_. With a [Personal access token](/docs/apis/authorization#personal-access-tokens) there are no scopes. The token holder must be an owner or admin of the space, and the request reaches only the projects the holder is enabled for, plus their subprojects. [Learn more about API scopes](/docs/platform/your-signalwire-api-space). #### Token Permissions You must set the functions allowed by this API Token by selecting which types of requests this API Token is allowed to make. Valid options are: calling, chat, datasphere, fax, management, messaging, numbers, pubsub, storage, tasking, and video Reference: https://signalwire.com/docs/apis/rest/project-tokens/create-token ## Authentication - `Authorization` header (basic auth, required) — SignalWire Basic Authentication using Project ID and API Token. The client sends HTTP requests with the Authorization header containing the word Basic followed by a space and a base64-encoded string of project_id:token. The project ID will be used as the username and the API token as the password. Example: ``` Authorization: Basic base64(project_id:token) ``` - `Authorization` header (basic auth, required) — Personal access token authentication for space-wide administration. Send HTTP Basic auth with an empty username and the Personal access token as the password. A Personal access token carries your own authority rather than a project's: it is created from your user menu in the Dashboard, is prefixed `pat_`, and has no scopes. The holder must be an owner or admin of the space named by the subdomain, and the token acts only on that space. Example: ``` Authorization: Basic base64(:pat_...) ``` ## Request ### Body (application/json) This endpoint expects a Project.CreateTokenRequest. - `name` (string, required) — The name representing the API token. - `permissions` (list of enum, required) — The permissions you would like to enable for this token. Valid permissions are calling, chat, datasphere, fax, management, messaging, numbers, pubsub, storage, tasking, and video - Allowed values: `calling`, `chat`, `datasphere`, `fax`, `management`, `messaging`, `numbers`, `pubsub`, `storage`, `tasking`, `video` - `project_id` (string, optional) — Personal access token only. The project to create the token for. Required with a Personal access token and must name a project the token holder can reach (`invalid_project_id`). Ignored with a project API token, which creates the token on its own project. - `subproject_id` (string, optional) — The unique identifier of the subproject you would like to create a token for. The subproject passed must be a child of the project used to authenticate the request, or of `project_id` when authenticating with a Personal access token. ## Response ### 200 The request has succeeded. - `id` (string, required) — The ID of the API Token. - `name` (string, required) — The name of the API Token. - `permissions` (list of enum, required) — The permissions enabled for this token. - Allowed values: `calling`, `chat`, `datasphere`, `fax`, `management`, `messaging`, `numbers`, `pubsub`, `storage`, `tasking`, `video` - `token` (string, required) — The API token that can be used along with the project ID for basic authentication. It is returned only in this response and cannot be retrieved again; store it securely. ## Errors ### 401 Unauthorized Error Access is unauthorized. - `error` (enum, required) - Allowed values: `Unauthorized` ### 422 Unprocessable Entity Error The request contains invalid parameters. See errors for details. - `errors` (list of Types.StatusCodes.RestApiErrorItem, required) — List of validation errors. ### 500 Internal Server Error An internal server error occurred. - `error` (enum, required) - Allowed values: `Internal Server Error` ## Types ### Types.StatusCodes.RestApiErrorItem Details about a specific error. - `type` (string, required) — The category of error. - `code` (string, required) — A specific error code. - `message` (string, required) — A description of what caused the error. - `url` (string, required) — A link to documentation about this error. - `attribute` (string, optional, nullable) — The request parameter that caused the error, if applicable. ## Examples **Request** ```json { "name": "John Doe's Token", "permissions": [ "calling", "fax", "messaging" ] } ``` **Response** ```json { "id": "ea14556a-984f-11ee-b9d1-0242ac120002", "name": "John Doe's Token", "permissions": [ "calling", "fax", "messaging" ], "token": "swapi_0123456789ab0123456789ab0123456789ab" } ``` **SDK Code** ```python import requests url = "https://{your_space_name}.signalwire.com/api/project/tokens" payload = { "name": "John Doe's Token", "permissions": ["calling", "fax", "messaging"] } headers = { "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers, auth=("", "")) print(response.json()) ``` ```javascript const url = 'https://{your_space_name}.signalwire.com/api/project/tokens'; const credentials = btoa(":"); const options = { method: 'POST', headers: { Authorization: `Basic ${credentials}`, 'Content-Type': 'application/json' }, body: '{"name":"John Doe\'s Token","permissions":["calling","fax","messaging"]}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://{your_space_name}.signalwire.com/api/project/tokens" payload := strings.NewReader("{\n \"name\": \"John Doe's Token\",\n \"permissions\": [\n \"calling\",\n \"fax\",\n \"messaging\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.SetBasicAuth("", "") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby require 'uri' require 'net/http' url = URI("https://{your_space_name}.signalwire.com/api/project/tokens") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request.basic_auth("", "") request["Content-Type"] = 'application/json' request.body = "{\n \"name\": \"John Doe's Token\",\n \"permissions\": [\n \"calling\",\n \"fax\",\n \"messaging\"\n ]\n}" response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://{your_space_name}.signalwire.com/api/project/tokens") .basicAuth("", "") .header("Content-Type", "application/json") .body("{\n \"name\": \"John Doe's Token\",\n \"permissions\": [\n \"calling\",\n \"fax\",\n \"messaging\"\n ]\n}") .asString(); ``` ```php request('POST', 'https://{your_space_name}.signalwire.com/api/project/tokens', [ 'body' => '{ "name": "John Doe\'s Token", "permissions": [ "calling", "fax", "messaging" ] }', 'headers' => [ 'Content-Type' => 'application/json', ], 'auth' => ['', ''], ]); echo $response->getBody(); ``` ```csharp using RestSharp; using RestSharp.Authenticators; var client = new RestClient("https://{your_space_name}.signalwire.com/api/project/tokens"); client.Authenticator = new HttpBasicAuthenticator("", ""); var request = new RestRequest(Method.POST); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"name\": \"John Doe's Token\",\n \"permissions\": [\n \"calling\",\n \"fax\",\n \"messaging\"\n ]\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let credentials = Data(":".utf8).base64EncodedString() let headers = [ "Authorization": "Basic \(credentials)", "Content-Type": "application/json" ] let parameters = [ "name": "John Doe's Token", "permissions": ["calling", "fax", "messaging"] ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://{your_space_name}.signalwire.com/api/project/tokens")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ```