Números, llamadas y SMS
Un número de teléfono pertenece a un perfil. Todos los números reciben y hacen llamadas; los SMS se activan en los números que pueden enviarlos. Comprar, configurar y dar de baja números lo hacen los propietarios y admins (y las claves API); llamar y enviar SMS, cualquier miembro.
Todo se cobra de tu saldo: cada número al mes (de 3 € a 30 €, según el país y el tipo), las llamadas por minuto y los SMS por segmento.
Elegir y comprar un número
Sección titulada «Elegir y comprar un número»Los países, sus tipos de número y el precio al mes (en céntimos):
curl "https://api.marsial.dev/v1/phone-numbers/countries" \ -H "Authorization: Bearer $MARSIAL_API_KEY"const res = await fetch('https://api.marsial.dev/v1/phone-numbers/countries', { headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, },});const { data } = await res.json();import os, requests
res = requests.get( "https://api.marsial.dev/v1/phone-numbers/countries", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},)data = res.json()["data"]En los países que venden al momento (como EE. UU. o Reino Unido) puedes buscar un número concreto y comprarlo:
curl "https://api.marsial.dev/v1/phone-numbers/available?country=GB&numberType=mobile&sms=true" \ -H "Authorization: Bearer $MARSIAL_API_KEY"const res = await fetch('https://api.marsial.dev/v1/phone-numbers/available?country=GB&numberType=mobile&sms=true', { headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, },});const { data } = await res.json();import os, requests
res = requests.get( "https://api.marsial.dev/v1/phone-numbers/available?country=GB&numberType=mobile&sms=true", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},)data = res.json()["data"]curl -X POST "https://api.marsial.dev/v1/phone-numbers" \ -H "Authorization: Bearer $MARSIAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "profileId": "prf_8f2k4d", "country": "GB", "numberType": "mobile", "phoneNumber": "+447700900123", "sms": true }'const res = await fetch('https://api.marsial.dev/v1/phone-numbers', { method: 'POST', headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ "profileId": "prf_8f2k4d", "country": "GB", "numberType": "mobile", "phoneNumber": "+447700900123", "sms": true }),});const { data } = await res.json();import os, requests
res = requests.post( "https://api.marsial.dev/v1/phone-numbers", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"}, json={ "profileId": "prf_8f2k4d", "country": "GB", "numberType": "mobile", "phoneNumber": "+447700900123", "sms": True },)data = res.json()["data"]Sin phoneNumber, te damos uno cualquiera del país (o del prefijo de areaCode). Hace falta saldo para al menos un mes del número; sin él, la respuesta es 402. Envía idempotencyKey si puedes reintentar la petición: un reintento nunca compra un segundo número.
Países con KYC (España y la mayoría de Europa)
Sección titulada «Países con KYC (España y la mayoría de Europa)»Donde la ley obliga a identificar al titular, la compra responde 202 con status: "kyc_required". Pide el formulario del país:
curl "https://api.marsial.dev/v1/phone-numbers/kyc?country=ES" \ -H "Authorization: Bearer $MARSIAL_API_KEY"const res = await fetch('https://api.marsial.dev/v1/phone-numbers/kyc?country=ES', { headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, },});const { data } = await res.json();import os, requests
res = requests.get( "https://api.marsial.dev/v1/phone-numbers/kyc?country=ES", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},)data = res.json()["data"]Cada campo tiene un kind:
textydate: van envalues, porrequirementId(las fechas comoAAAA-MM-DD).file: súbelo antes (PDF, JPEG o PNG, hasta 4 MB, en base64) y usa eldocumentIdque devuelve. Para un DNI, las dos caras en un solo archivo.address: va enaddress.action: una verificación de identidad que el titular hace después con un enlace. Envía su nombre legal enendUserFirstNameyendUserLastName.
curl -X POST "https://api.marsial.dev/v1/phone-numbers/kyc/documents" \ -H "Authorization: Bearer $MARSIAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "filename": "dni.pdf", "contentType": "application/pdf", "data": "JVBERi0xLjQK…" }'const res = await fetch('https://api.marsial.dev/v1/phone-numbers/kyc/documents', { method: 'POST', headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ "filename": "dni.pdf", "contentType": "application/pdf", "data": "JVBERi0xLjQK…" }),});const { data } = await res.json();import os, requests
res = requests.post( "https://api.marsial.dev/v1/phone-numbers/kyc/documents", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"}, json={ "filename": "dni.pdf", "contentType": "application/pdf", "data": "JVBERi0xLjQK…" },)data = res.json()["data"]curl -X POST "https://api.marsial.dev/v1/phone-numbers/kyc" \ -H "Authorization: Bearer $MARSIAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "profileId": "prf_8f2k4d", "country": "ES", "values": { "d7e8f9a0-…": "Acme SL" }, "documents": [ { "requirementId": "e8f9a0b1-…", "documentId": "kdoc_…" } ], "address": { "requirementId": "f9a0b1c2-…", "countryCode": "ES", "streetAddress": "Gran Vía 1", "locality": "Madrid", "postalCode": "28013" }, "submissionId": "pedido-123" }'const res = await fetch('https://api.marsial.dev/v1/phone-numbers/kyc', { method: 'POST', headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ "profileId": "prf_8f2k4d", "country": "ES", "values": { "d7e8f9a0-…": "Acme SL" }, "documents": [ { "requirementId": "e8f9a0b1-…", "documentId": "kdoc_…" } ], "address": { "requirementId": "f9a0b1c2-…", "countryCode": "ES", "streetAddress": "Gran Vía 1", "locality": "Madrid", "postalCode": "28013" }, "submissionId": "pedido-123" }),});const { data } = await res.json();import os, requests
res = requests.post( "https://api.marsial.dev/v1/phone-numbers/kyc", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"}, json={ "profileId": "prf_8f2k4d", "country": "ES", "values": { "d7e8f9a0-…": "Acme SL" }, "documents": [ { "requirementId": "e8f9a0b1-…", "documentId": "kdoc_…" } ], "address": { "requirementId": "f9a0b1c2-…", "countryCode": "ES", "streetAddress": "Gran Vía 1", "locality": "Madrid", "postalCode": "28013" }, "submissionId": "pedido-123" },)data = res.json()["data"]El número queda pending_regulatory mientras la operadora revisa los datos (de 1 a 3 días laborables) y no se cobra hasta que está active. Si la operadora pide la verificación de identidad, el número tiene regulatory.idVerificationUrl: envíaselo al titular. Si rechaza los datos, el número queda regulatory_declined con el motivo en regulatory.declineReason.
Llamadas entrantes
Sección titulada «Llamadas entrantes»Decide a dónde van las llamadas y qué pasa alrededor. Solo cambian los campos que envíes:
curl -X PATCH "https://api.marsial.dev/v1/phone-numbers/num_…/calls" \ -H "Authorization: Bearer $MARSIAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "forwardTo": "tel:+34600111222", "voicemailEnabled": true, "voicemailGreeting": "Hola, has llamado a Acme. Deja tu mensaje.", "recordingEnabled": true, "transcriptionEnabled": true, "businessHoursEnabled": true, "businessHoursTimezone": "Europe/Madrid", "businessHours": [ { "day": 1, "open": "09:00", "close": "18:00" } ] }'const res = await fetch('https://api.marsial.dev/v1/phone-numbers/num_…/calls', { method: 'PATCH', headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ "forwardTo": "tel:+34600111222", "voicemailEnabled": true, "voicemailGreeting": "Hola, has llamado a Acme. Deja tu mensaje.", "recordingEnabled": true, "transcriptionEnabled": true, "businessHoursEnabled": true, "businessHoursTimezone": "Europe/Madrid", "businessHours": [ { "day": 1, "open": "09:00", "close": "18:00" } ] }),});const { data } = await res.json();import os, requests
res = requests.patch( "https://api.marsial.dev/v1/phone-numbers/num_…/calls", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"}, json={ "forwardTo": "tel:+34600111222", "voicemailEnabled": True, "voicemailGreeting": "Hola, has llamado a Acme. Deja tu mensaje.", "recordingEnabled": True, "transcriptionEnabled": True, "businessHoursEnabled": True, "businessHoursTimezone": "Europe/Madrid", "businessHours": [ { "day": 1, "open": "09:00", "close": "18:00" } ] },)data = res.json()["data"]forwardTo puede ser un teléfono (tel:+E164), una dirección SIP (sip:…) o un agente de voz con IA por WebSocket (wss://…). Sin desvío, o fuera de horario, la llamada va al buzón de voz. La grabación hace sonar antes un aviso; grabación y transcripción cuestan algo más por minuto.
Marsial llama a to desde tu número y, cuando contesta, le conecta con forwardTo: tu móvil, una dirección SIP o tu agente de voz.
curl -X POST "https://api.marsial.dev/v1/calls" \ -H "Authorization: Bearer $MARSIAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "numberId": "num_…", "to": "+34611222333", "forwardTo": "tel:+34600111222", "record": true }'const res = await fetch('https://api.marsial.dev/v1/calls', { method: 'POST', headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ "numberId": "num_…", "to": "+34611222333", "forwardTo": "tel:+34600111222", "record": true }),});const { data } = await res.json();import os, requests
res = requests.post( "https://api.marsial.dev/v1/calls", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"}, json={ "numberId": "num_…", "to": "+34611222333", "forwardTo": "tel:+34600111222", "record": True },)data = res.json()["data"]Antes puedes saber lo que costará:
curl "https://api.marsial.dev/v1/calls/estimate?to=%2B34611222333&minutes=5&numberId=num_%E2%80%A6" \ -H "Authorization: Bearer $MARSIAL_API_KEY"const res = await fetch('https://api.marsial.dev/v1/calls/estimate?to=%2B34611222333&minutes=5&numberId=num_%E2%80%A6', { headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, },});const { data } = await res.json();import os, requests
res = requests.get( "https://api.marsial.dev/v1/calls/estimate?to=%2B34611222333&minutes=5&numberId=num_%E2%80%A6", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},)data = res.json()["data"]Con numberId, la respuesta dice además si ese número puede llegar al destino (reachable). Algunos números, como los de Canadá, solo llaman y envían SMS dentro de su país: entonces reachable es false y note explica por qué.
El historial de un número, con la duración, el coste y un fragmento de la transcripción:
curl "https://api.marsial.dev/v1/phone-numbers/num_…/calls" \ -H "Authorization: Bearer $MARSIAL_API_KEY"const res = await fetch('https://api.marsial.dev/v1/phone-numbers/num_…/calls', { headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, },});const { data } = await res.json();import os, requests
res = requests.get( "https://api.marsial.dev/v1/phone-numbers/num_…/calls", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"},)data = res.json()["data"]GET /v1/calls/{id} trae la transcripción completa y GET /v1/calls/{id}/recording un enlace a la grabación que dura 15 minutos.
Activa los SMS en un número que pueda enviarlos:
curl -X PUT "https://api.marsial.dev/v1/phone-numbers/num_…/sms" \ -H "Authorization: Bearer $MARSIAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "enabled": true }'const res = await fetch('https://api.marsial.dev/v1/phone-numbers/num_…/sms', { method: 'PUT', headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ "enabled": true }),});const { data } = await res.json();import os, requests
res = requests.put( "https://api.marsial.dev/v1/phone-numbers/num_…/sms", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"}, json={ "enabled": True },)data = res.json()["data"]curl -X POST "https://api.marsial.dev/v1/sms/messages" \ -H "Authorization: Bearer $MARSIAL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "numberId": "num_…", "to": "+447700900123", "text": "Tu pedido 4821 ya está en camino" }'const res = await fetch('https://api.marsial.dev/v1/sms/messages', { method: 'POST', headers: { Authorization: `Bearer ${process.env.MARSIAL_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ "numberId": "num_…", "to": "+447700900123", "text": "Tu pedido 4821 ya está en camino" }),});const { data } = await res.json();import os, requests
res = requests.post( "https://api.marsial.dev/v1/sms/messages", headers={"Authorization": f"Bearer {os.environ['MARSIAL_API_KEY']}"}, json={ "numberId": "num_…", "to": "+447700900123", "text": "Tu pedido 4821 ya está en camino" },)data = res.json()["data"]Las respuestas llegan a la bandeja como conversaciones de la plataforma sms, y a tu webhook como message.received. Quien responde STOP no puede volver a recibir SMS de ese número (GET /v1/phone-numbers/{id}/sms/opt-outs).
En el panel y para agentes
Sección titulada «En el panel y para agentes»En el panel, la sección Teléfono tiene los números (comprar, el formulario del titular, los ajustes de llamadas, los SMS, dar de baja) y el historial de llamadas con grabaciones y transcripciones. Los agentes de IA pueden listar números, enviar SMS, llamar y leer el historial por el servidor MCP; comprar números queda para las personas.
Aún no ofrecemos traer tu número de otra operadora (portabilidad), remitentes con el nombre de tu marca ni llamar desde el navegador.
© 2026 Marsial by TWOFACES ·marsial.dev ·Panel ·soporte@twofacesco.com