- Production:
https://api.machines.cash/partner/v1 - Sandbox:
https://dev-api.machines.cash/partner/v1
[email protected] or DM @erturkarda on Telegram.
All requests are JSON. Use X-Partner-Key for steps 1-2. Use Authorization: Bearer <SESSION_TOKEN> for the rest.
1. Create a session token
Call POST /sessions.Copy
curl --request POST \
--url https://api.machines.cash/partner/v1/sessions \
--header 'Content-Type: application/json' \
--header 'X-Partner-Key: <PARTNER_API_KEY>' \
--data '
{
"userId": "eeetest",
"scopes": [
"kyc.read",
"kyc.write"
],
"walletAddress": "0x462B1eD1B62F4c282c0EA342BCefcF8f9919226E",
"ttlSeconds": 9001
}
'
Copy
{
"ok": true,
"data": {
"sessionToken": "<SESSION_TOKEN>",
"sessionId": "<SESSION_ID>",
"userId": "eeetest",
"expiresAt": "2026-01-16T16:47:52.000Z",
"scopes": [
"kyc.read",
"kyc.write"
]
},
"summary": "session created",
"errors": []
}
2. Create or link the user
Call POST /users/resolve.Copy
curl --request POST \
--url https://api.machines.cash/partner/v1/users/resolve \
--header 'Content-Type: application/json' \
--header 'X-Partner-Key: <PARTNER_API_KEY>' \
--data '
{
"userId": "eeetest",
"walletAddress": "0x462B1eD1B62F4c282c0EA342BCefcF8f9919226E",
"walletLabel": "Main Wallet"
}
'
Copy
{
"ok": true,
"data": {
"userId": "eeetest",
"walletAddress": "0x462b1ed1b62f4c282c0ea342bcefcf8f9919226e",
"kycStatus": "not_submitted",
"createdAt": "2026-01-16T14:17:51.298Z"
},
"summary": "user linked; kyc not started",
"errors": []
}
3. Get KYC field requirements and values
Call GET /kyc/values to build your KYC form. The full occupation list is also available at /kyc-values.Copy
curl --request GET \
--url https://api.machines.cash/partner/v1/kyc/values \
--header 'Authorization: Bearer <SESSION_TOKEN>'
Copy
{
"ok": true,
"data": {
"fields": [
{
"name": "firstName",
"required": true,
"type": "string",
"maxLength": 50,
"description": "Given name."
},
{
"name": "lastName",
"required": true,
"type": "string",
"maxLength": 50,
"description": "Family name."
},
{
"name": "birthDate",
"required": true,
"type": "date",
"description": "YYYY-MM-DD (e.g., 1990-01-01)."
},
{
"name": "nationalId",
"required": true,
"type": "string",
"regex": "^[0-9A-Za-z-]+$",
"description": "Government ID number. Letters, numbers, and dashes only."
},
{
"name": "countryOfIssue",
"required": true,
"type": "string",
"minLength": 2,
"maxLength": 2,
"description": "ISO-3166-1 alpha-2 (e.g., US)."
},
{
"name": "email",
"required": true,
"type": "string",
"description": "Valid email address."
},
{
"name": "address",
"required": true,
"type": "object",
"description": "Object with line1, line2, city, region, postalCode, countryCode."
},
{
"name": "phoneCountryCode",
"required": false,
"type": "string",
"maxLength": 3,
"description": "Country calling code digits only (e.g., 1)."
},
{
"name": "phoneNumber",
"required": false,
"type": "string",
"maxLength": 15,
"description": "Phone number digits only; include area code."
},
{
"name": "occupation",
"required": true,
"type": "string",
"description": "SOC occupation code (e.g., 49-3023). Use /kyc/values for the list."
},
{
"name": "annualSalary",
"required": true,
"type": "string",
"enum": [
"<40k",
"50k–99k",
"100k–149k",
"150k+"
],
"description": "Choose a salary range."
},
{
"name": "accountPurpose",
"required": true,
"type": "string",
"enum": [
"everyday spend",
"subscriptions",
"business expenses",
"testing",
"other"
],
"description": "How the account will be used."
},
{
"name": "expectedMonthlyVolume",
"required": true,
"type": "string",
"enum": [
"under $1k",
"$1k–$5k",
"$5k–$20k",
"$20k+"
],
"description": "Choose a monthly volume range."
}
],
"occupations": [
{ "code": "11-1021", "label": "General and Operations Managers" },
{ "code": "11-2011", "label": "Advertising and Promotions Managers" },
{ "code": "11-3031", "label": "Financial Managers" },
{ "code": "11-9021", "label": "Construction Managers" },
{ "code": "11-9041", "label": "Architectural and Engineering Managers" },
{ "code": "11-9071", "label": "Gaming Managers" },
{ "code": "11-9141", "label": "Property, Real Estate, and Community Association Managers" },
{ "code": "13-1041", "label": "Compliance Officers" },
{ "code": "13-2011", "label": "Accountants and Auditors" },
{ "code": "13-2051", "label": "Financial Analysts" },
{ "code": "13-2052", "label": "Personal Financial Advisors" },
{ "code": "13-2082", "label": "Tax Preparers" },
{ "code": "15-1121", "label": "Computer Systems Analysts" },
{ "code": "15-1131", "label": "Computer Programmers" },
{ "code": "15-1132", "label": "Software Developers, Applications" },
{ "code": "15-1133", "label": "Software Developers, Systems Software" },
{ "code": "15-1141", "label": "Database Administrators" },
{ "code": "15-1142", "label": "Information Security Analysts" },
{ "code": "15-1143", "label": "Computer Network Architects" },
{ "code": "15-1151", "label": "Computer User Support Specialists" },
{ "code": "17-2051", "label": "Civil Engineers" },
{ "code": "17-2071", "label": "Electrical Engineers" },
{ "code": "17-2141", "label": "Mechanical Engineers" },
{ "code": "19-3011", "label": "Economists" },
{ "code": "23-1011", "label": "Lawyers" },
{ "code": "23-2011", "label": "Paralegals and Legal Assistants" },
{ "code": "25-2021", "label": "Elementary School Teachers" },
{ "code": "27-1024", "label": "Graphic Designers" },
{ "code": "27-2012", "label": "Producers and Directors" },
{ "code": "29-1141", "label": "Registered Nurses" },
{ "code": "29-1062", "label": "Family and General Practitioners" },
{ "code": "29-1067", "label": "Surgeons" },
{ "code": "31-9097", "label": "Phlebotomists" },
{ "code": "33-3021", "label": "Detectives and Criminal Investigators" },
{ "code": "35-1011", "label": "Chefs and Head Cooks" },
{ "code": "41-9011", "label": "Demonstrators and Product Promoters" },
{ "code": "41-9021", "label": "Real Estate Brokers" },
{ "code": "43-3071", "label": "Tellers" },
{ "code": "47-1011", "label": "Construction Supervisors" },
{ "code": "47-2061", "label": "Construction Laborers" },
{ "code": "49-3023", "label": "Automotive Service Technicians and Mechanics" },
{ "code": "51-4121", "label": "Welders, Cutters, Solderers, and Brazers" },
{ "code": "53-3032", "label": "Heavy and Tractor-Trailer Truck Drivers" },
{ "code": "53-3041", "label": "Taxi Drivers and Chauffeurs" },
{ "code": "SELFEMP", "label": "Self-Employed" },
{ "code": "UNEMPLO", "label": "Unemployed" },
{ "code": "RETIRED", "label": "Retired" },
{ "code": "OTHERXX", "label": "Other" }
],
"annualSalary": ["<40k", "50k–99k", "100k–149k", "150k+"],
"expectedMonthlyVolume": ["under $1k", "$1k–$5k", "$5k–$20k", "$20k+"],
"accountPurpose": ["everyday spend", "subscriptions", "business expenses", "testing", "other"]
},
"summary": "kyc values",
"errors": []
}
4. Submit KYC
Call POST /kyc/applications.Copy
curl --request POST \
--url https://api.machines.cash/partner/v1/kyc/applications \
--header 'Authorization: Bearer <SESSION_TOKEN>' \
--header 'Content-Type: application/json' \
--data '
{
"firstName": "John",
"lastName": "smith",
"birthDate": "1990-01-01",
"nationalId": "123456789",
"countryOfIssue": "US",
"email": "[email protected]",
"address": {
"line1": "123 Main St",
"city": "New York",
"region": "NY",
"postalCode": "10001",
"countryCode": "US",
"line2": "Unit 4"
},
"occupation": "49-3023",
"annualSalary": "<40k",
"accountPurpose": "everyday spend",
"expectedMonthlyVolume": "under $1k",
"phoneCountryCode": "1",
"phoneNumber": "4155551234"
}
'
Copy
{
"ok": true,
"data": {
"status": "needs_verification",
"reason": "",
"completionLink": {
"url": "https://kyc.machines.cash/verify",
"params": {
"userId": "18717ac1-c375-4ff6-972d-79dd702b7d44",
"signature": "<KYC_SIGNATURE>"
}
},
"externalVerificationLink": {
"url": "https://kyc.machines.cash/verify",
"params": {
"userId": "18717ac1-c375-4ff6-972d-79dd702b7d44",
"signature": "<KYC_SIGNATURE>"
}
},
"isActive": true,
"isTermsOfServiceAccepted": false
},
"summary": "kyc submitted",
"errors": []
}
5. Complete verification
Open thecompletionLink (or externalVerificationLink) in a new window so the user can finish verification.
6. Poll KYC status
Call GET /kyc/status until the status isapproved. Status meanings are listed in KYC status reference.
Copy
curl --request GET \
--url https://api.machines.cash/partner/v1/kyc/status \
--header 'Authorization: Bearer <SESSION_TOKEN>'
Copy
{
"ok": true,
"data": {
"status": "approved",
"reason": "",
"completionLink": null,
"externalVerificationLink": null,
"isActive": null,
"isTermsOfServiceAccepted": false
},
"summary": "kyc status",
"errors": []
}
7. Show agreements and collect consent
Call GET /agreements to fetch agreement text, then POST /agreements to accept.Copy
curl --request GET \
--url https://api.machines.cash/partner/v1/agreements \
--header 'Authorization: Bearer <SESSION_TOKEN>'
Copy
{
"ok": true,
"data": {
"agreements": [
{
"id": "esignConsent",
"text": "I accept the E-Sign Consent",
"links": [
{ "label": "E-Sign Consent", "url": "https://machines.cash/e-sign" }
]
},
{
"id": "accountOpeningPrivacyNotice",
"text": "I accept the Account Opening Privacy Notice",
"links": [
{ "label": "Account Opening Privacy Notice", "url": "https://machines.cash/account-opening-privacy" }
]
},
{
"id": "cardTermsAndIssuerPrivacyPolicy",
"text": "I accept the Machines Card Terms and the Issuer Privacy Policy",
"links": [
{ "label": "Machines Card Terms", "url": "https://machines.cash/machines-card-terms" },
{ "label": "Issuer Privacy Policy", "url": "https://www.third-national.com/privacypolicy" }
]
},
{
"id": "informationCertification",
"text": "I certify that the information I have provided is accurate and that I will abide by all the rules and requirements related to my Machines Spend Card.",
"links": []
},
{
"id": "solicitationAcknowledgement",
"text": "I acknowledge that applying for the Machines Spend Card does not constitute unauthorized solicitation.",
"links": []
}
],
"accepted": false,
"acceptedAt": null
},
"summary": "agreements",
"errors": []
}
Copy
curl --request POST \
--url https://api.machines.cash/partner/v1/agreements \
--header 'Authorization: Bearer <SESSION_TOKEN>' \
--header 'Content-Type: application/json' \
--data '
{
"accepted": true
}
'
Copy
{
"ok": true,
"data": {
"agreements": [
{
"id": "esignConsent",
"text": "I accept the E-Sign Consent",
"links": [
{ "label": "E-Sign Consent", "url": "https://machines.cash/e-sign" }
]
},
{
"id": "accountOpeningPrivacyNotice",
"text": "I accept the Account Opening Privacy Notice",
"links": [
{ "label": "Account Opening Privacy Notice", "url": "https://machines.cash/account-opening-privacy" }
]
},
{
"id": "cardTermsAndIssuerPrivacyPolicy",
"text": "I accept the Machines Card Terms and the Issuer Privacy Policy",
"links": [
{ "label": "Machines Card Terms", "url": "https://machines.cash/machines-card-terms" },
{ "label": "Issuer Privacy Policy", "url": "https://www.third-national.com/privacypolicy" }
]
},
{
"id": "informationCertification",
"text": "I certify that the information I have provided is accurate and that I will abide by all the rules and requirements related to my Machines Spend Card.",
"links": []
},
{
"id": "solicitationAcknowledgement",
"text": "I acknowledge that applying for the Machines Spend Card does not constitute unauthorized solicitation.",
"links": []
}
],
"accepted": true,
"acceptedAt": "2026-01-16T16:22:48.186Z"
},
"summary": "agreements accepted",
"errors": []
}
8. Create a deposit address
Call POST /deposits. We currently support USDC on Base during beta.Copy
curl --request POST \
--url https://api.machines.cash/partner/v1/deposits \
--header 'Authorization: Bearer <SESSION_TOKEN>' \
--header 'Content-Type: application/json' \
--data '
{
"currency": "usdc",
"network": "base"
}
'
Copy
{
"ok": true,
"data": {
"deposit": {
"id": "cmkh7ocks0001s601xm7v8ljp",
"contractId": "2729a818-64ef-422f-a8e6-6f2785703cd3",
"changeNowId": "ff65698c01121a",
"fromCurrency": "usdc",
"fromNetwork": "base",
"depositAddress": "0x969A9c0fDe4aD175A6539Ac7Bb6aB0bC3d7e66d3",
"chainId": 8453,
"minAmount": 1,
"maxAmount": null,
"status": "awaitingDeposit",
"createdAt": "2026-01-16T18:27:55.180Z",
"updatedAt": "2026-01-16T18:27:55.180Z"
}
},
"summary": "deposit created",
"errors": []
}
9. Check deposit status and balances
Use GET /deposits/ to check status. Balances update ~3 minutes after a successful deposit.Copy
curl --request GET \
--url https://api.machines.cash/partner/v1/deposits/cmkh7ocks0001s601xm7v8ljp \
--header 'Authorization: Bearer <SESSION_TOKEN>'
Copy
{
"ok": true,
"data": {
"deposit": {
"id": "cmkh7ocks0001s601xm7v8ljp",
"contractId": "2729a818-64ef-422f-a8e6-6f2785703cd3",
"changeNowId": "ff65698c01121a",
"fromCurrency": "usdc",
"fromNetwork": "base",
"depositAddress": "0x969A9c0fDe4aD175A6539Ac7Bb6aB0bC3d7e66d3",
"chainId": 8453,
"minAmount": 1,
"maxAmount": null,
"status": "awaitingDeposit",
"createdAt": "2026-01-16T18:27:55.180Z",
"updatedAt": "2026-01-16T18:30:55.180Z"
}
},
"summary": "deposit",
"errors": []
}
Copy
curl --request GET \
--url https://api.machines.cash/partner/v1/balances \
--header 'Authorization: Bearer <SESSION_TOKEN>'
Copy
{
"ok": true,
"data": {
"balances": {
"creditLimit": 3000,
"pendingCharges": 0,
"postedCharges": 0,
"balanceDue": 0,
"spendingPower": 3000
}
},
"summary": "balances",
"errors": []
}
10. Create a card session token
For card creation, labels, and card secrets, mint a new session token with POST /sessions. Use this token for steps 11-14.Copy
curl --request POST \
--url https://api.machines.cash/partner/v1/sessions \
--header 'Content-Type: application/json' \
--header 'X-Partner-Key: <PARTNER_API_KEY>' \
--data '
{
"userId": "eeetest",
"scopes": [
"crypto.read",
"crypto.write",
"cards.secrets.read",
"cards.write",
"cards.read"
],
"walletAddress": "0x462B1eD1B62F4c282c0EA342BCefcF8f9919226E",
"ttlSeconds": 9001
}
'
Copy
{
"ok": true,
"data": {
"sessionToken": "<SESSION_TOKEN>",
"sessionId": "<SESSION_ID>",
"userId": "eeetest",
"expiresAt": "2026-01-17T16:32:47.000Z",
"scopes": [
"crypto.read",
"crypto.write",
"cards.secrets.read",
"cards.write",
"cards.read"
]
},
"summary": "session created",
"errors": []
}
11. Encrypt a card label (optional)
If you want to display a card label to your users, encrypt it with POST /encryption/encrypt and pass it asencryptedName when creating the card.
Copy
curl --request POST \
--url https://api.machines.cash/partner/v1/encryption/encrypt \
--header 'Authorization: Bearer <CARD_SESSION_TOKEN>' \
--header 'Content-Type: application/json' \
--data '
{
"value": "Marketing Spend"
}
'
Copy
{
"ok": true,
"data": {
"value": {
"v": 1,
"iv": "Qz4f2m7Hk1P9x0ab",
"ct": "Hdbb2yT2F4xWZL5m5bJX3eJb4n8wVhjPzqLw2h7i"
}
},
"summary": "encrypted",
"errors": []
}
12. Create a card
Call POST /cards with an optional card label and limit.Copy
curl --request POST \
--url https://api.machines.cash/partner/v1/cards \
--header 'Authorization: Bearer <CARD_SESSION_TOKEN>' \
--header 'Content-Type: application/json' \
--data '
{
"encryptedName": {
"v": 1,
"iv": "Qz4f2m7Hk1P9x0ab",
"ct": "Hdbb2yT2F4xWZL5m5bJX3eJb4n8wVhjPzqLw2h7i"
},
"limit": {
"amountCents": 2500,
"frequency": "perAuthorization"
}
}
'
Copy
{
"ok": true,
"data": {
"cardId": "9f970d1a-fd8e-41ac-a6fd-5993417942e3",
"status": "active",
"brand": "VISA",
"last4": "4242",
"expirationMonth": 12,
"expirationYear": 2029
},
"summary": "card created",
"errors": []
}
13. Create a card secrets session
Call POST /cards/secrets/session.Copy
curl --request POST \
--url https://api.machines.cash/partner/v1/cards/secrets/session \
--header 'Authorization: Bearer <CARD_SESSION_TOKEN>' \
--header 'Content-Type: application/json' \
--data '{}'
Copy
{
"ok": true,
"data": {
"sessionId": "<CARD_SECRETS_SESSION_ID>",
"secretKey": "<CARD_SECRETS_SECRET_KEY>"
},
"summary": "card secrets session",
"errors": []
}
14. Fetch card secrets
Call POST /cards//secrets with the session id from the previous step. This returns encrypted PAN and CVC only (not the card label).Copy
curl --request POST \
--url https://api.machines.cash/partner/v1/cards/9f970d1a-fd8e-41ac-a6fd-5993417942e3/secrets \
--header 'Authorization: Bearer <CARD_SESSION_TOKEN>' \
--header 'Content-Type: application/json' \
--data '
{
"sessionId": "<CARD_SECRETS_SESSION_ID>"
}
'
Copy
{
"ok": true,
"data": {
"encryptedPan": {
"iv": "TTPaDqoFqscIQriDfJ/Efg==",
"data": "Mo3n8fEUM0yZpaopmfQvaIPmSy8YgEZpyGLbU7vqqvM="
},
"encryptedCvc": {
"iv": "QG5uolhSt7b9MseCnH7ljA==",
"data": "ruOb8ZRovieujsg34n0EhGWb5w=="
}
},
"summary": "card secrets",
"errors": []
}
15. Decrypt PAN and CVC (server-side)
Use thesecretKey from Step 13 to decrypt the card number and CVC. This step is typically handled server-side (or by an agent) and never exposed to the browser.
Copy
import { createDecipheriv } from "crypto";
function decrypt({ iv, data }, keyHex) {
const key = Buffer.from(keyHex, "hex");
const payload = Buffer.from(data, "base64");
const tag = payload.subarray(payload.length - 16);
const ciphertext = payload.subarray(0, payload.length - 16);
const decipher = createDecipheriv("aes-128-gcm", key, Buffer.from(iv, "base64"));
decipher.setAuthTag(tag);
return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
}
console.log("PAN:", decrypt(encryptedPan, secretKey));
console.log("CVC:", decrypt(encryptedCvc, secretKey));