Skip to main content
Base URLs:
  • Production: https://api.machines.cash/partner/v1
  • Sandbox: https://dev-api.machines.cash/partner/v1
Get API access: email [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.
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
}
'
{
  "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": []
}
Use this session token for steps 3-9. Call POST /users/resolve.
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"
}
'
{
  "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.
curl --request GET \
  --url https://api.machines.cash/partner/v1/kyc/values \
  --header 'Authorization: Bearer <SESSION_TOKEN>'
{
  "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.
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"
}
'
{
  "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 the completionLink (or externalVerificationLink) in a new window so the user can finish verification.

6. Poll KYC status

Call GET /kyc/status until the status is approved. Status meanings are listed in KYC status reference.
curl --request GET \
  --url https://api.machines.cash/partner/v1/kyc/status \
  --header 'Authorization: Bearer <SESSION_TOKEN>'
{
  "ok": true,
  "data": {
    "status": "approved",
    "reason": "",
    "completionLink": null,
    "externalVerificationLink": null,
    "isActive": null,
    "isTermsOfServiceAccepted": false
  },
  "summary": "kyc status",
  "errors": []
}
Call GET /agreements to fetch agreement text, then POST /agreements to accept.
curl --request GET \
  --url https://api.machines.cash/partner/v1/agreements \
  --header 'Authorization: Bearer <SESSION_TOKEN>'
{
  "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": []
}
curl --request POST \
  --url https://api.machines.cash/partner/v1/agreements \
  --header 'Authorization: Bearer <SESSION_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "accepted": true
}
'
{
  "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.
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"
}
'
{
  "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.
curl --request GET \
  --url https://api.machines.cash/partner/v1/deposits/cmkh7ocks0001s601xm7v8ljp \
  --header 'Authorization: Bearer <SESSION_TOKEN>'
{
  "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": []
}
Fetch balances with GET /balances:
curl --request GET \
  --url https://api.machines.cash/partner/v1/balances \
  --header 'Authorization: Bearer <SESSION_TOKEN>'
{
  "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.
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
}
'
{
  "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 as encryptedName when creating the card.
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"
}
'
{
  "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.
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"
  }
}
'
{
  "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.
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 '{}'
{
  "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).
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>"
}
'
{
  "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 the secretKey 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.
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));