Geben Sie keine persönlichen Daten ein, etwa den Namen eines Kunden.
API-Schlüssel und programmatischer Zugriff
Erstellen, klonen und listen Sie DS-160-Formulare und erzeugen Sie Kundenerfassungslinks aus Ihrem eigenen Backend, mit API-Schlüsseln pro Arbeitsbereich, Berechtigungen und Ratenlimits.
Wenn Sie bereits ein CRM, ein Fallverwaltungssystem oder ein eigenes Portal betreiben, müssen Sie sich nicht für jedes Formular durch das Dashboard klicken. Mit API-Schlüsseln ruft Ihr Backend die v1-API von DS160.io direkt auf – es erstellt Formulare, klont sie und erzeugt Kundenerfassungslinks nach Ihrem Zeitplan. Diese Seite führt Sie von einem neuen Schlüssel zu Ihrem ersten Formular und Kundenlink und dokumentiert anschließend jeden Endpunkt.
Bevor Sie beginnen
- Ein Business-Arbeitsbereich. API-Schlüssel gibt es in Business-Arbeitsbereichen. Jeder Schlüssel ist an einen Arbeitsbereich gebunden und kann nur in diesem handeln.
- Inhaber- oder Administratorzugriff. Nur Inhaber und Administratoren des Arbeitsbereichs können Schlüssel erstellen.
- Formularguthaben. Das Erstellen oder Klonen eines Formulars über die API verbraucht ein Formularguthaben, genau wie im Dashboard.
- Ein Secrets-Manager. Das Geheimnis des Schlüssels wird nur einmal angezeigt, beim Erstellen.
- Ratenlimit: 60 Anfragen pro Minute und Schlüssel.
Schnellstart
- Erstellen Sie einen Schlüssel unter Arbeitsbereichseinstellungen → Team und Zugriff → API-Schlüssel mit den Berechtigungen, die Ihre Integration braucht, und kopieren Sie sein Geheimnis.
- Authentifizieren Sie jeden Aufruf mit einem Header
Authorization: Bearer <secret>, gegenhttps://www.ds160.io/api/v1/workspaces/<workspaceId>/…. - Erstellen Sie ein Formular mit
POST /formsund speichern Sie die zurückgegebeneformId. - Erzeugen Sie einen Kundenerfassungslink mit
POST /forms/:formId/client-linksund senden Sie dessenurlan den Antragsteller. - Fragen Sie
GET /forms/:formIdab, bis derstatusdes Formularscompletedist.
Jeder Schritt wird unten ausführlich behandelt, und das durchgängige Beispiel fügt sie zusammen.
Erwartetes Ergebnis
Ihr Backend erstellt Formulare und Kundenlinks im Arbeitsbereich, ohne dass jemand das Dashboard öffnet. Die Formulare liegen im Arbeitsbereich wie alle anderen, und die Spalte Zuletzt verwendet der Liste der API-Schlüssel zeigt, dass der Schlüssel in Gebrauch ist.
Basis-URL der API
Alle v1-Endpunkte liegen unter:
https://www.ds160.io/api/v1
Diese Dokumentation kann auf der White-Label-Domain Ihrer Agentur gehostet sein, aber API-Aufrufe gehen immer an www.ds160.io. Jedes Codebeispiel auf dieser Seite verwendet die vollständige URL, damit Sie es ohne Anpassung kopieren können.
Endpunktreferenz
/v1 ist stabil – Pfade und Feldnamen ändern sich nicht ohne eine neue Hauptversion /v2 (siehe Versionierung und Support). Die Pfade in der Tabelle unten sind relativ zum Arbeitsbereichspräfix /workspaces/:workspaceId/ angegeben; die vollständigen Anfrage- und Antwortstrukturen sind im Abschnitt des jeweiligen Endpunkts dokumentiert.
| Methode | Pfad | Berechtigung | Anfragekörper |
|---|---|---|---|
POST | /forms | forms:write | name? |
POST | /forms/:formId/clone | forms:clone | disabledSections? |
POST | /forms/:formId/client-links | client-links:write | expiresInDays, defaultLanguage, hideBranding?, lenientPhotoUpload?, requireConsent? |
GET | /forms | forms:read / forms:write | Query: limit?, cursor? |
GET | /forms/:formId | forms:read / forms:write | — |
Alle Anfragekörper und Antworten sind JSON. Die Berechtigung forms:read gewährt nur lesenden Zugriff auf Formularmetadaten; forms:write gewährt Lesen und Schreiben, sodass ein Schlüssel, der nur schreibt, den Lesezugriff ohnehin hat.
1. Einen API-Schlüssel erstellen
Öffnen Sie Arbeitsbereichseinstellungen → Team und Zugriff → API-Schlüssel und klicken Sie auf API-Schlüssel erstellen. Wählen Sie einen aussagekräftigen Namen (wir empfehlen einen Schlüssel pro Integration, z. B. Produktiv-CRM oder Staging-Webhook-Handler) und dann die Berechtigungen, die die Integration braucht:
forms:read– nur Formularmetadaten lesen (auflisten / abrufen)forms:write– Formulare erstellen; gewährt auch Lesenforms:clone– ein vorhandenes Formular in ein neues duplizierenclient-links:write– Kundenerfassungslinks erzeugen
Nur Inhaber und Administratoren des Arbeitsbereichs können Schlüssel erstellen.
Wenn Sie auf Schlüssel erstellen klicken, zeigt Ihnen die Plattform das vollständige Geheimnis einmal an. Kopieren Sie es sofort in Ihren Secrets-Manager – nachdem sich dieses Fenster geschlossen hat, werden nur noch die letzten vier Zeichen angezeigt. Wenn Sie einen Schlüssel verlieren, widerrufen Sie ihn und erstellen Sie einen neuen.
2. Authentifizieren
Alle v1-Endpunkte erwarten einen Header Authorization: Bearer <secret>.
export DS160_KEY="...the secret you just copied..."
export DS160_WORKSPACE="your-workspace-id"
curl https://www.ds160.io/api/v1/workspaces/$DS160_WORKSPACE/forms \
-H "Authorization: Bearer $DS160_KEY" Die Arbeitsbereichs-ID steht in der URL jeder Dashboard-Seite (/workspaces/<workspaceId>/...). Der Arbeitsbereich des Schlüssels wird serverseitig gebunden – ein Aufruf des Endpunkts eines anderen Arbeitsbereichs mit dem falschen Schlüssel liefert 403 Forbidden.
Tipp: Die Sprach-Tabs sind über alle Codebeispiele dieser Seite synchronisiert. Wählen Sie Ihre Sprache einmal, und der Rest der Seite folgt.
3. Ein Formular erstellen
curl -X POST https://www.ds160.io/api/v1/workspaces/$DS160_WORKSPACE/forms \
-H "Authorization: Bearer $DS160_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Smith / B1 — 2026-05" }'
# → { "formId": "65f2…" } Jeder Aufruf verbraucht ein Formularguthaben aus Ihrem Abrechnungsplan (genau wie das Erstellen eines Formulars im Dashboard). Hat Ihr Arbeitsbereich kein Guthaben mehr, liefert der Aufruf 402 Payment Required – laden Sie Guthaben auf, bevor Sie es erneut versuchen.
Das optionale Feld name legt eine lesbare Bezeichnung für das Formular fest (bis zu 200 Zeichen). Lassen Sie es weg, um einen automatisch erzeugten Namen zu erhalten – in beiden Fällen können Sie das Formular später im Dashboard umbenennen.
4. Ein vorhandenes Formular klonen
Wenn Sie ein Vorlageformular haben, das Sie häufig erneut ausgeben (etwa das J-1-Programm desselben Arbeitgebers), klonen Sie es, statt bei null anzufangen. Optional übergeben Sie disabledSections, um bestimmte Formularseiten von der Kopie auszunehmen – alles, was Sie aufführen, wird im neuen Formular durch leere Felder ersetzt, sodass der Kunde es neu ausfüllt:
curl -X POST https://www.ds160.io/api/v1/workspaces/$DS160_WORKSPACE/forms/$SOURCE_FORM_ID/clone \
-H "Authorization: Bearer $DS160_KEY" \
-H "Content-Type: application/json" \
-d '{ "disabledSections": ["spouse-info-page", "security-background-page-5"] }'
# → { "formId": "65f3…" } Das Klonen verbraucht ein Formularguthaben, genau wie das Erstellen eines neuen Formulars.
Gültige Werte für disabledSections
Übergeben Sie ein leeres Array (oder lassen Sie das Feld ganz weg), um jede Seite zu kopieren. Andernfalls verwenden Sie eine beliebige Kombination der folgenden Bezeichner – alles andere liefert 400 Bad Request.
| Bezeichner | Seite |
|---|---|
personal-info-page-1 | Personal Information - Part 1 |
personal-info-page-2 | Personal Information - Part 2 |
visa-purpose-page | Purpose of Visa |
travel-companions-page | Travel Companions |
previous-us-travel-page | Previous U.S. Travel History |
address-and-phone-page | Address and Phone Details |
passport-page | Passport Information |
contact-info-page | US Contact Information |
family-info-page | Family Information |
spouse-info-page | Spouse Information |
deceased-spouse-info-page | Deceased Spouse Information |
former-spouse-info-page | Former Spouse Information |
present-occupation-page | Current Occupation |
previous-occuptation-page | Previous Occupation |
additional-occuptation-page | Additional Occupation Details |
security-background-page-1 | Security Background - Part 1 |
security-background-page-2 | Security Background - Part 2 |
security-background-page-3 | Security Background - Part 3 |
security-background-page-4 | Security Background - Part 4 |
security-background-page-5 | Security Background - Part 5 |
student-visa-page-1 | Student Visa Details - Part 1 |
student-visa-page-2 | Student Visa Details - Part 2 |
e-visa-business-profile-page | E-Visa: Business Profile |
e-visa-foreign-parent-page | E-Visa: Foreign Parent Business |
e-visa-finance-trade-page | E-Visa: Finance and Trade |
e-visa-investment-page | E-Visa: Investment |
e-visa-personnel-page-1 | E-Visa: U.S. Personnel (1/2) |
e-visa-personnel-page-2 | E-Visa: U.S. Personnel (2/2) |
e-visa-present-position-page | E-Visa: Applicant Present Position |
e-visa-us-position-page | E-Visa: Applicant Position in U.S. |
e-visa-application-contact-page | E-Visa: Application Contact |
e-visa-us-employer-page | E-Visa: U.S. Employer |
temporary-visa-page | Temporary Visa Information |
crew-visa-page | Crew Visa Information |
preparer-of-application-page | Preparer of Application |
Nur die für die Visumkategorie des Formulars relevanten Abschnitte sind tatsächlich vorhanden; eine Seite aufzuführen, die im Quellformular nicht vorkommt, hat keine Wirkung.
5. Einen Kundenerfassungslink erzeugen
Sobald ein Formular existiert, erzeugen Sie eine URL mit Token, über die der Kunde es ausfüllen kann:
curl -X POST https://www.ds160.io/api/v1/workspaces/$DS160_WORKSPACE/forms/$FORM_ID/client-links \
-H "Authorization: Bearer $DS160_KEY" \
-H "Content-Type: application/json" \
-d '{ "expiresInDays": 7, "defaultLanguage": "en" }' Anfragekörper
| Feld | Erforderlich | Hinweise |
|---|---|---|
expiresInDays | ja | Ganzzahl 1–365. Kein Standardwert – fehlt es, wird 400 Bad Request geliefert. Das expiresAt des Links wird als now + expiresInDays berechnet, und der zugrunde liegende Token-Datensatz wird zu diesem Zeitpunkt automatisch gelöscht. |
defaultLanguage | ja | Einer der Codes unter Gültige Werte für defaultLanguage. Legt das Sprachpräfix der zurückgegebenen url fest und die Sprache, in der sich das Erfassungsformular öffnet. |
hideBranding | nein | Boolean. Bei true wird das Erfassungsformular ohne Branding angezeigt – Logo und Design des White-Labels der Agentur werden für diesen Link ausgeblendet. Standard ist false (das White-Label-Erscheinungsbild des Arbeitsbereichs wird angezeigt, falls eingerichtet). |
lenientPhotoUpload | nein | Boolean. Bei true akzeptiert der Platz für das Antragsfoto jedes Foto (JPEG/PNG/PDF bis 30 MB, wie der Passscan), und die strengen DS-160-Fotoprüfungen werden zu nicht blockierenden Warnungen, statt den Upload abzulehnen. Lassen Sie es weg, um die Agentureinstellung Upload jedes Fotos zulassen des Arbeitsbereichs zu übernehmen; übergeben Sie ausdrücklich true/false, um diese Voreinstellung für diesen Link zu überschreiben. Siehe Dokumentenablage und Fotoautomatisierung. |
requireConsent | nein | Boolean. Bei true muss der Kunde Ihrer Datenschutzerklärung zustimmen, bevor der Link etwas anzeigt oder annimmt. Lassen Sie es weg, um die Einstellung Einwilligung des Kunden des Arbeitsbereichs zu übernehmen; übergeben Sie ausdrücklich true/false, um sie für diesen Link zu überschreiben. Siehe Kunden um Einwilligung bitten. |
Beispielantwort (200 OK)
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NmMxYmQ0ZjZmNGFkNTQwMzMxNDhmYmEiLCJmb3JtSWQiOiI2NWYyYTkxMTNkZjAxYzAwMTI3YjY4MmEiLCJ3b3Jrc3BhY2VJZCI6IjY1ZjJhOTAwM2RmMDFjMDAxMjdiNjgwYSIsImV4cCI6MTc0ODA0ODI0NywiaWF0IjoxNzQ3NDQzNDQ3LCJkZWZhdWx0TGFuZ3VhZ2UiOiJlbiIsImhpZGVCcmFuZGluZyI6ZmFsc2V9.SiGNATuRe",
"url": "https://intake.your-agency.com/client-intake/65f2a9113df01c00127b682a?token=eyJhbGciOi…",
"shortUrl": "https://intake.your-agency.com/c/Ab3dE7gH9jKm?s=api",
"expiresAt": "2026-05-24T01:50:46.000Z"
}
| Feld | Hinweise |
|---|---|
token | Das JWT, das auch in url enthalten ist. Normalerweise brauchen Sie es nicht direkt – Kunden öffnen url, und der Server prüft das enthaltene Token. Der Claim jti des Tokens ist die eindeutige Link-ID; speichern Sie sie in Ihrem System, wenn Sie genau diesen Link später widerrufen möchten (siehe Einen Kundenerfassungslink widerrufen). |
url | Der teilbare Link. Verwendet Ihre eigene Domain, wenn eine für den Arbeitsbereich verifiziert und mit SSL eingerichtet ist; andernfalls ds160.io. Das Sprachpräfix im Pfad (/es, /cn, …) richtet sich nach defaultLanguage. |
shortUrl | Derselbe Link in Kurzform, /c/<code> auf demselben Host, markiert mit ?s=api, damit das erste Öffnen durch den Kunden als von der API stammend erfasst wird. Leichter per SMS oder WhatsApp zu senden. Vorhanden, wenn Kurzlinks aktiv sind (auf ds160.io sind sie es). |
expiresAt | ISO-8601-Zeitstempel. Der zugehörige Datensatz wird zu diesem Zeitpunkt automatisch gelöscht, sodass Links nach Ablauf nicht wiederverwendet werden können. |
Senden Sie die url an Ihren Kunden. Das Token in der URL dient nur diesem Zweck und läuft zu expiresAt ab – der Kunde braucht keine weitere Authentifizierung, um das Formular auszufüllen. Oder senden Sie die shortUrl, die denselben Link öffnet.
Einen Kundenerfassungslink widerrufen
Es gibt keinen v1-Endpunkt zum Widerrufen ausgegebener Kundenlinks – widerrufen Sie im Dashboard (Arbeitsbereich → Formular → Teilen → Link widerrufen). Der Widerruf wirkt sofort und dauerhaft: Die nächste Anfrage des Links liefert 401. Besteht der Verdacht auf ein Datenleck und ist niemand verfügbar, der in der Oberfläche widerrufen kann, ist die sicherste Lösung, den Link ablaufen zu lassen (begrenzen Sie expiresInDays entsprechend).
Gültige Werte für defaultLanguage
defaultLanguage bestimmt die Sprache der Kundenerfassungsoberfläche, wenn der Empfänger den Link zum ersten Mal öffnet. Verwenden Sie einen der folgenden Codes – alles andere liefert 400 Bad Request. Die Kurzcodes (en, cn, …) sind die internen Sprachkennungen von DS160.io; die Spalte BCP-47 zeigt, was wir in <html lang>, hreflang und den Intl.*-APIs ausgeben. Verwenden Sie in API-Anfragen den Kurzcode; die BCP-47-Form dient nur zur Information.
| Code | Sprache | Eigenbezeichnung | BCP-47 |
|---|---|---|---|
en | English | English | en-US |
ru | Russian | Русский | ru-RU |
ro | Romanian | Română | ro-RO |
es | Spanish | Español | es-ES |
cn | Chinese | 中文 | zh-CN |
vi | Vietnamese | Tiếng Việt | vi-VN |
hi | Hindi | हिन्दी | hi-IN |
nl | Dutch | Nederlands | nl-NL |
pt | Portuguese | Português | pt-BR |
fr | French | Français | fr-FR |
tr | Turkish | Türkçe | tr-TR |
ja | Japanese | 日本語 | ja-JP |
de | German | Deutsch | de-DE |
Behandeln Sie Kundenlinks wie Passwörter
Die url ist ein Inhaber-Zugangsnachweis – wer sie besitzt, kann das Formular bis zum Ablauf ausfüllen, ohne zweiten Faktor.
- Senden Sie sie über einen vertrauenswürdigen Kanal; veröffentlichen Sie sie nicht an Orten, an denen sie durchsickern könnte (öffentliche Chats, von Suchmaschinen indexierte Seiten, geteilte Bundles).
- Schwärzen Sie
?token=in Logs. Der Claimjtiallein kann sicher protokolliert werden. - Widerrufen Sie bei Verdacht auf ein Leck – der Widerruf wirkt sofort und dauerhaft.
expiresInDaysist eine Abwägung: kürzer = kleineres Zeitfenster für ein Leck, länger = weniger Aufwand für Neuausgaben.
6. Formulare auflisten oder abrufen
# All forms in the workspace
curl https://www.ds160.io/api/v1/workspaces/$DS160_WORKSPACE/forms \
-H "Authorization: Bearer $DS160_KEY"
# A single form by id
curl https://www.ds160.io/api/v1/workspaces/$DS160_WORKSPACE/forms/$FORM_ID \
-H "Authorization: Bearer $DS160_KEY" Diese Lese-Endpunkte akzeptieren die Berechtigung forms:read (nur Lesen) oder forms:write (die auch Lesen gewährt).
Paginierung
GET /v1/workspaces/:workspaceId/forms ist paginiert. Übergeben Sie die Query-Parameter ?limit= und ?cursor=, um durch die Ergebnisse zu blättern:
| Query-Parameter | Bedeutung |
|---|---|
limit | Höchstzahl der Formulare auf dieser Seite. Standard 50, feste Obergrenze 200. |
cursor | Formular-id aus dem nextCursor der vorherigen Seite. Bei der ersten Anfrage weglassen, um beim neuesten Formular zu beginnen. |
Jede Antwort enthält ein Feld nextCursor. Gibt es keine weiteren Seiten, ist nextCursor null. Beispiel:
{
"forms": [
{ "id": "65f2a911…", "name": "Smith / B1", "status": "in_progress", "workspaceId": "65f2a900…", "userId": "65f2a8f0…", "preferredConsulate": null, "createdAt": "2026-05-14T09:12:33.000Z", "archivedAt": null },
{ "id": "65f2a8a3…", "name": "Garcia / F1", "status": "completed", "workspaceId": "65f2a900…", "userId": "65f2a8f0…", "preferredConsulate": "MAD", "createdAt": "2026-05-13T18:01:09.000Z", "archivedAt": null }
],
"nextCursor": "65f2a8a3…"
}
Blättern Sie weiter, indem Sie bei der nächsten Anfrage ?cursor=65f2a8a3…&limit=50 senden. Formulare sind nach id absteigend sortiert, das neueste zuerst, sodass ein Cursor Ihre Leseposition festhält, auch wenn zwischen den Aufrufen neue Formulare erstellt werden – Sie sehen keine Duplikate und verpassen nichts, was zu Beginn des Blätterns existierte.
Werte für den Formular-status
Das Feld status in jeder Antwort mit Formularmetadaten hat einen dieser Werte:
| Wert | Wann er gilt |
|---|---|
not_started | Das Formular wurde erstellt (über API oder Dashboard), aber noch kein Feld wurde beantwortet. |
in_progress | Mindestens ein Feld wurde beantwortet. Die meisten Formulare verbringen den Großteil ihrer Lebensdauer in diesem Zustand. |
completed | Der Antragsteller hat die Erfassung abgeschlossen und abgesendet; die Agentur kann jetzt das DS-160-PDF herunterladen bzw. einreichen. |
archived | Das Formular wurde im Dashboard archiviert. In den Standardergebnissen der Liste nicht enthalten, sofern Sie nicht ausdrücklich nach archivierten Einträgen fragen. |
Das Übertragungsformat verwendet Unterstriche (in_progress, nicht in-progress). Ein Vergleich mit den obigen Zeichenketten in genau dieser Form funktioniert immer.
Zugriff auf personenbezogene Daten über die API
Die v1-Endpunkte für Formularmetadaten (GET /workspaces/:workspaceId/forms und GET /workspaces/:workspaceId/forms/:formId) liefern nur betriebliche Metadaten: id, name, status, workspaceId, userId, preferredConsulate, createdAt, archivedAt und beim Endpunkt für ein einzelnes Formular applicantConsent (die neueste Einwilligung des Kunden über einen Link, der sie verlangt hat: acceptedAt, withdrawnAt und noticeVersion, oder null). Sie geben die Antworten des Antragstellers nicht preis – keine Namen, Geburtsdaten, Passnummern, Reisehistorie oder sonstigen DS-160-Felder sind über /v1 erreichbar.
Ausgefüllte DS-160-PDFs und vollständige Felddaten sind nur über das Dashboard zugänglich, unter dem Eigentümer des Antragstellers mit Prüfprotokoll. Wenn Ihre Integration vom Antragsteller eingegebene Daten lesen muss, tun Sie das über Ihren eigenen Erfassungsprozess (Ihr CRM erfasst die Daten zuerst, Sie übertragen sie in DS160.io) – gehen Sie nie davon aus, dass die API sie zurückgibt.
Ratenlimits
Jeder Schlüssel ist auf 60 Anfragen pro Minute begrenzt. Jede Antwort enthält:
| Header | Bedeutung |
|---|---|
X-RateLimit-Limit | Die Obergrenze (60). |
X-RateLimit-Remaining | Verbleibende Anfragen im aktuellen Zeitfenster. |
X-RateLimit-Reset | Unix-Zeitstempel, zu dem das Zeitfenster zurückgesetzt wird. |
Überschreiten Sie das Limit, liefert die API 429 Too Many Requests mit einem Header Retry-After. Braucht Ihre Integration berechtigterweise eine höhere Obergrenze, wenden Sie sich an den Support – wir können das Limit für bestimmte Schlüssel anheben.
Idempotenz und Wiederholungen
Die v1-API unterstützt keinen Header Idempotency-Key. Konkret:
POST /formsundPOST /forms/:formId/clonesind nicht idempotent und verbrauchen bei jedem Aufruf ein Formularguthaben. Eine naive Wiederholung nach einer Netzwerk-Zeitüberschreitung erstellt ein doppeltes Formular und verbraucht ein zweites Guthaben.POST /forms/:formId/client-linksist ebenfalls nicht idempotent, verbraucht aber kein Guthaben – ein wiederholter Aufruf erstellt einfach einen zweiten Link mit eigenemjtiundexpiresAt.- Alle
GET-Endpunkte können bedenkenlos wiederholt werden.
Empfohlenes Wiederholungsmuster für Erstellen/Klonen: Wenn bei POST /forms (oder /clone) eine Zeitüberschreitung auftritt oder ein 5xx geliefert wird, wiederholen Sie nicht blind. Rufen Sie stattdessen GET /workspaces/:workspaceId/forms auf (Formulare sind das neueste zuerst sortiert) und prüfen Sie, ob in den letzten Sekunden ein Formular mit dem von Ihnen angegebenen name erstellt wurde. Falls ja, betrachten Sie den ursprünglichen Aufruf als erfolgreich und überspringen Sie die Wiederholung. Falls nicht, ist der ursprüngliche Schreibvorgang sicher nicht angekommen, und eine Wiederholung ist unbedenklich.
Möglicherweise unterstützen wir Idempotency-Key in einer künftigen Nebenversion; Integrationen sollten das einplanen, sich heute aber nicht darauf verlassen.
Einen Schlüssel widerrufen
Wenn ein Schlüssel offengelegt wurde, ausgedient hat oder einfach nicht genutzt wird, widerrufen Sie ihn unter Arbeitsbereichseinstellungen → Team und Zugriff → API-Schlüssel → Widerrufen. Der Widerruf wirkt sofort – die nächste Anfrage des Schlüssels liefert 401 Unauthorized. Widerrufene Schlüssel bleiben zu Prüfzwecken in der Liste, können aber nicht reaktiviert werden; erstellen Sie einen neuen, wenn die Integration weiterlaufen soll.
Bewährte Vorgehensweisen
- Ein Schlüssel pro Integration. So lässt er sich gezielt widerrufen, wenn ein System außer Betrieb geht, und die Spalte
Last usedim Dashboard zeigt Ihnen, welche Integrationen noch aktiv sind. - Minimale Berechtigungen. Ein Schlüssel, der nur Kundenlinks erzeugt, sollte kein
forms:clonehaben. Kleinere Berechtigungen bedeuten geringeren Schaden, falls das Geheimnis durchsickert. - Bewahren Sie Geheimnisse in einem Tresor auf. Committen Sie sie nie in die Versionsverwaltung und betten Sie sie nie in ein Frontend-Bundle ein – jeder Browser-Tab würde sie offenlegen.
- Rotieren Sie regelmäßig. Erstellen Sie einen neuen Schlüssel, stellen Sie die Integration um und widerrufen Sie dann den alten. Das Dashboard zeigt, wann ein Schlüssel zuletzt verwendet wurde, sodass Sie die Umstellung vor dem Widerruf bestätigen können.
Fehler
Alle Antworten außerhalb von 2xx haben dieselbe JSON-Struktur:
{ "error": "human-readable message" }
Der Wert von error ist eine Zeichenkette. Bei 400 Bad Request aus der Schemaprüfung ist es ein serialisiertes JSON-Array, das jede verletzte Bedingung beschreibt; in allen anderen Fällen ist es eine kurze Meldung, die Sie direkt anzeigen oder protokollieren können.
| Status | Wann er auftritt | Beispielkörper |
|---|---|---|
400 | Anfragekörper oder Pfadparameter haben die Prüfung nicht bestanden (fehlendes Pflichtfeld, Wert außerhalb des Bereichs, unbekannter Enum-Wert usw.). | { "error": "[{\"keyword\":\"required\",\"params\":{\"missingProperty\":\"expiresInDays\"}}]" } |
401 | Fehlender Header Authorization, fehlerhaftes Bearer-Token, das Geheimnis passt zu keinem Schlüssel, oder der Schlüssel wurde widerrufen. | { "error": "Missing API key" } · { "error": "Invalid API key" } · { "error": "API key revoked" } |
402 | Der Arbeitsbereich hat kein Formularguthaben mehr. Nur beim Erstellen/Klonen. Laden Sie Guthaben für den Arbeitsbereich auf und versuchen Sie es erneut. | { "error": "Insufficient credits. You have used 10 of 10 available credits." } |
403 | Dem Schlüssel fehlt die erforderliche Berechtigung, oder die :workspaceId im Pfad stimmt nicht mit dem gebundenen Arbeitsbereich des Schlüssels überein. | { "error": "Missing required scope: forms:write" } · { "error": "API key does not match workspace" } |
404 | Formular nicht gefunden, oder das Formular existiert, liegt aber in einem anderen Arbeitsbereich als der Schlüssel. (Als 404 statt 403 geliefert, um die Existenz nicht arbeitsbereichsübergreifend preiszugeben.) | { "error": "Form not found" } |
429 | Ratenlimit pro Schlüssel überschritten (standardmäßig 60 Anfragen/Min.). Warten Sie den Wert von Retry-After (Sekunden) ab und versuchen Sie es erneut. | { "error": "Rate limit exceeded" } |
5xx | Vorübergehender Serverfehler. GET-Anfragen können bedenkenlos wiederholt werden; bei schreibenden Endpunkten lesen Sie vor einer Wiederholung Idempotenz und Wiederholungen. | — |
Durchgängiges Beispiel
Ein vollständiger Erfassungsablauf – ein Formular erstellen, einen Kundenlink erzeugen, ihn senden und auf den Abschluss prüfen – mit curl. Echte Integrationen verwenden ihren eigenen HTTP-Client; die Struktur ist in jeder Sprache dieselbe.
# 0. credentials (set once)
export DS160_KEY="..."
export DS160_WORKSPACE="65f2a900..."
# 1. Create a form. Capture the formId from the response.
FORM_ID=$(curl -s -X POST \
https://www.ds160.io/api/v1/workspaces/$DS160_WORKSPACE/forms \
-H "Authorization: Bearer $DS160_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "Smith / B1 — 2026-05" }' \
| jq -r .formId)
# 2. Mint a client intake link valid for 14 days.
LINK_JSON=$(curl -s -X POST \
https://www.ds160.io/api/v1/workspaces/$DS160_WORKSPACE/forms/$FORM_ID/client-links \
-H "Authorization: Bearer $DS160_KEY" \
-H "Content-Type: application/json" \
-d '{ "expiresInDays": 14, "defaultLanguage": "en" }')
CLIENT_URL=$(echo "$LINK_JSON" | jq -r .url)
# 3. Send $CLIENT_URL to the applicant through your usual channel
# (email, secure portal, etc.). The applicant fills in the form.
# 4. Poll for completion. Status transitions:
# not_started → in_progress → completed
curl -s https://www.ds160.io/api/v1/workspaces/$DS160_WORKSPACE/forms/$FORM_ID \
-H "Authorization: Bearer $DS160_KEY" \
| jq .status
# → "completed" when the applicant has finished
# 5. Download the DS-160 PDF from the dashboard
# (no v1 endpoint for this today).
Einige Hinweise zu diesem Ablauf:
- Abfrageintervall: alle 5–15 Minuten genügt völlig. Mit einer Obergrenze von 60 Anfragen/Min. kann ein einzelner Schlüssel problemlos Tausende laufender Formulare abfragen.
- Webhooks sind noch nicht verfügbar. Wenn Sie Push-Benachrichtigungen beim Abschluss brauchen, behalten Sie diese Seite im Blick oder wenden Sie sich an den Support – sie stehen auf der Roadmap.
- Schritt 5 (das ausgefüllte PDF herunterladen) erfordert heute eine Dashboard-Sitzung. Die v1-API gibt Antworten des Antragstellers bewusst nicht preis – siehe Zugriff auf personenbezogene Daten über die API.
Versionierung und Support
Stabilität. /v1 ist die stabile API-Oberfläche. Innerhalb von /v1 fügen wir neue optionale Felder, neue Endpunkte und neue Enum-Werte hinzu, ohne die Hauptversion zu erhöhen, aber wir benennen keine bestehenden Felder um, entfernen sie nicht und ändern nicht ihren Typ. Sollte je eine inkompatible Änderung nötig sein, erscheint sie unter /v2, und /v1 funktioniert daneben mindestens 12 Monate weiter.
Abwärtskompatible Ergänzungen, die Sie einplanen sollten:
- Mit der Zeit kommen neue optionale Anfragefelder hinzu. Bestehende Anfragen, die sie nicht senden, funktionieren weiter.
- Es können neue Antwortfelder hinzukommen. Behandeln Sie unbekannte Felder als ignorierbar – brechen Sie nicht ab, wenn ein künftiges Feld auftaucht.
- Es werden neue Enum-Werte für
status,defaultLanguageunddisabledSectionshinzukommen. Stürzen Sie bei unbekannten Werten nicht ab; protokollieren Sie sie und fahren Sie fort.
Support:
- Höhere Ratenlimits, eigene Domains, früher Zugang zu Webhooks und Fragen zur Integration: Wenden Sie sich an Ihren Account Manager oder an support@ds160.io.
- Fehlermeldungen zur v1-API: dieselbe Adresse. Jede Antwort enthält einen Header
x-request-id– geben Sie ihn in Ihrer Meldung an, damit wir den genauen Aufruf in unseren Logs finden.
Fehlerbehebung
Die error-Meldung jedes Fehlers und was zu tun ist:
| Problem | Was zu tun ist |
|---|---|
401 Missing API key | Senden Sie bei jedem Aufruf den Header Authorization: Bearer <secret>. |
401 Invalid API key | Das Geheimnis passt zu keinem Schlüssel. Prüfen Sie, ob es vollständig kopiert wurde. Das Geheimnis wird nur einmal angezeigt: Ist es verloren, widerrufen Sie den Schlüssel und erstellen Sie einen neuen. |
401 API key revoked | Ein widerrufener Schlüssel kann nicht reaktiviert werden. Erstellen Sie einen neuen Schlüssel und stellen Sie die Integration darauf um. |
403 Missing required scope: … | Dem Schlüssel fehlt die genannte Berechtigung. Erstellen Sie einen Schlüssel mit dieser Berechtigung, stellen Sie die Integration darauf um und widerrufen Sie dann den alten Schlüssel. |
403 API key does not match workspace | Die :workspaceId im Pfad muss der Arbeitsbereich des Schlüssels sein. Sie steht in der URL jeder Dashboard-Seite (/workspaces/<workspaceId>/...). |
402 beim Erstellen oder Klonen | Der Arbeitsbereich hat kein Formularguthaben mehr oder ist wegen einer unbezahlten Rechnung pausiert. Laden Sie Guthaben für den Arbeitsbereich auf oder bezahlen Sie die in der Meldung verlinkte Rechnung, und versuchen Sie es dann erneut. |
404 Form not found | Prüfen Sie die Formular-ID. Ein Formular in einem anderen Arbeitsbereich als dem des Schlüssels wird ebenfalls als nicht gefunden gemeldet. |
400 mit einer Liste von Bedingungen | Anfragekörper oder Pfad haben die Prüfung nicht bestanden. Jeder Eintrag nennt das Feld und die verletzte Regel, zum Beispiel ein fehlendes expiresInDays. |
429 Rate limit exceeded | Warten Sie die Anzahl Sekunden in Retry-After ab und versuchen Sie es dann erneut. Braucht Ihre Integration ein höheres Limit, wenden Sie sich an den Support. |
Zeitüberschreitung beim Erstellen oder Klonen, oder ein 5xx | Wiederholen Sie nicht blind: Listen Sie die Formulare auf und prüfen Sie, ob gerade ein Formular mit Ihrem name erstellt wurde. Wiederholen Sie nur, wenn nicht. |