curl --request POST \
--url https://api.emissa.com.ar/v1/arca/credentials \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"taxpayerId": "cmfa1b2c30000",
"environment": "HOMOLOGACION",
"certificate": "-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----",
"privateKey": "-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----"
}
'import requests
url = "https://api.emissa.com.ar/v1/arca/credentials"
payload = {
"taxpayerId": "cmfa1b2c30000",
"environment": "HOMOLOGACION",
"certificate": "-----BEGIN CERTIFICATE-----
MIIB...
-----END CERTIFICATE-----",
"privateKey": "-----BEGIN PRIVATE KEY-----
MIIE...
-----END PRIVATE KEY-----"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
taxpayerId: 'cmfa1b2c30000',
environment: 'HOMOLOGACION',
certificate: '-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----',
privateKey: '-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----'
})
};
fetch('https://api.emissa.com.ar/v1/arca/credentials', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.emissa.com.ar/v1/arca/credentials",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'taxpayerId' => 'cmfa1b2c30000',
'environment' => 'HOMOLOGACION',
'certificate' => '-----BEGIN CERTIFICATE-----
MIIB...
-----END CERTIFICATE-----',
'privateKey' => '-----BEGIN PRIVATE KEY-----
MIIE...
-----END PRIVATE KEY-----'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.emissa.com.ar/v1/arca/credentials"
payload := strings.NewReader("{\n \"taxpayerId\": \"cmfa1b2c30000\",\n \"environment\": \"HOMOLOGACION\",\n \"certificate\": \"-----BEGIN CERTIFICATE-----\\nMIIB...\\n-----END CERTIFICATE-----\",\n \"privateKey\": \"-----BEGIN PRIVATE KEY-----\\nMIIE...\\n-----END PRIVATE KEY-----\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.emissa.com.ar/v1/arca/credentials")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"taxpayerId\": \"cmfa1b2c30000\",\n \"environment\": \"HOMOLOGACION\",\n \"certificate\": \"-----BEGIN CERTIFICATE-----\\nMIIB...\\n-----END CERTIFICATE-----\",\n \"privateKey\": \"-----BEGIN PRIVATE KEY-----\\nMIIE...\\n-----END PRIVATE KEY-----\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.emissa.com.ar/v1/arca/credentials")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"taxpayerId\": \"cmfa1b2c30000\",\n \"environment\": \"HOMOLOGACION\",\n \"certificate\": \"-----BEGIN CERTIFICATE-----\\nMIIB...\\n-----END CERTIFICATE-----\",\n \"privateKey\": \"-----BEGIN PRIVATE KEY-----\\nMIIE...\\n-----END PRIVATE KEY-----\"\n}"
response = http.request(request)
puts response.read_body{
"id": "cmt42x6k6000furi4veejuoyl",
"taxpayerId": "cmt42x6jb000curi4sz1gyeij",
"environment": "HOMOLOGACION",
"status": "ACTIVE",
"cuit": "20000000001",
"certificateSubject": "CN=emissa-e2e, O=Emissa, C=AR, serialNumber=CUIT 20000000001",
"certificateIssuer": "CN=emissa-e2e, O=Emissa, C=AR, serialNumber=CUIT 20000000001",
"certificateSerial": "01",
"certificateFingerprint": "04790c756e83825857aa2a007df482eef4af7e5b4177b7d28d629f45a803e9ec",
"notBefore": "2026-08-21T07:51:04.000Z",
"notAfter": "2027-08-22T07:51:04.000Z",
"diasParaVencer": 364,
"createdAt": "2026-08-22T07:51:09.942Z",
"supersededAt": null,
"revokedAt": null
}{
"statusCode": 401,
"errorCode": "UNAUTHORIZED",
"message": "No autorizado",
"timestamp": "2026-07-26T18:30:00.000Z",
"path": "/v1/invoices/authorize",
"details": "<string>",
"retryable": false,
"retryAfterSeconds": 43200,
"requestId": "0f2c1a5e-1d9b-4c7a-9a55-7f1a2b3c4d5e"
}{
"statusCode": 401,
"errorCode": "UNAUTHORIZED",
"message": "No autorizado",
"timestamp": "2026-07-26T18:30:00.000Z",
"path": "/v1/invoices/authorize",
"details": "<string>",
"retryable": false,
"retryAfterSeconds": 43200,
"requestId": "0f2c1a5e-1d9b-4c7a-9a55-7f1a2b3c4d5e"
}{
"statusCode": 401,
"errorCode": "UNAUTHORIZED",
"message": "No autorizado",
"timestamp": "2026-07-26T18:30:00.000Z",
"path": "/v1/invoices/authorize",
"details": "<string>",
"retryable": false,
"retryAfterSeconds": 43200,
"requestId": "0f2c1a5e-1d9b-4c7a-9a55-7f1a2b3c4d5e"
}{
"statusCode": 401,
"errorCode": "UNAUTHORIZED",
"message": "No autorizado",
"timestamp": "2026-07-26T18:30:00.000Z",
"path": "/v1/invoices/authorize",
"details": "<string>",
"retryable": false,
"retryAfterSeconds": 43200,
"requestId": "0f2c1a5e-1d9b-4c7a-9a55-7f1a2b3c4d5e"
}{
"statusCode": 401,
"errorCode": "UNAUTHORIZED",
"message": "No autorizado",
"timestamp": "2026-07-26T18:30:00.000Z",
"path": "/v1/invoices/authorize",
"details": "<string>",
"retryable": false,
"retryAfterSeconds": 43200,
"requestId": "0f2c1a5e-1d9b-4c7a-9a55-7f1a2b3c4d5e"
}Cargar el certificado y la clave privada
El par que ARCA emitió para este CUIT y ambiente. Se guarda cifrado y no se devuelve nunca, ni completo ni parcial.
Se puede con API key desde la 5.35, con el scope credential:write. Si la key está restringida a ciertos contribuyentes, el de este pedido tiene que estar entre ellos.
Cargar un certificado propio es opcional: un contribuyente que autorizó a Emissa en ARCA emite firmando con el certificado de la plataforma. El propio le gana cuando está, y no depende de la delegación.
Scope de API key: credential:write. Una key sin ese scope recibe 403 API_KEY_INSUFFICIENT_SCOPE, aunque el rol de quien la creó lo permita: el permiso efectivo es la intersección de los dos.
curl --request POST \
--url https://api.emissa.com.ar/v1/arca/credentials \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"taxpayerId": "cmfa1b2c30000",
"environment": "HOMOLOGACION",
"certificate": "-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----",
"privateKey": "-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----"
}
'import requests
url = "https://api.emissa.com.ar/v1/arca/credentials"
payload = {
"taxpayerId": "cmfa1b2c30000",
"environment": "HOMOLOGACION",
"certificate": "-----BEGIN CERTIFICATE-----
MIIB...
-----END CERTIFICATE-----",
"privateKey": "-----BEGIN PRIVATE KEY-----
MIIE...
-----END PRIVATE KEY-----"
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
taxpayerId: 'cmfa1b2c30000',
environment: 'HOMOLOGACION',
certificate: '-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----',
privateKey: '-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----'
})
};
fetch('https://api.emissa.com.ar/v1/arca/credentials', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.emissa.com.ar/v1/arca/credentials",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'taxpayerId' => 'cmfa1b2c30000',
'environment' => 'HOMOLOGACION',
'certificate' => '-----BEGIN CERTIFICATE-----
MIIB...
-----END CERTIFICATE-----',
'privateKey' => '-----BEGIN PRIVATE KEY-----
MIIE...
-----END PRIVATE KEY-----'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.emissa.com.ar/v1/arca/credentials"
payload := strings.NewReader("{\n \"taxpayerId\": \"cmfa1b2c30000\",\n \"environment\": \"HOMOLOGACION\",\n \"certificate\": \"-----BEGIN CERTIFICATE-----\\nMIIB...\\n-----END CERTIFICATE-----\",\n \"privateKey\": \"-----BEGIN PRIVATE KEY-----\\nMIIE...\\n-----END PRIVATE KEY-----\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.emissa.com.ar/v1/arca/credentials")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"taxpayerId\": \"cmfa1b2c30000\",\n \"environment\": \"HOMOLOGACION\",\n \"certificate\": \"-----BEGIN CERTIFICATE-----\\nMIIB...\\n-----END CERTIFICATE-----\",\n \"privateKey\": \"-----BEGIN PRIVATE KEY-----\\nMIIE...\\n-----END PRIVATE KEY-----\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.emissa.com.ar/v1/arca/credentials")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"taxpayerId\": \"cmfa1b2c30000\",\n \"environment\": \"HOMOLOGACION\",\n \"certificate\": \"-----BEGIN CERTIFICATE-----\\nMIIB...\\n-----END CERTIFICATE-----\",\n \"privateKey\": \"-----BEGIN PRIVATE KEY-----\\nMIIE...\\n-----END PRIVATE KEY-----\"\n}"
response = http.request(request)
puts response.read_body{
"id": "cmt42x6k6000furi4veejuoyl",
"taxpayerId": "cmt42x6jb000curi4sz1gyeij",
"environment": "HOMOLOGACION",
"status": "ACTIVE",
"cuit": "20000000001",
"certificateSubject": "CN=emissa-e2e, O=Emissa, C=AR, serialNumber=CUIT 20000000001",
"certificateIssuer": "CN=emissa-e2e, O=Emissa, C=AR, serialNumber=CUIT 20000000001",
"certificateSerial": "01",
"certificateFingerprint": "04790c756e83825857aa2a007df482eef4af7e5b4177b7d28d629f45a803e9ec",
"notBefore": "2026-08-21T07:51:04.000Z",
"notAfter": "2027-08-22T07:51:04.000Z",
"diasParaVencer": 364,
"createdAt": "2026-08-22T07:51:09.942Z",
"supersededAt": null,
"revokedAt": null
}{
"statusCode": 401,
"errorCode": "UNAUTHORIZED",
"message": "No autorizado",
"timestamp": "2026-07-26T18:30:00.000Z",
"path": "/v1/invoices/authorize",
"details": "<string>",
"retryable": false,
"retryAfterSeconds": 43200,
"requestId": "0f2c1a5e-1d9b-4c7a-9a55-7f1a2b3c4d5e"
}{
"statusCode": 401,
"errorCode": "UNAUTHORIZED",
"message": "No autorizado",
"timestamp": "2026-07-26T18:30:00.000Z",
"path": "/v1/invoices/authorize",
"details": "<string>",
"retryable": false,
"retryAfterSeconds": 43200,
"requestId": "0f2c1a5e-1d9b-4c7a-9a55-7f1a2b3c4d5e"
}{
"statusCode": 401,
"errorCode": "UNAUTHORIZED",
"message": "No autorizado",
"timestamp": "2026-07-26T18:30:00.000Z",
"path": "/v1/invoices/authorize",
"details": "<string>",
"retryable": false,
"retryAfterSeconds": 43200,
"requestId": "0f2c1a5e-1d9b-4c7a-9a55-7f1a2b3c4d5e"
}{
"statusCode": 401,
"errorCode": "UNAUTHORIZED",
"message": "No autorizado",
"timestamp": "2026-07-26T18:30:00.000Z",
"path": "/v1/invoices/authorize",
"details": "<string>",
"retryable": false,
"retryAfterSeconds": 43200,
"requestId": "0f2c1a5e-1d9b-4c7a-9a55-7f1a2b3c4d5e"
}{
"statusCode": 401,
"errorCode": "UNAUTHORIZED",
"message": "No autorizado",
"timestamp": "2026-07-26T18:30:00.000Z",
"path": "/v1/invoices/authorize",
"details": "<string>",
"retryable": false,
"retryAfterSeconds": 43200,
"requestId": "0f2c1a5e-1d9b-4c7a-9a55-7f1a2b3c4d5e"
}Authorizations
API key de integración. El modo va en el prefijo: emi_test_ opera contra homologación, emi_live_ contra producción. Después, 64 hexadecimales.
Headers
El producto que origina el pedido (inmos, por ejemplo). Opcional, sólo con API key. Formato ^[a-z0-9-]{1,32}$; otro valor da 400 INVALID_INPUT. Queda en el comprobante, en el consumo y en el registro de pedidos.
Con una key sin producto es sólo atribución: no autoriza ni restringe nada. Con una key atada a un producto el pedido se etiqueta con el de la key aunque no mandes la cabecera, y si mandás otro valor la respuesta es 403 API_KEY_PRODUCTO_DISTINTO.
^[a-z0-9-]{1,32}$"inmos"
Body
A qué contribuyente se le carga. El CUIT del certificado tiene que coincidir con el suyo o la carga se rechaza: es lo que impide subir el certificado de otro por error.
"cmfa1b2c30000"
Para qué ambiente sirve este certificado. Son trámites distintos en ARCA y certificados distintos: el de homologación no funciona en producción ni al revés.
HOMOLOGACION, PRODUCCION "HOMOLOGACION"
Certificado X.509 en PEM, el que emitió ARCA para este CUIT y ambiente.
"-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----"
Clave privada en PEM. Se guarda cifrada y no se devuelve nunca, ni completa ni parcial.
"-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----"
Response
Metadatos del certificado guardado. Nunca el PEM.
Id de la credencial. Es lo que se usa para revocarla.
"cms5182zi00heurgsh49sgxwv"
A qué contribuyente pertenece.
"cms5182yf00gxurgsa7fzew8p"
Contra qué ambiente de ARCA sirve. Un certificado de homologación no funciona en producción: son trámites distintos y certificados distintos.
HOMOLOGACION, PRODUCCION "HOMOLOGACION"
ACTIVE es la que se usa para emitir. Cargar una nueva deja la anterior en SUPERSEDED; revocarla la deja en REVOKED. El historial no se borra: la trazabilidad de con qué certificado se emitió cada comprobante depende de que queden todas.
"ACTIVE"
El CUIT leído del certificado, no el declarado. Si no coincide con el del contribuyente, la carga se rechaza.
"20437136697"
El subject del certificado, tal como lo emitió ARCA. De ahí se lee el CUIT.
"CN=emissa, SERIALNUMBER=CUIT 20437136697"
Quién lo emitió. El de homologación dice Computadores Test; el de producción, no.
"CN=Computadores Test, O=AFIP"
Número de serie del certificado, en hexadecimal.
"3c9a1f2b4d5e6071"
SHA-256 del certificado. Sirve para identificarlo sin abrirlo.
"a4:1f:9c:2b:..."
Desde cuándo vale el certificado. Uno cargado antes de esta fecha no sirve para emitir todavía.
"2026-01-15T00:00:00.000Z"
Cuándo vence. Pasada esta fecha ARCA rechaza todo, así que hay que renovarlo antes: es la causa más común de que un sistema que venía facturando deje de hacerlo de un día para el otro.
"2028-01-15T00:00:00.000Z"
Días hasta notAfter. Puede ser negativo si ya venció: no se recorta a cero para que un certificado vencido se distinga de uno que vence hoy.
540
Cuándo se cargó en Emissa, en UTC.
"2026-01-20T14:05:00.000Z"
Cuándo la reemplazó otra. null mientras sea la vigente.
Cuándo se revocó a mano. null si no se revocó.