Skip to main content

NEAR API

The NEAR API is a collection of language-specific SDKs that allow developers to interact with the NEAR blockchain from both frontend and backend applications. These libraries enable you to:

  • Invoke view and call functions on deployed smart contracts
  • Query on-chain data such as account state, keys, balance
  • Create and manage NEAR accounts
  • Transfer tokens, including native NEAR, Fungible Tokens, Non-Fungible Tokens
  • Sign transactions/meta-transactions/messages and broadcasting them to the network
  • Deploy smart contracts

Our API is available in multiple languages, including:

  • JavaScript/TypeScript:
    info

    The legacy near-api-js package has been replaced with a set of modular packages under the @near-js/* namespace. These new libraries offer improved developer experience, better performance, and more flexibility by allowing you to import only the functionality you need.

  • Rust: near-api-rs
  • Python: py-near
Wallet Integration

To allow users to login into your web application using a wallet you will need the wallet-selector. Read more in our Web Frontend integration article


Install​

Include the following core libraries as most applications will need them:

npm i @near-js/accounts@2 @near-js/providers@2 @near-js/signers@2
Static HTML

If you are building a site without using npm, you can include libraries directly in your HTML file through a CDN.

<script src="https://cdn.jsdelivr.net/npm/@near-js/accounts/lib/esm/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@near-js/providers/lib/esm/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@near-js/signers/lib/esm/index.min.js"></script>

Import​

You can use the API library in the browser, or in Node.js runtime.

import { Account } from "@near-js/accounts";
import { JsonRpcProvider } from "@near-js/providers";
import { KeyPairSigner } from "@near-js/signers";
Using the API in Node.js

All these examples are written for the browser, to use these examples in Node.js you should convert the project to an ES module. To do this, add the following to your package.json:


Connecting to NEAR​

To interact with the blockchain you'll need to create a NetworkConfig object.

Preset connections mainnet and testnet are available that come with standard configurations for each network.

You can also create your own custom connection.


Key Handlers: Stores & Signers​

In previous versions of the NEAR SDK, signing transactions required setting up a KeyStore to manage and retrieve keys. With the new @near-js/signers package, this process has been simplified.

You can now use the Signer abstraction, which provides a clean and extensible interface for signing. For most use cases, the KeyPairSigner implementation is the simplest option β€” it allows you to sign transactions directly using a single in-memory key pair, without needing a persistent keystore.

In browser, you typically don’t need to manage private keys manually. Instead, use Wallet Selector, the official wallet connection framework for NEAR dApps. It handles account access, key management, and user authentication across multiple wallet providers with a unified interface.

You can find a full example of browser-based signing with Wallet Selector in the official example here.

Manually managing keys in the browser (not recommended)

If your use case requires direct control over keys in the browser (e.g. building a custom signing flow), you can use the KeyPairSigner together with in-browser storage.

// Creates Signer using private key from local storage
import { KeyPairSigner } from "@near-js/signers";
import { BrowserLocalStorageKeyStore } from "@near-js/keystores-browser";

const keyStore = new BrowserLocalStorageKeyStore();
const key = await keyStore.getKey('testnet', 'user.testnet');
const signer = new KeyPairSigner(key);

RPC Failover​

RPC endpoints can occasionally become unreliable due to network issues, server downtime, or rate limiting - leading to failed requests or dropped transactions. To make your application more resilient, you can define multiple RPC endpoints and automatically fall back to the next available one when an issue occurs.

You can pass multiple individual Provider instances into the FailoverRpcProvider to improve the reliability of your application's connection.

It’s also important to note that each Provider can internally use different transport protocols (such as HTTPS or WebSocket), making the failover strategy flexible across various infrastructure setups.

import { JsonRpcProvider, FailoverPrcProvider } from "@near-js/providers";

const jsonProviders = [
new JsonRpcProvider({ url: "https://incorrect-rpc-url.com" }), // Incorrect RPC URL
new JsonRpcProvider(
{ url: "https://test.rpc.fastnear.com" }, // Valid RPC URL
{
retries: 3, // Number of retries before giving up on a request
backoff: 2, // Backoff factor for the retry delay
wait: 500, // Wait time between retries in milliseconds
} // Retry options
),
];

const provider = new FailoverRpcProvider(jsonProviders);

See full example on GitHub


Account​

Instantiate Account​

This will return an Account object for you to interact with.

You can create an Account instance using the code below. At a minimum, it requires a Provider to fetch data from the blockchain. If you also want to perform actions on behalf of the account (such as sending tokens, signing transactions, or managing keys) - you’ll need to pass a Signer as well. See the section above on how to create one using a private key, seed phrase, or JSON file.

import { JsonRpcProvider } from "@near-js/providers";
import { Account } from "@near-js/accounts";

const provider = new JsonRpcProvider({ url: "https://test.rpc.fastnear.com" });
const account = new Account("user.testnet", provider, undefined // here could've been a Signer);

Get Balance​

Gets the available and staked balance of an account in yoctoNEAR.

Once you've created an Account instance, you can use it to query the balance of a token in its smallest unit β€” whether it's the native NEAR token or any other fungible token (FT). Let's start by checking the balance of NEAR.

Pro Tip

If you need to display the balance in a human-readable format, each Token instance provides a toDecimal method that you can use to convert raw values to their standard decimal representation.

import { NEAR } from "@near-js/tokens";

const account = new Account("user.testnet", provider);

// returns yoctoNear amount as bigint
const amount = await account.getBalance(NEAR);
// converts to human-readable string like "1.234"
NEAR.toDecimal(amount);

For commonly used tokens like USDT or USDC, you can access pre-configured token definitions from the either @near-js/tokens/testnet, or @near-js/tokens/mainnet package, depending on the network. These built-in tokens make it easy to fetch balances without additional setup.

import { USDT } from "@near-js/tokens/testnet";
// import { USDT } from "@near-js/tokens/mainnet";

const account = new Account("user.testnet", provider);

// returns units as bigint
const amount = await account.getBalance(USDT);
// converts to human-readable string like "1.234"
USDT.toDecimal(amount);

If your token isn’t included in the provided collections, no problemβ€”you can manually create a Token instance for any fungible token contract by following the example below.

import { FungibleToken } from "@near-js/tokens";

const account = new Account("user.testnet", provider);

const REF = new FungibleToken("ref.fakes.testnet", {
decimals: 18,
symbol: "REF",
});

// returns units as bigint
const amount = await account.getBalance(REF);
// converts to human-readable string like "1.234"
REF.toDecimal(amount);

See full example on GitHub


Get State​

Get basic account information, such as its code hash and storage usage.

Once you've created an Account instance, you can use it to query basic on-chain information about the account, such as its code hash and current storage usage.

const account = new Account("user.testnet", provider);

await account.getState();

While the Account class represents a wallet on-chain, some use cases, like simply reading account state or contract data β€” do not require full account access. In those cases, you can skip creating an Account and use the Provider directly, as shown below.

await provider.viewAccount("user.testnet");

See full example on GitHub


Create Named Account​

To create a named account like user.testnet, you need to call the create_account function on a top-level account’s contract β€” that’s testnet on testnet or near on mainnet. Yes, on NEAR, every account can have a contract deployed to it, even top-level ones.

Keep in mind that creating a named account requires a small amount of NEAR to cover Gas fees.

When creating a new account, you’ll need to provide:

  • A public key, which will be added to the account as FullAccess key
  • An optional initial balance in NEAR (this can be zero if you don’t want to fund it right away)

Once you've created an Account instance, you can create any available named account (as long as it's not already taken). To do this, the creator account must include a Signer, since signing a transaction is required. If you're not sure how to set that up, check the section above on how to connect a signer.

const account = new Account("user.testnet", provider, signer);

// generate a keypair randomly
const keyPair = KeyPair.fromRandom("ed25519");
await account.createAccount(
"another_user.testnet",
keyPair.getPublicKey(),
// attaches 1.234 NEAR tokens that will become
// an initial balance of "another_user.testnet"
NEAR.toUnits("1.234")
);

See full example on GitHub

In some cases, you might need to create an account using a seed phrase. Here’s how you can do that:

import { generateSeedPhrase } from "near-seed-phrase";

const account = new Account("user.testnet", provider, signer);

// get public key from a randomly generated seed phrase
const { seedPhrase, publicKey, secretKey } = generateSeedPhrase();

await account.createAccount(
"another_user.testnet",
publicKey,
// attaches 1.234 NEAR tokens that will become
// an initial balance of "another_user.testnet"
NEAR.toUnits("1.234")
);

See full example on GitHub


Create Sub-Account​

Accounts on NEAR can create sub-accounts under their own namespace, which is useful for organizing accounts by purpose β€” for example, project.user.testnet.

warning

The parent account DOES NOT have any control over its sub-accounts once they are created.

Keep in mind that creating a sub-account requires a small amount of NEAR to cover Gas fees.

To create a sub-account, the parent must send a transaction to itself with the CreateAccount action. Just like when creating named accounts, you'll need to provide a public key that will be assigned to the new sub-account, along with an optional initial deposit to fund it (can be zero).

Once you've created an Account instance, you can create any sub-account (as long as it hasn't been created previously). To do this, the creator account must include a Signer, since signing a transaction is required. If you're not sure how to set that up, check the section above on how to connect a signer.

const account = new Account("user.testnet", provider, signer);

// generate a keypair randomly
const keyPair = KeyPair.fromRandom("ed25519");
await account.createAccount(
"project.user.testnet",
keyPair.getPublicKey(),
// attaches 1.234 NEAR tokens that will become
// an initial balance of "project.user.testnet"
NEAR.toUnits("1.234")
);

See full example on GitHub


Delete Account​

An account on NEAR can only delete itself β€” it CANNOT delete other accounts or its sub-accounts.

To delete an account, it must send a transaction to itself with the DeleteAccount action, including a required parameter called beneficiary_id. This is the account that will receive any remaining NEAR tokens.

info

Deleting an account DOES NOT affect its sub-accounts - they will remain active.

const account = new Account("user.testnet", provider, signer);

// account "user.testnet" gets deleted
// and remaining funds will go to account "beneficiary.testnet" (if it exists)
await account.deleteAccount("beneficiary.testnet");

See full example on GitHub

Keep in mind
  • Only NEAR tokens are transferred to the beneficiary.
  • Fungible (FTs) or Non-Fungible tokens (NFTs) held by the account ARE NOT automatically transferred. These tokens are still associated with the account, even after the account is deleted. Make sure to transfer those assets manually before deletion, or you're risking losing them permanently! Once the account is gone, those assets are effectively stuck unless the same account is recreated by anyone (not necessarily you).
  • If the beneficiary account doesn't exist, all NEAR tokens sent to it will be burned. Double-check the account ID before proceeding.

Transactions​

Send Tokens​

Accounts can transfer different types of tokens to other accounts, including the native NEAR token and NEP-141 fungible tokens.

To begin with, you’ll need the @near-js/tokens package, which provides the necessary utilities.

Once you've created an Account instance, you can transfer tokens to others. Let’s start by looking at how to transfer native NEAR tokens.

import { NEAR } from "@near-js/tokens";

const account = new Account("user.testnet", provider, signer);

// transfer 0.1 NEAR tokens to receiver.testnet
await account.transfer({
token: NEAR,
amount: NEAR.toUnits("0.1"),
receiverId: "receiver.testnet"
});

You can also use the same package to send fungible tokens (NEP-141) like USDT β€” many of the most common tokens are included out of the box and can be imported from @near-js/tokens/testnet or @near-js/tokens/mainnet, depending on the network you're using.

warning

Before receiving fungible tokens (NEP-141), the recipient must be registered on the token’s contract. If they aren’t, the transfer will fail.

If your use case involves sending tokens to users, you have two options:

  • Cover the storage cost and register them yourself

  • Ask the user to register in advance

Good news - if the account is already registered, any repeated registration attempt will automatically refund the storage deposit β€” so you’ll never pay it twice.

import { USDT } from "@near-js/tokens/testnet";

const account = new Account("user.testnet", provider, signer);

// double-check that a recipient is registered
await USDT.registerAccount({
accountIdToRegister: "receiver.testnet",
fundingAccount: account,
})

// transfer 1.23 USDT to receiver.testnet
await account.transfer({
token: USDT,
amount: USDT.toUnits("1.23"),
receiverId: "receiver.testnet"
});

For more advanced use cases, such as working with custom or less common tokens, you can create your own instance of the FungibleToken class by passing the appropriate parameters. The example below demonstrates this using the REF token.

import { FungibleToken } from "@near-js/tokens/testnet";

const account = new Account("user.testnet", provider, signer);

const REF = new FungibleToken("ref.fakes.testnet", {
decimals: 18,
symbol: "REF",
});

// double-check that a recipient is registered
await REF.registerAccount({
accountIdToRegister: "receiver.testnet",
fundingAccount: account,
})

// transfer 2.34 REF to receiver.testnet
await account.transfer({
token: REF,
amount: REF.toUnits("2.34"),
receiverId: "receiver.testnet"
});

See full example on GitHub


Call Function​

A smart contract exposes its methods, and making a function call that modifies state requires a Signer/KeyPair. You can optionally attach a NEAR deposit to the call.

Once you've created an Account instance, you can start interacting with smart contracts.

For example, let’s say there’s a Guestbook contract deployed at guestbook.near-examples.testnet, and you want to add a message to it. To do that, you’d call its add_message method.

import { NEAR } from "@near-js/tokens";

const account = new Account("user.testnet", provider, signer);

await account.callFunction({
contractId: "guestbook.near-examples.testnet",
methodName: "add_message",
args: { text: "Hello, world!" },
deposit: NEAR.toUnits('0.001'), // 0.001 NEAR
gas: "30000000000000" // 30 TGas
});

See full example on GitHub

In this function call, we’ve attached a small deposit of 0.001 NEAR to cover the storage cost of adding the message.

We’ve also attached 30 TGas to limit the amount of computational resources the method can consume.


Batch Actions​

You can send multiple actions in a batch to a single receiver. If one action fails then the entire batch of actions will be reverted.

Once you've created an Account instance, you can start sending transactions.

Let’s take a look at an example of a batched transaction that performs multiple actions in a single call - it increments a counter on a smart contract counter.near-examples.testnet twice, then transfers 0.1 NEAR tokens to this address.

Each function call to increment the counter has 10 TGas attached, which is enough for a lightweight state update. No deposit is included with these calls, since they don’t store new data β€” just update existing values.

import { NEAR } from "@near-js/tokens";

const account = new Account("user.testnet", provider, signer);

await account.signAndSendTransaction({
receiverId: "counter.near-examples.testnet",
actions: [
actionCreators.functionCall(
"increment",
{},
"10000000000000", // 10 TGas
0 // 0 NEAR
),
actionCreators.functionCall(
"increment",
{},
"10000000000000", // 10 TGas
0 // 0 NEAR
),
actionCreators.transfer(NEAR.toUnits("0.1"))
],
});

See full example on GitHub


Simultaneous Transactions​

While many other blockchains don’t support truly parallel transactions due to nonce collisions, NEAR takes a different approach. It supports access keys, and each key maintains its own independent nonce.

This means you can add multiple keys to an account and use them to sign and send transactions concurrently, without running into nonce conflicts. It’s a powerful feature for parallel execution and high-throughput use cases.

Keep in mind

Simultaneous execution means there’s no guarantee of order or success. Any transaction may fail independently.

If your use case requires strict ordering or depends on all actions succeeding together, consider using cross-contract calls instead. They allow you to chain calls with guarantees around execution flow and error handling.

Once you've created an Account instance, you can start by generating two new key pairs and adding them to the account. In our example, we’re using Full Access keys, but that’s not a requirement β€” Function Call access keys can work just as well, depending on your use case.

If you already have the keys prepared, feel free to skip this step. We're including it here to show the full setup for learning purposes.

note

Notice that we’re adding both keys in a batched transaction. Learn more about it here.

const account = new Account("user.testnet", provider, signer);

const keyPairOne = KeyPair.fromRandom("ed25519");
const keyPairTwo = KeyPair.fromRandom("ed25519");

// add two keys in a single transaction
await account.signAndSendTransaction({
receiverId: account.accountId,
actions: [
actionCreators.addKey(
keyPairOne.getPublicKey(),
actionCreators.fullAccessKey()
),
actionCreators.addKey(
keyPairTwo.getPublicKey(),
actionCreators.fullAccessKey()
),
],
waitUntil: "FINAL",
});

Now that we’ve created two separate keys, we need to create corresponding Account instances for each one. These will be used to build and send different transactions independently.

One of the transactions adds a message to the Guestbook contract, while the other increments a counter on a different contract.

const accountOne = new Account(
accountId,
provider,
new KeyPairSigner(keyPairOne)
);
const accountTwo = new Account(
accountId,
provider,
new KeyPairSigner(keyPairTwo)
);

const signedTxOne = await accountOne.createSignedTransaction(
"guestbook.near-examples.testnet",
[
actionCreators.functionCall(
"add_message",
{ text: "Hello, world!" },
"30000000000000", // 30 TGas
NEAR.toUnits("0.001") // 0.001 NEAR
),
]
);
const signedTxTwo = await accountTwo.createSignedTransaction(
"counter.near-examples.testnet",
[
actionCreators.functionCall(
"increment",
{},
"10000000000000", // 10 TGas
0 // 0 NEAR
),
]
);

The last step is to broadcast both transactions concurrently to the network using the Provider.

const sendTxOne = provider.sendTransaction(signedTxOne);
const sendTxTwo = provider.sendTransaction(signedTxTwo);

const transactionsResults = await Promise.all([sendTxOne, sendTxTwo]);

See full example on GitHub


Deploy a Contract​

On NEAR, a smart contract is deployed as a WASM file. Every account has the potential to become a contract β€” you simply need to deploy code to it.

note

Unlike many other blockchains, contracts on NEAR are mutable, meaning you have the ability to redeploy updated versions to the same account. However, if you remove all access keys from the account, it becomes impossible to sign new deploy transactions, effectively locking the contract code permanently.

Once you've created an Account instance, you can deploy a smart contract to it.

Let's read a .wasm file from your local machine and deploy its content directly to the account.

import { readFileSync } from "fs";

const account = new Account("user.testnet", provider, signer);

const wasm = readFileSync("../contracts/contract.wasm");
await account.deployContract(wasm);

See full example on GitHub


View Function​

View functions are read-only methods on a smart contract that do not modify state. You can call them without needing a Signer or KeyPair, and there’s no need to attach gas or a deposit.

Let’s look at an example using the Guestbook contract to read how many messages are currently stored.

import { JsonRpcProvider } from "@near-js/providers";

const provider = new JsonRpcProvider({ url: "https://test.rpc.fastnear.com" });

await provider.callFunction(
"guestbook.near-examples.testnet",
"total_messages",
{}
);

See full example on GitHub


Keys​

Get All Access Keys​

List all the access keys for an account.

Let’s walk through an example of how to query the list of access keys associated with an account.

import { JsonRpcProvider } from "@near-js/providers";

const provider = new JsonRpcProvider({ url: "https://test.rpc.fastnear.com" });

await provider.viewAccessKeyList("user.testnet");

See full example on GitHub


Add Full Access Key​

Each account on NEAR can have multiple access keys, each with different permissions.

A Full Access key, as the name suggests, grants complete control over the account. Anyone with this key can transfer funds, sign transactions, interact with contracts, or even delete the account entirely.

Once you've created an Account instance, you can add another Full Access key to it.

Simply generate a new key pair, then use the method below to add it to the account.

import { KeyPair } from "@near-js/crypto";

const account = new Account("user.testnet", provider, signer);

const keyPair = KeyPair.fromRandom("ed25519");

await account.addFullAccessKey(
keyPair.getPublicKey()
);

See full example on GitHub


Add Function Call Key​

Each account on NEAR can have multiple access keys, each with different permissions.

A Function Call access key is designed specifically to sign transactions that include only functionCall actions to a specific contract.

You can further restrict this key by:

  • Limiting which method names can be called
  • Capping the amount of NEAR the key can spend on transaction fees
warning

For security reasons, Function Call access keys **can only be used with function calls that attach zero NEAR tokens. Any attempt to include a deposit will result in a failed transaction.

tip

One of the most powerful use cases for this type of key is enabling seamless user experiences β€” such as allowing a user to sign actions in a browser game without being redirected to a wallet for every interaction.

Once you've created an Account instance, you can add a Functional Access key to it.

Simply generate a new key pair, then use the method below to add it to the account.

import { KeyPair } from "@near-js/crypto";
import { NEAR } from "@near-js/tokens";

const account = new Account("user.testnet", provider, signer);

const keyPair = KeyPair.fromRandom("ed25519");

await account.addFunctionCallAccessKey({
publicKey: keyPair.getPublicKey(),
contractId: "example-contract.testnet", // Contract this key is allowed to call
methodNames: ["example_method"], // Methods this key is allowed to call (optional)
allowance: NEAR.toUnits("0.25") // Gas allowance key can use to call methods (optional)
}
);

See full example on GitHub


Delete Access Key​

Each account on Near can have multiple access keys, or even none at all. An account has the ability to remove its own keys, but not the keys of any other account, including its sub-accounts.

danger

Be very careful when deleting keys. If you remove the same key used to sign the deletion, and it’s your only key, you will lose access to the account permanently. There’s no recovery unless another key was previously added. Always double-check before removing your access key.

Once you've created an Account instance, you can delete a key from it by simply providing the public key of the key pair you want to remove.

const account = new Account("user.testnet", provider, signer);

const publicKey = "ed25519:xxxxxxxx";
await account.deleteKey(publicKey);

See full example on GitHub


Validate Message Signatures​

Users can sign messages using the wallet-selector signMessage method, which returns a signature. This signature can be verified using the following code:


Utilities​

NEAR to yoctoNEAR​

Convert an amount in NEAR to an amount in yoctoNEAR.

The @near-js/tokens package provides ready-to-use instances of common tokens, making it easy to format and convert token amounts.

Let’s import the NEAR token and see how effortlessly you can convert a human-readable amount into yoctoNEAR units.

import { NEAR } from "@near-js/tokens";

// outputs as BigInt(100000000000000000000000)
NEAR.toUnits("0.1");

See full example on GitHub


Format Amount​

The @near-js/tokens package provides ready-to-use instances of common tokens, making it easy to format and convert token amounts.

Let’s import the NEAR token and see how easily you can convert values from yoctoNEAR back to a human-readable decimal amount.

import { NEAR } from "@near-js/tokens";

// outputs as "1.23"
NEAR.toDecimal("1230000000000000000000000");

See full example on GitHub


Additional resources​

Was this page helpful?